如何为Azure Ubuntu VM创build交换?

我已经阅读了不less文章,但我仍然不确定正确的做法,假设:

  1. 我有一个在Azure上创build并运行的默认Ubuntu 14.04 LTS虚拟机,它没有交换

  2. 我想用现有的虚拟机存储创build一个交换,而不是使用额外的存储创build一个新的磁盘

我已阅读的post:

  • https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-how-to-inject-custom-data/
  • https://wiki.ubuntu.com/AzureSwapPartitions
  • https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1374166

讨论了许多解决scheme,但我似乎无法find一个将继续跨服务器重新启动(可能是由于云初始化有自己的想法有关图像分区),有人可以告诉我的最佳做法吗?

假设你已经安装了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. 

它将自动使用资源磁盘(每个虚拟机附带)来创build交换。 没有必要为它创build一个磁盘。

更新 :您还需要执行以下步骤来创build交换文件:

 umount /mnt service walinuxagent restart 

布鲁诺的答案是一个很好的起点,但它只有在我重新启动并在启动后再一分钟后才起作用。

一个。 在/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.我有一个默认的Ubuntu 14.04 LTS虚拟机在Azure上运行,并且没有交换2.我想要使用现有的VM存储创build交换,而不是使用额外的存储创build新磁盘

我也需要这个(实际上是16.04而不是14.04,但我的答案将适用于我所认为的)。

我已阅读的post:

但是当我看到我必须阅读那么长的文章时,你才会指出,我将要放弃…但突然间,我想起DigitalOcean博客中一篇非常简单的文章:

如何在Ubuntu 14.04上添加交换

这很简单,我甚至为它写了一个脚本(至less对于最好的部分,还不是swappiness设置和其他高级的东西):

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

讨论了许多解决scheme,但我似乎无法find一个将持续跨服务器重新启动

使我的答案通过服务器重新启动的部分是写入/ etc / fstab文件。

这个解决scheme的好处是,它应该在Azure,DigitalOcean,YouNameIt,…

请享用!

我相信正确的做法是让cloud-init和waagent一起玩(从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