Azure Ubuntu VM에 대한 스왑을 만드는 방법은 무엇입니까?


9

나는 이것에 대해 꽤 많은 게시물을 읽었지만 여전히 올바른 접근법에 대해 확신하지 못한다.

  1. 스왑이 제공되지 않는 Azure에서 만들고 실행하는 기본 Ubuntu 14.04 LTS VM이 있습니다.

  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.

스왑을 생성하기 위해 자동으로 리소스 디스크 (모든 VM과 함께 제공)를 사용합니다. 디스크를 만들 필요가 없습니다.

업데이트 : 스왑 파일을 만들려면 아래 단계도 수행해야합니다.

umount /mnt
service walinuxagent restart

디스크 배포는 다른 배포와 달리 Ubuntu의 Cloud Init에 의해 제어됩니다. 그래서 아니오, 이것은 작동하지 않아야하며 doc과 내 테스트 모두 확인합니다.
bitinn

2
I는 MS 지원 접촉하여 용액을 설정하는 발견 ResourceDisk.Format, ResourceDisk.EnableSwapResourceDisk.SwapSizeMB. 그러나 중요한 단계는 sudo service walinuxagent restart재부팅 서버가 작동하지 않기 때문에 수동 으로 스왑 파일을 만드는 것입니다.
bitinn 2018 년

doc 및 waagent.conf 주석이 잘못되어 있기 때문에 Cloud Init 이이 모든 것을 어떻게 이해하는지 여전히 묻고 있습니다.
bitinn 2018 년

예. 죄송 해요. 에이전트 재시작을 포함하지 않았습니다. 우분투 vm에서 테스트했으며 문제없이 작동했습니다. 답변을 업데이트했습니다. cloud-init와 관련하여 에이전트가 ext4 파티션 (/ mnt) 내에 파일을 작성하기 때문에 스왑 파일 작성과 전혀 관련이 없다고 생각합니다. 스왑 파티션을 만들지 않습니다.
Bruno Faria 2016 년

2
Azure Gallery 이미지에서 만든 Ubuntu 14.04 LTS VM에서 작동하지 않았습니다. 모든 단계를 수행 한 swapon -s후에도 여전히 비어있는 스왑 파일 목록이 표시됩니다.
JustAMartin

2

Bruno의 대답은 훌륭한 출발점이지만 재부팅 한 후에 만 ​​작동했으며 부팅 후 1 분이 더 지났습니다.

ㅏ. 스왑 /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
reboot

씨. 부팅 후에도 스왑이 실제로 활성화되기까지 시간이 조금 걸립니다. 로 확인할 수 있습니다 swapon -s.


1

cloud-init와 waagent가 'nice'을 함께 ( Cloud-Init Azure docs에서 ) 함께 사용하도록이를 수행하는 올바른 방법 은이 값을 다음과 같이 설정하는 것입니다.

# 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

나는 이것에 대해 꽤 많은 게시물을 읽었지만 여전히 다음과 같은 가정하에 올바른 접근법에 대해 확신이 없습니다. 추가 스토리지를 사용하여 새 디스크를 생성하는 대신 기존 VM 스토리지를 사용하여 스왑을 생성하려고합니다

나는 또한 이것을 필요로했다.

내가 읽은 게시물 :

그러나 내가 당신이 지적한 너무 긴 수필을 읽어야한다는 것을 알았을 때 나는 포기하려고했지만 ... 갑자기 DigitalOcean의 블로그에서 매우 간단한 기사를 기억했습니다.

우분투 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는 리포지토리에서 선명하지 않으며 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.