Bagaimana cara membuat swap untuk Azure Ubuntu VM?

9

Saya telah membaca beberapa posting tentang ini, tetapi saya masih tidak yakin tentang pendekatan yang benar, dengan asumsi:

  1. Saya memiliki Ubuntu 14.04 LTS VM default yang dibuat oleh dan berjalan di Azure, yang tidak disertai dengan swap

  2. Saya ingin membuat swap menggunakan penyimpanan VM yang ada, daripada membuat disk baru menggunakan penyimpanan tambahan

Tulisan yang saya baca:

Banyak solusi yang dibahas, tetapi sepertinya saya tidak dapat menemukan satu yang akan bertahan di seluruh reboot server (mungkin karena cloud-init memiliki ide sendiri tentang partisi gambar), dapatkah seseorang memberi saran kepada saya tentang praktik terbaik?

bitinn
sumber

Jawaban:

8

Dengan anggapan Anda telah menginstal Linux Agent. Yang harus Anda lakukan adalah mengaktifkan swap di /etc/waagent.conf. Ini adalah baris yang relevan:

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.

Secara otomatis akan menggunakan disk sumber daya (yang datang dengan setiap VM) untuk membuat swap. Tidak perlu membuat disk untuk itu.

Pembaruan : Anda juga perlu menjalankan langkah-langkah di bawah ini untuk membuat swapfile:

umount /mnt
service walinuxagent restart
Bruno Faria
sumber
Penyediaan disk dikendalikan oleh Cloud Init di Ubuntu, tidak seperti distribusi lainnya. Jadi tidak, ini seharusnya tidak berhasil, dan baik dokter maupun pengujian saya mengonfirmasinya.
bitinn
2
Saya menghubungi dukungan MS dan menemukan solusinya adalah mengatur ResourceDisk.Format, ResourceDisk.EnableSwapdan ResourceDisk.SwapSizeMB. TETAPI langkah penting adalah melakukan manual sudo service walinuxagent restartuntuk membuat file swap, karena hanya me-reboot server tidak bekerja untuk saya.
bitinn
Saya masih bertanya tentang bagaimana Cloud Init memahami semua ini, karena komentar doc dan waagent.conf mereka menyesatkan.
bitinn
Ya. Maafkan saya. lupa untuk memasukkan agen restart. Saya menguji vm ubuntu saya dan bekerja tanpa masalah. Saya sudah memperbarui jawabannya. Mengenai cloud-init, saya tidak berpikir itu ada hubungannya dengan pembuatan swapfile sama sekali karena agen membuat file di dalam partisi ext4 (/ mnt). Itu tidak membuat partisi swap.
Bruno Faria
2
Tidak bekerja di Ubuntu 14.04 LTS VM, dibuat dari gambar Azure Gallery. Setelah melakukan semua langkah, swapon -smasih menampilkan daftar kosong file swap.
JustAMartin
2

Jawaban Bruno adalah titik awal yang bagus, tetapi itu hanya berhasil setelah saya reboot dan memberikannya satu menit setelah booting.

Sebuah. Aktifkan swap masuk /etc/waagent.conf, baris yang relevan:

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.

b. Lakukan hal berikut sebagai root, yang termasuk me-reboot mesin Anda:

umount /mnt
service walinuxagent restart
reboot

c. Setelah booting, masih perlu waktu sebelum swap diaktifkan. Anda dapat memeriksanya swapon -s.

kqw
sumber
1

Saya percaya cara yang tepat untuk melakukan ini sehingga cloud-init dan waagent bermain 'bagus' bersama (dari Cloud-Init Azure docs ) adalah untuk menjaga nilai-nilai ini tetap seperti ini.

# 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

Saya mencoba mengubah mountpoint tetapi sepertinya tidak berfungsi dengan baik sehingga dokumen mungkin akurat tentang nilai-nilai

Dan kemudian Anda dapat menyesuaikan opsi swap seperti yang Anda inginkan

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

# Size of the swapfile.
ResourceDisk.SwapSizeMB=8192

Restart dasar mengambil denda swap baru

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
Takut Hyena
sumber
0

Saya telah membaca beberapa posting tentang ini, tetapi saya masih tidak yakin tentang pendekatan yang benar, dengan asumsi: 1. Saya memiliki Ubuntu 14.04 LTS VM default yang dibuat oleh dan berjalan di Azure, yang tidak datang dengan swap 2. Saya ingin membuat swap menggunakan penyimpanan VM yang ada, alih-alih membuat disk baru menggunakan penyimpanan tambahan

Saya juga membutuhkan ini (sebenarnya 16,04 bukannya 14,04, tetapi jawaban saya akan berlaku untuk keduanya saya pikir).

Tulisan yang saya baca:

Tetapi ketika saya melihat saya harus membaca esai yang begitu panjang yang Anda tunjukkan, saya akan menyerah ... Tapi tiba-tiba saya teringat sebuah artikel yang sangat mudah di blog DigitalOcean:

Cara Menambahkan Swap Pada Ubuntu 14.04

Ini sangat sederhana sehingga saya bahkan telah menulis skrip untuk itu (setidaknya untuk bagian terbaik, belum pengaturan swappiness dan hal-hal canggih lainnya):

#!/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))

Agar hal di atas berfungsi, Anda harus sudo apt install fsharpterlebih dahulu (setidaknya Ubuntu 16.04 memiliki fsharp di repositori, tidak yakin tentang 14,04).

Anda juga memerlukan InfraTools.fsfile ini :

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())

Banyak solusi yang dibahas, tetapi sepertinya saya tidak dapat menemukan satu yang akan bertahan di seluruh reboot server

Bagian yang membuat jawaban saya berfungsi melalui reboot server adalah penulisan ke file / etc / fstab.

Hal yang baik tentang solusi ini adalah ia harus bekerja di Azure, DigitalOcean, YouNameIt, ...

Nikmati!

knocte
sumber
2
"Ini sangat sederhana" diikuti oleh 50 baris kode yang tampaknya sedikit oxymoron!
kqw