準備 Linux 以用於 Azure 映像

警告

本文參考 CentOS,這是接近結束生命週期 (EOL) 狀態的 Linux 發行版本。 請據以考慮您的使用和規劃。 如需詳細資訊,請參閱 CentOS 生命週期結束指引

適用於:✔️ Linux VM ✔️ 彈性擴展集

僅當您使用其中一個背書的發行版本時,Azure 平台服務等級協定 (SLA) 才會適用於執行 Linux 作業系統的虛擬機器 (VM)。 針對背書的發行版本,Azure Marketplace 提供預先設定的 Linux 映像。 如需詳細資訊,請參閱

在 Azure 上執行的所有其他發行版本,包含社群支援和非背書的發行版本,都有一些必要條件。

本文將著重於在 Azure 上執行 Linux 發行版本時的一般指導。 本文無法完整詳述,因為每個發行版本各不相同。 即使您符合本文描述的所有準則,還是可能需要對您的 Linux 系統進行大幅調整,以使其正常執行。

一般 Linux 安裝注意事項

  • Azure 不支援 Hyper-V 虛擬硬碟 (VHDX) 格式。 Azure 只支援固定 VHD。 您可以使用 Hyper-V 管理員或 Convert-VHD Cmdlet,將磁碟轉換為 VHD 格式。 如果您使用的是 VirtualBox,即會在建立磁碟時選取 [固定大小] 而不是預設值 (動態配置的)

  • Azure 支援 Gen1 (BIOS 開機) 和 Gen2 (UEFI 開機) 虛擬機器。

  • 必須在核心中啟用虛擬檔案配置表 (VFAT) 核心模組。

  • 允許的 VHD 大小上限為 1023 GB。

  • 安裝 Linux 系統時,建議您使用標準磁碟分割,而不是邏輯磁碟區管理員 (LVM)。 LVM 是許多安裝程序的預設值。

    使用標準磁碟分割將可避免 LVM 名稱與複製的 VM 發生衝突,特別是為了疑難排解而一律要將 OS 磁碟連接至另一個相同的 VM 時。 您可以在資料磁碟上使用 LVMRAID

  • 需要裝載了使用者定義函式 (UDF) 檔案系統的核心支援。 在 Azure 上第一次開機時,佈建設定會透過連結至客體的 UDF 格式媒體傳遞至 Linux VM。 Azure Linux 代理程式必須裝載 UDF 檔案系統,才能讀取其設定並佈建 VM。

  • 2.6.37 以前的 Linux 核心版本不支援具較大 VM 大小的 Hyper-V 非統一記憶體存取 (NUMA)。 這個問題主要會影響使用了上游 Red Hat 2.6.32 核心的較舊發行版本。 該問題已在 Red Hat Enterprise Linux (RHEL) 6.6 (kernel-2.6.32-504) 進行修正。

    若系統執行的自訂核心是 2.6.37 以前版本,或 執行 2.6.32-504 以前版本的 RHEL 型核心,則必須在 grub.conf 的核心命令列上設定開機參數 numa=off。 如需詳細資訊,請參閱 Red Hat KB 436883 \(英文\)。

  • 請勿在 OS 磁碟上設定交換磁碟分割。 如本文後段所述,您可以設定 Linux 代理程式以在暫存資源磁碟上建立分頁檔。

  • Azure 上的所有 VHD 必須具有與 1 MB (1024 x 1024 位元組) 對應的虛擬大小。 如本文後段所述,當您從原始磁碟轉換為 VHD 時,請在轉換前確定原始磁碟大小是 1 MB 的倍數。

  • 使用最新的散發套件版本、套件和軟體。

  • 移除使用者和系統帳戶、公開金鑰、敏感性資料、不必要的軟體和應用程式。

注意

Cloud-init 21.2 版或更新版本會移除 UDF 需求。 不過,若未啟用 udf 模組,就無法在佈建期間裝載 CD-ROM,進而無法套用自訂資料。 因應措施是套用使用者資料。 然而,與自訂資料不同,使用者資料並未經過加密。 如需詳細資訊,請參閱 cloud-init 文件中的使用者資料格式

安裝不含 Hyper-V 的核心模組

Azure 會在 Hyper-V Hypervisor 上執行,因此 Linux 要求在 Azure 中執行某些核心模組。 如果您是在 Hyper-V 外部建立 VM,除非 VM 偵測到其執行環境為 Hyper-V 環境,否則 Linux 安裝程式在初始的 RAM 磁碟 (initrd 或 initramfs) 中可能不會包含 Hyper-V 的驅動程式。

使用不同的虛擬化系統 (例如 VirtualBox 或 KVM) 來準備 Linux 映像時,您可能需要重建 initrd,以確保在初始 RAM 磁碟上至少有 hv_vmbushv_storvsc 核心模組可以使用。 這個已知問題適用於以上游 Red Hat 發行版本為基礎的系統,而且可能還有其他系統。

重建 initrd 或 initramfs 映像的機制可能會根據發行版本而有所不同。 請參閱散發套件的文件或洽支援人員,以了解適當程序。 以下是使用 mkinitrd 公用程式重建 initrd 的範例之一:

  1. 備份現有的 initrd 映像:

    cd /boot
    sudo cp initrd-`uname -r`.img  initrd-`uname -r`.img.bak
    
  2. 使用 hv_vmbushv_storvsc 核心模組重建 initrd:

    sudo mkinitrd --preload=hv_storvsc --preload=hv_vmbus -v -f initrd-`uname -r`.img `uname -r`
    

調整 VHD 的大小

Azure 上的 VHD 映像必須具有與 1 MB 對齊的虛擬大小。 一般而言,透過 Hyper-V 建立的 VHD 均會正確地對應儲存。 如果 VHD 並未正確地對應儲存,則當您嘗試從 VHD 建立映像時,可能會收到類似以下範例的錯誤訊息:

The VHD http://<mystorageaccount>.blob.core.windows.net/vhds/MyLinuxVM.vhd has an unsupported virtual size of 21475270656 bytes. The size must be a whole number (in MBs).

在此案例中,您可以使用 Hyper-V 管理員主控台或 Resize-VHD PowerShell Cmdlet 來調整 VM 的大小。 如果您不是在 Windows 環境中執行,建議使用 qemu-img 來轉換 VHD (如果需要) 並調整其大小。

注意

QEMU 2.2.1 版和之後的部份版本有 qemu-img 已知錯誤 (bug),該錯誤會導致 VHD 的格式不正確。 此問題已在 QEMU 2.6 中修正。 建議您使用 2.2.0 版或更早版本,或使用 2.6 版或更新版本。

  1. 直接使用工具 (例如 qemu-imgvbox-manage) 調整 VHD 的大小,可能會導致 VHD 無法開機。 建議您先使用以下程式碼,將 VHD 轉換為原始磁碟映像。

    如果 VM 映像已建立為原始磁碟映像,您可以略過此步驟。 將 VM 映像建立為原始磁碟映像是某些 Hypervisor (例如 KVM) 中的預設值。

    sudo qemu-img convert -f vpc -O raw MyLinuxVM.vhd MyLinuxVM.raw
    
  2. 計算所需的磁碟映像大小,如此一來,虛擬大小即會對應儲存為 1 MB。 下列 Bash 殼層指令碼會使用 qemu-img info 來判斷磁碟映像的虛擬大小,然後計算到下一個 1 MB 的大小:

    rawdisk="MyLinuxVM.raw"
    vhddisk="MyLinuxVM.vhd"
    
    MB=$((1024*1024))
    size=$(qemu-img info -f raw --output json "$rawdisk" | \
    gawk 'match($0, /"virtual-size": ([0-9]+),/, val) {print val[1]}')
    
    rounded_size=$(((($size+$MB-1)/$MB)*$MB))
    
    echo "Rounded Size = $rounded_size"
    
  3. 使用 $rounded_size 調整原始磁碟的大小:

    sudo qemu-img resize MyLinuxVM.raw $rounded_size
    
  4. 將原始磁碟轉換回固定大小的 VHD:

    sudo qemu-img convert -f raw -o subformat=fixed,force_size -O vpc MyLinuxVM.raw MyLinuxVM.vhd
    

    或者,使用 2.6 版之前的 QEMU 版本來移除 force_size 選項:

    sudo qemu-img convert -f raw -o subformat=fixed -O vpc MyLinuxVM.raw MyLinuxVM.vhd
    

Linux 核心需求

適用於 Hyper-V 和 Azure 的 Linux Integration Services (LIS) 驅動程式會直接提供給上游 Linux Kernel。 許多包括最新 Linux 核心版本 (例如 3.x) 的發行版本已經有這些驅動程式可供使用,或透過其核心來提供這些驅動程式的向後移植版本。

LIS 驅動程式會在上游核心中不斷更新,並具有新的修正程式和功能。 建議您執行包含這些修正程式和更新的背書發行版本 (若適用)。

如果您執行的是 RHEL 版本 6.0 到 6.3 的變體,則必須安裝 Hyper-V 的最新 LIS 驅動程式。 從 RHEL 6.4+ (及衍生項目) 開始,核心就已經隨附 LIS 驅動程式,因此您無需額外的安裝套件。

如果需要自訂核心,建議您使用最新的核心版本 (例如 3.8+)。 針對發行版本或自行維護核心的廠商,您需要定期將 LIS 驅動程式從上游核心反向移植到您的自訂核心。

即使您已經在執行相對較新的核心版本,還是強烈建議您持續追蹤 LIS 驅動程式中的任何上游修正程式,並視需要將其反向移植。 LIS 驅動程式原始程式檔的位置均指定於 Linux 核心來源樹狀目錄的 MAINTAINERS 檔案中:

    F:    arch/x86/include/asm/mshyperv.h
    F:    arch/x86/include/uapi/asm/hyperv.h
    F:    arch/x86/kernel/cpu/mshyperv.c
    F:    drivers/hid/hid-hyperv.c
    F:    drivers/hv/
    F:    drivers/input/serio/hyperv-keyboard.c
    F:    drivers/net/hyperv/
    F:    drivers/scsi/storvsc_drv.c
    F:    drivers/video/fbdev/hyperv_fb.c
    F:    include/linux/hyperv.h
    F:    tools/hv/

VM 的作用中核心必須包含下列修補檔。 對於所有發行版本而言,此清單並不完整。

Azure Linux 代理程式

Azure Linux 代理程式 (waagent) 會在 Azure 中佈建 Linux 虛擬機器。 您可以在 Linux 代理程式 GitHub 存放庫中取得最新版本、回報問題或提交提取要求。

以下是使用 Azure Linux 代理程式的一些考量:

  • Linux 代理程式已在 Apache 2.0 授權下發行。 許多發行版本已為代理程式提供 .rpm 或 .deb 套件。 您可以輕鬆安裝及更新這些套件。
  • Azure Linux 代理程式需要 Python v2.6+。
  • 代理程式還需要 python-pyasn1 模組。 大多數的發行版本都會以可個別安裝的套件形式提供此模組。
  • 在某些情況下,Azure Linux 代理程式可能與 NetworkManager 不相容。 發行版本所提供的許多套件 (.rpm 或 .deb) 都會將 NetworkManager 設定為與 waagent 套件的衝突。 在這些情況下,當您安裝 Linux 代理程式套件時,代理程式將會解除安裝 NetworkManager。
  • Azure Linux 代理程式必須等於或高於最小支援版本

注意

請確定已啟用 udfvfat 模組。 停用 udf 模組會導致佈建失敗。 停用 vfat 模組會同時導致佈建和開機失敗。 在這兩個條件存在的情況下,Cloud-init 21.2 版或更新版本可以佈建 VM 而無需使用 UDF:

  • 您使用 SSH 公開金鑰而非密碼來建立 VM。
  • 您未提供任何自訂資料。

一般的 Linux 系統需求

  1. 修改 GRUB 或 GRUB2 中的核心開機行以包含下列參數,如此便會將所有主控台訊息傳送到第一個序列埠。 這些訊息均可協助 Azure 支援來偵錯任何問題。

    GRUB_CMDLINE_LINUX="rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0"
    

    我們也建議移除下列參數 (如果有的話):

    rhgb quiet crashkernel=auto
    

    在雲端環境中,您會想要將所有記錄傳送到序列埠,因此不適合使用圖形化和無訊息開機。 您可以視需要保留已設定的 crashkernel 選項,但此參數會減少 VM 中至少 128 MB 的可用記憶體數量。 減少可用的記憶體可能會對較小的 VM 大小造成問題。

  2. 在您編輯 /etc/default/grub 之後,請執行下列命令以重建 GRUB 設定:

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    
  3. 使用 dracut 來新增適用於 initramfs 的 Hyper-V 模組:

    cd /boot
    sudo cp initramfs-<kernel-version>.img <kernel-version>.img.bak
    sudo dracut -f -v initramfs-<kernel-version>.img <kernel-version> --add-drivers "hv_vmbus hv_netvsc hv_storvsc"
    sudo grub-mkconfig -o /boot/grub/grub.cfg
    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    

    使用 mkinitramfs 來新增適用於 initrd 的 Hyper-V 模組:

    cd /boot
    sudo cp initrd.img-<kernel-version>  initrd.img-<kernel-version>.bak
    sudo mkinitramfs -o initrd.img-<kernel-version> <kernel-version>  --with=hv_vmbus,hv_netvsc,hv_storvsc
    sudo update-grub
    
  4. 確定您已安裝 SSH 伺服器,並已設定為在開機時啟動。 此設定通常是預設值。

  5. 安裝 Azure Linux 代理程式。

    如需在 Azure 上佈建 Linux 映像,您需要 Azure Linux 代理程式。 許多發行版本會以 .rpm 或 .deb 套件的形式提供代理程式。 套件通常稱為 WALinuxAgentwalinuxagent。 您也可以遵循 Azure Linux 代理程式指南中的步驟來手動安裝代理程式。

    注意

    請確定已啟用 udfvfat 模組。 移除或停用該模組將導致佈建或開機失敗。 Cloud-init 21.2 版或更新版本會移除 UDF 需求。

    執行下列其中一個命令,以安裝 Azure Linux 代理程式、cloud-init 和其他必要的公用程式。

    針對 Red Hat 或 CentOS 使用此命令:

    sudo yum install -y WALinuxAgent cloud-init cloud-utils-growpart gdisk hyperv-daemons
    

    針對 Ubuntu/Debian 使用此命令:

    sudo apt install walinuxagent cloud-init cloud-utils-growpart gdisk hyperv-daemons
    

    針對 SUSE 使用此命令:

    sudo zypper install python-azure-agent cloud-init cloud-utils-growpart gdisk hyperv-daemons
    

    然後在所有發行版本上啟用代理程式和 cloud-init:

    sudo systemctl enable waagent.service
    sudo systemctl enable cloud-init.service
    
  6. 請不要在 OS 磁碟上建立交換空間。

    您可以使用 Azure Linux 代理程式或 cloud-init,透過本機資源磁碟來設定交換空間。 在 Azure 上佈建後,此資源磁碟會連結至 VM。 本機資源磁碟是暫存磁碟,可能會在 VM 取消佈建時清空。 下列區塊示範如何設定此交換程序。

    若您選擇 Azure Linux 代理程式,請在 /etc/waagent.conf 中修改下列參數:

    ResourceDisk.Format=y
    ResourceDisk.Filesystem=ext4
    ResourceDisk.MountPoint=/mnt/resource
    ResourceDisk.EnableSwap=y
    ResourceDisk.SwapSizeMB=2048    ## NOTE: Set this to your desired size.
    

    若您選擇 cloud-init,請設定 cloud-init 來處理佈建程序:

    sudo sed -i 's/Provisioning.Agent=auto/Provisioning.Agent=cloud-auto/g' /etc/waagent.conf
    sudo sed -i 's/ResourceDisk.Format=y/ResourceDisk.Format=n/g' /etc/waagent.conf
    sudo sed -i 's/ResourceDisk.EnableSwap=y/ResourceDisk.EnableSwap=n/g' /etc/waagent.conf
    

    若要將 cloud-init 設定為格式並建立交換空間,您可以使用兩個選項:

    • 每次透過 customdata 建立 VM 時傳入 cloud-init 設定。 建議您採用此方法。
    • 使用映像中的 cloud-init 指示詞,以在每次建立 VM 時設定交換空間。

    使用 cloud-init 建立 .cfg 檔案以設定交換空間:

    sudo echo 'DefaultEnvironment="CLOUD_CFG=/etc/cloud/cloud.cfg.d/00-azure-swap.cfg"' >> /etc/systemd/system.conf
    sudo cat > /etc/cloud/cloud.cfg.d/00-azure-swap.cfg << EOF
    #cloud-config
    # Generated by Azure cloud image build
    disk_setup:
      ephemeral0:
        table_type: mbr
        layout: [66, [33, 82]]
        overwrite: True
    fs_setup:
      - device: ephemeral0.1
        filesystem: ext4
      - device: ephemeral0.2
        filesystem: swap
    mounts:
      - ["ephemeral0.1", "/mnt/resource"]
      - ["ephemeral0.2", "none", "swap", "sw,nofail,x-systemd.requires=cloud-init.service,x-systemd.device-timeout=2", "0", "0"]
    EOF
    
  7. 設定 cloud-init 來處理佈建:

    1. 設定 cloud-init 的 waagent

      sudo sed -i 's/Provisioning.Agent=auto/Provisioning.Agent=cloud-init/g' /etc/waagent.conf
      sudo sed -i 's/ResourceDisk.Format=y/ResourceDisk.Format=n/g' /etc/waagent.conf
      sudo sed -i 's/ResourceDisk.EnableSwap=y/ResourceDisk.EnableSwap=n/g' /etc/waagent.conf
      

      如果您要遷移特定的虛擬機器,但不想建立一般化映像,請在 /etc/waagent.conf 設定中設定 Provisioning.Agent=disabled

    2. 設定掛接:

      sudo echo "Adding mounts and disk_setup to init stage"
      sudo sed -i '/ - mounts/d' /etc/cloud/cloud.cfg
      sudo sed -i '/ - disk_setup/d' /etc/cloud/cloud.cfg
      sudo sed -i '/cloud_init_modules/a\\ - mounts' /etc/cloud/cloud.cfg
      sudo sed -i '/cloud_init_modules/a\\ - disk_setup' /etc/cloud/cloud.cfg
      
      
    3. 設定 Azure 資料來源:

      sudo echo "Allow only Azure datasource, disable fetching network setting via IMDS"
      sudo cat > /etc/cloud/cloud.cfg.d/91-azure_datasource.cfg <<EOF
      datasource_list: [ Azure ]
      datasource:
         Azure:
           apply_network_config: False
      EOF
      
    4. 如果您已設定一個分頁檔,則請移除現有的分頁檔:

      if [[ -f /mnt/resource/swapfile ]]; then
      echo "Removing swapfile" #RHEL uses a swap file by default
      swapoff /mnt/resource/swapfile
      rm /mnt/resource/swapfile -f
      fi
      
    5. 設定 cloud-init 記錄:

      sudo echo "Add console log file"
      sudo cat >> /etc/cloud/cloud.cfg.d/05_logging.cfg <<EOF
      
      # This tells cloud-init to redirect its stdout and stderr to
      # 'tee -a /var/log/cloud-init-output.log' so the user can see output
      # there without needing to look on the console.
      output: {all: '| tee -a /var/log/cloud-init-output.log'}
      EOF
      
  8. 執行下列命令以取消佈建虛擬機器。

    警告

    如果您要遷移特定的虛擬機器,但不想建立一般化映像,請略過取消佈建步驟。 執行 waagent -force -deprovision+user 命令會將來源機器轉譯為無法使用。 此步驟僅供您建立一般化映像。

    sudo rm -f /var/log/waagent.log
    sudo cloud-init clean
    sudo waagent -force -deprovision+user
    sudo rm -f ~/.bash_history
    sudo export HISTSIZE=0
    

    執行 waagent -force -deprovision 後,您可能會在 VirtualBox 上看到錯誤訊息:[Errno 5] Input/output error。 此錯誤訊息並不重要,您可以忽略此訊息。

  9. 關閉虛擬機器,並將 VHD 上傳至 Azure。

下一步

使用 Azure CLI 從自訂磁碟建立 Linux VM