Come creare uno scambio per VM Ubuntu di Azure?


9

Ho letto alcuni post su questo, ma non sono ancora sicuro dell'approccio corretto, supponendo:

  1. Ho una macchina virtuale Ubuntu 14.04 LTS predefinita creata e in esecuzione su Azure, che non viene fornita con uno scambio

  2. Vorrei creare uno scambio utilizzando l'archiviazione VM esistente, invece di creare un nuovo disco utilizzando spazio di archiviazione aggiuntivo

Post che ho letto:

Sono state discusse molte soluzioni, ma non riesco a trovarne una che persista nei riavvii dei server (probabilmente a causa del cloud-init ha una sua idea sul partizionamento delle immagini), qualcuno può consigliarmi le migliori pratiche?

Risposte:


8

Supponendo che tu abbia Linux Agent installato. Tutto quello che devi fare è abilitare lo scambio in /etc/waagent.conf. Queste sono le linee pertinenti:

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.

Utilizzerà automaticamente il disco delle risorse (fornito con ogni macchina virtuale) per creare lo scambio. Non è necessario creare un disco per esso.

Aggiornamento : è inoltre necessario eseguire i passaggi seguenti per creare il file di scambio:

umount /mnt
service walinuxagent restart

La fornitura del disco è controllata da Cloud Init su Ubuntu, a differenza di altre distribuzioni. Quindi no, questo non dovrebbe funzionare e sia doc che il mio test lo confermano.
Bitinn,

2
Ho contattato il supporto SM e trovato la soluzione è impostato ResourceDisk.Format, ResourceDisk.EnableSwape ResourceDisk.SwapSizeMB. MA il passo importante è fare un manuale sudo service walinuxagent restartper creare il file di scambio, poiché il riavvio del server non funziona per me.
bitinn,

Sto ancora chiedendo come Cloud Init sia in grado di comprendere tutto ciò, perché i loro commenti doc e waagent.conf sono fuorvianti.
bitinn,

Sì. Mi dispiace. dimenticato di includere il riavvio dell'agente. Ho provato su Ubuntu VM e ho lavorato senza problemi. Ho aggiornato la risposta. Per quanto riguarda cloud-init, non penso che abbia nulla a che fare con la creazione del file di scambio poiché l'agente crea il file all'interno di una partizione ext4 (/ mnt). Non crea una partizione di swap.
Bruno Faria,

2
Non ha funzionato su Ubuntu 14.04 LTS VM, creato dall'immagine della Galleria di Azure. Dopo aver eseguito tutti i passaggi, swapon -smostra ancora un elenco vuoto di file di scambio.
JustAMartin,

2

La risposta di Bruno è un ottimo punto di partenza, ma ha funzionato solo dopo il riavvio e l'ho dato un altro minuto dopo l'avvio.

un. Abilita scambio in /etc/waagent.conf, righe pertinenti:

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. Effettuare le seguenti operazioni come root, che include il riavvio del computer:

umount /mnt
service walinuxagent restart
reboot

c. Dopo l'avvio, ci vorrà ancora del tempo prima che lo swap sia effettivamente abilitato. Puoi verificarlo con swapon -s.


1

Credo che il modo giusto per farlo in modo che sia cloud-init che waagent giochino insieme (dai documenti di Azure Cloud-Init ) sia mantenere questi valori impostati su questo

# 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

Ho provato a cambiare il mountpoint ma non sembra funzionare correttamente, quindi i documenti sono probabilmente precisi sui valori

E quindi puoi personalizzare le opzioni di scambio come desideri

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

# Size of the swapfile.
ResourceDisk.SwapSizeMB=8192

Un riavvio di base raccoglie la nuova multa di scambio

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

Ho letto alcuni post su questo, ma non sono ancora sicuro dell'approccio corretto, supponendo: 1. Ho una macchina virtuale Ubuntu 14.04 LTS predefinita creata e in esecuzione su Azure, che non viene fornita con uno scambio 2. I vorrebbe creare uno swap utilizzando l'archiviazione VM esistente, anziché creare un nuovo disco utilizzando l'archiviazione aggiuntiva

Ne avevo anche bisogno (in realtà il 16.04 invece del 14.04, ma la mia risposta si applicherà a entrambi penso).

Post che ho letto:

Ma quando ho visto che dovevo leggere saggi così lunghi che mi fai notare, mi sarei arreso ... Ma all'improvviso mi sono ricordato di un articolo molto semplice nel blog di DigitalOcean:

Come aggiungere Swap su Ubuntu 14.04

È così semplice che ho persino scritto una sceneggiatura (almeno per la parte migliore, non ancora le impostazioni di swappiness e altre cose avanzate):

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

Affinché quanto sopra funzioni, devi sudo apt install fsharpprima (almeno Ubuntu 16.04 ha fsharp nei repository, non sono sicuro circa 14.04).

Inoltre è necessario questo InfraTools.fsfile:

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

Sono state discusse molte soluzioni, ma non riesco a trovarne una che persista al riavvio del server

La parte che fa funzionare la mia risposta al riavvio del server è la scrittura nel file / etc / fstab.

La cosa buona di questa soluzione è che dovrebbe funzionare in Azure, DigitalOcean, YouNameIt, ...

Godere!


2
"È così semplice" seguito da 50 righe di codice sembra un po 'un ossimoro!
kqw,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.