Як створити своп для Azure Ubuntu VM?


9

Я прочитав досить багато публікацій з цього приводу, але все ще не впевнений у правильному підході, припускаючи:

  1. У мене є за замовчуванням Ubuntu 14.04 LTS VM, створений і працює на Azure, який не поставляється зі свопом

  2. Я хотів би створити своп, використовуючи наявний накопичувач VM, а не створити новий диск, використовуючи додаткове сховище

Я прочитав:

Було обговорено багато рішень, але я не можу знайти те, що зберігатиметься через перезавантаження сервера (можливо, через хмарно-ініт є власна ідея про розподіл зображень), може хтось порадить мені найкращу практику?

Відповіді:


8

Якщо припустимо, що у вас встановлений агент Linux Все, що вам потрібно зробити, це ввімкнути своп під /etc/waagent.conf. Це відповідні рядки:

ResourceDisk.Format=y                   # Format if unformatted. If 'n', resour$
ResourceDisk.Filesystem=ext4            # Typically ext3 or ext4. FreeBSD image$
ResourceDisk.MountPoint=/mnt/resource   #
ResourceDisk.EnableSwap=y               # Create and use swapfile on resource d$
ResourceDisk.SwapSizeMB=2048            # Size of the swapfile.

Він автоматично використовувати диск ресурсів (який постачається з кожною машиною управління) для створення свопу. Для цього немає необхідності створювати диск.

Оновлення : Вам також потрібно виконати наведені нижче кроки, щоб створити свопфайл:

umount /mnt
service walinuxagent restart

Забезпечення диска контролюється Cloud Init на Ubuntu, на відміну від інших дистрибутивів. Так що ні, це не повинно працювати, і док, і мій тест це підтверджують.
bitinn

2
Я зв’язався зі службою підтримки MS та виявив, що рішення встановити ResourceDisk.Format, ResourceDisk.EnableSwapі ResourceDisk.SwapSizeMB. Але важливим кроком є ​​створення посібника sudo service walinuxagent restartзі створення файлу swap, оскільки просто перезавантаження сервера не працює для мене.
bitinn

Я все ще запитую про те, як Cloud Init вбачає у всьому цьому, оскільки їх коментарі doc та waagent.conf вводять в оману.
bitinn

Так. мені шкода забув включити перезапуск агента. Я тестував на своєму ubuntu vm і працював без проблем. Я оновив відповідь. Щодо cloud-init, я не думаю, що це взагалі не має нічого спільного зі створенням swapfile, оскільки агент створює файл всередині розділу ext4 (/ mnt). Він не створює розділ swap.
Бруно Фарія

2
Не працював на Ubuntu 14.04 LTS VM, створений із зображення галереї Azure. Після виконання всіх кроків swapon -sвсе ще з’являється порожній список файлів своп.
JustAMartin

2

Відповідь Бруно - чудова відправна точка, але вона спрацювала лише після того, як я перезавантажився і дав їй ще хвилину після завантаження.

а. Увімкнути заміну /etc/waagent.confвідповідних рядків:

ResourceDisk.Format=y                   # Format if unformatted. If 'n', resour$
ResourceDisk.Filesystem=ext4            # Typically ext3 or ext4. FreeBSD image$
ResourceDisk.MountPoint=/mnt/resource   #
ResourceDisk.EnableSwap=y               # Create and use swapfile on resource d$
ResourceDisk.SwapSizeMB=2048            # Size of the swapfile.

б. Виконайте такі дії як root, що включає перезавантаження машини.

umount /mnt
service walinuxagent restart
reboot

c. Після завантаження все ще буде потрібно деякий час, перш ніж фактично включити своп. Ви можете це перевірити swapon -s.


1

Я вважаю, що правильний спосіб зробити це так, щоб і хмара-ініт, і ваагент грали «добре» разом (від документів Cloud-Init Azure ), щоб ці значення були встановлені до цього

# disabling provisioning turns off all 'Provisioning.*' function
Provisioning.Enabled=n
# this is currently not handled by cloud-init, so let walinuxagent do it.
ResourceDisk.Format=y
ResourceDisk.MountPoint=/mnt

Я спробував змінити точку кріплення, але, здається, вона не працює належним чином, тому документи, ймовірно, точні щодо значень

І тоді ви можете налаштувати параметри заміни за своїм бажанням

# Create and use swapfile on resource disk.
ResourceDisk.EnableSwap=y

# Size of the swapfile.
ResourceDisk.SwapSizeMB=8192

Основний перезапуск набирає новий штраф

sudo service walinuxagent restart

free -m
             total       used       free     shared    buffers     cached
Mem:          3944        882       3061         44         29        163
-/+ buffers/cache:        689       3255
Swap:         8192          0       8192

0

Я прочитав досить багато публікацій з цього приводу, але я все ще не впевнений у правильному підході, припускаючи: 1. У мене є Ubuntu 14.04 LTS VM, створений за замовчуванням, створений і працює на Azure, який не поставляється зі свопом 2. I хотіли б створити своп, використовуючи наявний накопичувач VM, а не створювати новий диск, використовуючи додаткове сховище

Я також потребував цього (фактично 16.04 замість 14.04, але моя відповідь стосуватиметься обох, я думаю).

Я прочитав:

Але коли я побачив, що мені довелося прочитати настільки довгі нариси, що ви вказуєте, я збирався здатися ... Але раптом згадав дуже просту статтю в блозі DigitalOcean:

Як додати Swap на Ubuntu 14.04

Це так просто, що я навіть написав сценарій для нього (принаймні, з найкращої частини, ще не налаштувань простоти та інших додаткових матеріалів):

#!/usr/bin/env fsharpi

open System
open System.IO
open System.Net
open System.Diagnostics

#load "InfraTools.fs"
open Gatecoin.Infrastructure

// automation of https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04

let NUMBER_OF_GB_FOR_SWAP = 1

let isThereSwapMemoryInTheSystem (): bool =
    let _,output,_ = Tools.SafeHiddenExec("swapon", "-s")
    (output.Trim().Length > 0)

if (isThereSwapMemoryInTheSystem()) then
    Console.WriteLine("Swap already setup")
    Environment.Exit(0)

let swapFile = new FileInfo(Path.Combine("/", "swapfile"))
if not (swapFile.Exists) then
    Tools.BailIfNotSudoer("Need to use 'fallocate' to create swap file")
    Console.WriteLine("Creating swap file...")
    Tools.SafeExec("fallocate", String.Format("-l {0}G {1}", NUMBER_OF_GB_FOR_SWAP, swapFile.FullName), true)

let permissionsForSwapFile = 600
if not (Tools.OctalPermissions(swapFile) = permissionsForSwapFile) then
    Tools.BailIfNotSudoer("Need to adjust permissions of the swap file")
    Tools.SafeExec("chmod", String.Format("{0} {1}", permissionsForSwapFile, swapFile.FullName), true)

Tools.BailIfNotSudoer("Enable swap memory")
Tools.SafeExec("mkswap", swapFile.FullName, true)
Tools.SafeExec("swapon", swapFile.FullName, true)
if not (isThereSwapMemoryInTheSystem()) then
    Console.WriteLine("Something went wrong while enabling the swap file")
    Environment.Exit(1)

Tools.BailIfNotSudoer("Writing into /etc/fstab")
Tools.SafeHiddenExecBashCommand(String.Format("echo \"{0}   none    swap    sw    0   0\" >> /etc/fstab", swapFile.FullName))

Щоб вищезазначене працювало, sudo apt install fsharpспочатку потрібно (принаймні, Ubuntu 16.04 має fsharp у сховищах, не впевнений про 14.04).

Також вам потрібен цей InfraTools.fsфайл:

open System
open System.IO
open System.Net

namespace Gatecoin.Infrastructure

module Tools =

    let HiddenExec (command: string, arguments: string) =
        let startInfo = new System.Diagnostics.ProcessStartInfo(command)
        startInfo.Arguments <- arguments
        startInfo.UseShellExecute <- false

        // equivalent to `>/dev/null 2>&1` in unix
        startInfo.RedirectStandardError <- true
        startInfo.RedirectStandardOutput <- true

        use proc = System.Diagnostics.Process.Start(startInfo)
        proc.WaitForExit()
        (proc.ExitCode,proc.StandardOutput.ReadToEnd(),proc.StandardError.ReadToEnd())

    let HiddenExecBashCommand (commandWithArguments: string) =
        let args = String.Format("-c \"{0}\"", commandWithArguments.Replace("\"", "\\\""))
        HiddenExec("bash", args)

    let SafeHiddenExecBashCommand (commandWithArguments: string) =
        let exitCode,stdOut,stdErr = HiddenExecBashCommand commandWithArguments
        if not (exitCode = 0) then
            Console.Error.WriteLine(stdErr)
            Console.Error.WriteLine()
            Console.Error.WriteLine("Bash command '{0}' failed with exit code {1}.", commandWithArguments, exitCode.ToString())
            Environment.Exit(1)
        exitCode,stdOut,stdErr

    let Exec (command: string, arguments: string, echo: bool) =
        let psi = new System.Diagnostics.ProcessStartInfo(command)
        psi.Arguments <- arguments
        psi.UseShellExecute <- false
        if (echo) then
            Console.WriteLine("{0} {1}", command, arguments)
        let p = System.Diagnostics.Process.Start(psi)
        p.WaitForExit()
        p.ExitCode

    let ExecBashCommand (commandWithArguments: string, echo: bool) =
        let args = String.Format("-c \"{0}\"", commandWithArguments.Replace("\"", "\\\""))
        if (echo) then
            Console.WriteLine(commandWithArguments)
        Exec("bash", args, false)

    let SafeHiddenExec (command: string, arguments: string) =
        let exitCode,stdOut,stdErr = HiddenExec(command, arguments)
        if not (exitCode = 0) then
            Console.Error.WriteLine(stdErr)
            Console.Error.WriteLine()
            Console.Error.WriteLine("Command '{0}' failed with exit code {1}. Arguments supplied: '{2}'", command, exitCode.ToString(), arguments)
            Environment.Exit(1)
        exitCode,stdOut,stdErr

    let SafeExec (command: string, arguments: string, echo: bool) =
        let exitCode = Exec(command, arguments, echo)
        if not (exitCode = 0) then
            Console.Error.WriteLine("Command '{0}' failed with exit code {1}. Arguments supplied: '{2}'", command, exitCode.ToString(), arguments)
            Environment.Exit(1)
            failwith "unreached"
        ()

    let SafeExecBashCommand (commandWithArguments: string, echo: bool) =
        let args = String.Format("-c \"{0}\"", commandWithArguments.Replace("\"", "\\\""))
        if (echo) then
            Console.WriteLine(commandWithArguments)
        SafeExec("bash", args, false)

    let FirstElementOf3Tuple (a, _, _) = a
    let SecondElementOf3Tuple (_, b, _) = b

    let SimpleStringSplit (str: string, separator: string): string list =
        List.ofSeq(str.Split([|separator|], StringSplitOptions.RemoveEmptyEntries))

    let SplitStringInLines (str: string): string list =
        SimpleStringSplit(str,Environment.NewLine)

    let CommandWorksInShell (command: string): bool =
        let exitCode =
            try
                Some(FirstElementOf3Tuple(HiddenExec(command,String.Empty))
            with
                | :? System.ComponentModel.Win32Exception -> (); None
        if exitCode.IsNone then
            false
        else
            true

    let BailIfNotSudoer(reason: string): unit =   
        if not (CommandWorksInShell "id") then
            Console.WriteLine ("'id' unix command is needed for this script to work")
            Environment.Exit(2)
            ()

        let _,idOutput,_ = HiddenExec("id","-u")
        if not (idOutput.Trim() = "0") then
            Console.Error.WriteLine ("Error: needs sudo privilege. Reason: {0}", reason)
            Environment.Exit(3)
            ()
        ()

    let OctalPermissions (file: FileInfo): int =
        let output = SecondElementOf3Tuple(SafeHiddenExec("stat", String.Format("-c \"%a\" {0}", file.FullName)))
        Int32.Parse(output.Trim())

Було обговорено багато рішень, але я не можу знайти таке, яке зберігатиметься через перезавантаження сервера

Частина, яка змушує мою відповідь працювати через перезавантаження сервера - це запис у / etc / fstab файл.

Хороша річ у цьому рішенні - це те, що воно має працювати в Azure, DigitalOcean, YouNameIt, ...

Насолоджуйтесь!


2
"Це так просто" з 50 рядків коду здається трохи оксимороном!
kqw

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.