Comment créer un swap pour Azure Ubuntu VM?


9

J'ai lu pas mal de messages à ce sujet, mais je ne suis toujours pas sûr de la bonne approche, en supposant:

  1. J'ai une machine virtuelle Ubuntu 14.04 LTS par défaut créée par et exécutée sur Azure, qui ne vient pas avec un échange

  2. Je voudrais créer un swap en utilisant le stockage de VM existant, au lieu de créer un nouveau disque en utilisant un stockage supplémentaire

Articles que j'ai lus:

De nombreuses solutions ont été discutées mais je n'arrive pas à en trouver une qui persiste lors des redémarrages du serveur (probablement en raison du cloud-init a sa propre idée sur le partitionnement d'image), quelqu'un peut-il me conseiller sur la meilleure pratique?

Réponses:


8

En supposant que Linux Agent soit installé. Tout ce que vous avez à faire est d'activer le swap sous /etc/waagent.conf. Ce sont les lignes pertinentes:

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.

Il utilisera automatiquement le disque de ressources (fourni avec chaque machine virtuelle) pour créer le swap. Il n'est pas nécessaire de créer un disque pour cela.

Mise à jour : vous devez également exécuter les étapes ci-dessous pour créer le fichier d'échange:

umount /mnt
service walinuxagent restart

La disposition du disque est contrôlée par Cloud Init sur Ubuntu, contrairement aux autres distributions. Donc non, cela ne devrait pas fonctionner, et doc et mon test le confirment.
bitinn

2
J'ai contacté le support MS et j'ai trouvé que la solution était de définir ResourceDisk.Format, ResourceDisk.EnableSwapet ResourceDisk.SwapSizeMB. MAIS l'étape importante est de faire un manuel sudo service walinuxagent restartpour créer le fichier d'échange, car le redémarrage du serveur ne fonctionne pas pour moi.
bitinn

Je demande toujours comment Cloud Init figure dans tout cela, car leurs commentaires doc et waagent.conf sont trompeurs.
bitinn

Ouaip. Je suis désolé. oublié d'inclure le redémarrage de l'agent. J'ai testé sur mon ubuntu vm et travaillé sans problème. J'ai mis à jour la réponse. Concernant cloud-init, je ne pense pas que cela ait quoi que ce soit à voir avec la création du fichier d'échange puisque l'agent crée le fichier à l'intérieur d'une partition ext4 (/ mnt). Il ne crée pas de partition de swap.
Bruno Faria

2
N'a pas fonctionné sur Ubuntu 14.04 LTS VM, créé à partir de l'image Azure Gallery. Après avoir effectué toutes les étapes, swapon -saffiche toujours une liste vide de fichiers d'échange.
JustAMartin

2

La réponse de Bruno est un excellent point de départ, mais cela n'a fonctionné qu'après que j'ai redémarré et lui ai donné une minute après le démarrage.

une. Activer l'échange /etc/waagent.conf, lignes pertinentes:

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. Effectuez les opérations suivantes en tant que root, ce qui comprend le redémarrage de votre ordinateur:

umount /mnt
service walinuxagent restart
reboot

c. Après le démarrage, il faudra encore un certain temps avant que l'échange ne soit réellement activé. Vous pouvez le vérifier avec swapon -s.


1

Je crois que la bonne façon de le faire pour que cloud-init et waagent jouent `` bien '' ensemble (à partir des documents Cloud-Init Azure ) est de conserver ces valeurs définies sur ce

# 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

J'ai essayé de changer le point de montage mais cela ne semblait pas fonctionner correctement, donc les documents sont probablement précis sur les valeurs

Et puis vous pouvez personnaliser les options de swap comme vous le souhaitez

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

# Size of the swapfile.
ResourceDisk.SwapSizeMB=8192

Un redémarrage de base reprend le nouveau swap fine

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

J'ai lu pas mal de messages à ce sujet, mais je ne suis toujours pas sûr de la bonne approche, en supposant: 1. J'ai une machine virtuelle Ubuntu 14.04 LTS par défaut créée par et exécutée sur Azure, qui ne vient pas avec un échange 2. Je souhaite créer un swap en utilisant le stockage de VM existant, au lieu de créer un nouveau disque en utilisant un stockage supplémentaire

J'en avais aussi besoin (en fait 16.04 au lieu de 14.04, mais ma réponse s'appliquera aux deux je pense).

Articles que j'ai lus:

Mais quand j'ai vu que je devais lire des essais si longs que vous le dites, j'allais abandonner ... Mais soudain, je me suis souvenu d'un article très simple dans le blog de DigitalOcean:

Comment ajouter Swap sur Ubuntu 14.04

C'est si simple que j'ai même écrit un script pour cela (au moins pour la meilleure partie, pas encore les paramètres de swappiness et d'autres choses avancées):

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

Pour que ce qui précède fonctionne, vous devez d' sudo apt install fsharpabord (au moins Ubuntu 16.04 a fsharp dans les référentiels, pas sûr de 14.04).

Vous avez également besoin de ce InfraTools.fsfichier:

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

De nombreuses solutions ont été discutées mais je n'arrive pas à en trouver une qui persistera lors des redémarrages du serveur

La partie qui fait fonctionner ma réponse lors des redémarrages du serveur est l'écriture dans le fichier / etc / fstab.

La bonne chose à propos de cette solution est qu'elle devrait fonctionner dans Azure, DigitalOcean, YouNameIt, ...

Prendre plaisir!


2
"C'est tellement simple" suivi de 50 lignes de code semble un peu un oxymore!
kqw

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.