準備 Linux 以在 Azure 中進行映像處理

適用於:✔️ Linux 虛擬機 ✔️ 彈性規模設定

Azure 平台服務等級協議(SLA)僅適用於運行 Linux 作業系統的虛擬機(VM),前提是你使用經授權的發行版之一。 對於經授權的發行版,Azure Marketplace 提供預先設定的 Linux 映像檔。 欲了解更多資訊,請參閱:

所有在 Azure 上運行的其他發行版,包括社群支援與非背書發行版,都有一些先決條件。

本文著重於在 Azure 上運行 Linux 發行版的一般指引。 這篇文章無法全面說明,因為每個分布都不同。 即使你符合本文所述的所有條件,你可能還是需要大幅調整你的 Linux 系統才能正常運作。

一般 Linux 安裝說明

Important

本文中遠端 NVMe 準備步驟為可選。 僅當您建立的映像打算與遠端 NVMe 磁碟控制器搭配部署時,才完成這些設定。 如果目標虛擬機使用 SCSI,則跳過所有標示為遠端 NVMe 的步驟,保留標準設定。 遠端 NVMe 需要第二代映像檔及支援的作業系統版本。 確認目標虛擬機容量的 DiskControllerTypes 精確能力,並檢視 支援遠端 NVMe 的作業系統映像檔。 不要只從 VM 系列世代推斷控制器類型。

  • Azure不支援 Hyper-V 虛擬硬碟(VHDX)格式。 Azure 只支援固定 VHD。 你可以使用 Hyper-V Manager 或 Convert-VHD 指令檔將光碟轉換成 VHD 格式。 如果你用的是 VirtualBox,建立磁碟時請選擇 固定大小 ,而不是預設的動態分配大小。

  • Azure 支援第一代(BIOS 開機)和第二代(UEFI 開機)虛擬機。

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

  • VHD 的最大允許容量為 1,023 GB。

  • 安裝 Linux 系統時,我們建議使用標準分割區,而非邏輯磁碟管理器(LVM)。 LVM 是許多安裝的預設選項。

    使用標準分割區可避免與複製虛擬機發生 LVM 名稱衝突,特別是當作業系統磁碟連接到另一台相同虛擬機進行故障排除時。 你可以在資料磁碟上使用 LVM 或 RAID 。

  • 核心支援掛載使用者定義函式(UDF)檔案系統是必要的。 在 Azure 首次開機時,配置設定會透過附加在訪客上的 UDF 格式媒體傳遞到 Linux 虛擬機。 Azure Linux 代理程式必須掛載 UDF 檔案系統以讀取其設定並配置虛擬機。

  • Linux 核心版本 2.6.37 之前,在 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 型核心的系統,必須在 numa=off 的核心命令列中設定開機參數 。 如需詳細資訊,請參閱 Red Hat KB 436883 \(英文\)。

  • 不要在作業系統磁碟上設定交換分割區。 你可以設定 Linux 代理程式在臨時資源磁碟上建立交換檔案,詳情請參考本文後續說明。

  • 所有 Azure 上的 VHD 都必須具有與 1 MB (1024 x 1024 位元組) 相符的虛擬大小。 當你從原始光碟轉換成 VHD 時,請確保原始光碟大小是 1 MB 的倍數,這點在本文後面會說明。

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

  • 移除使用者與系統帳號、公鑰、敏感資料、不必要的軟體及應用程式。

Note

Cloud-init 版本 21.2 或更新版本則移除了 UDF 的要求。 但若未啟用 udf 模組,CD-ROM 在佈建期間將無法掛載,因此無法套用自訂資料。 一個變通方法是套用使用者資料。 然而,與自訂資料不同的是,使用者資料並未加密。 欲了解更多資訊,請參閱 cloud-init 文件中的 使用者資料格式 。

不使用 Hyper-V 安裝核心模組

Azure 運行在 Hyper-V 虛擬機管理程式上,因此 Linux 需要特定核心模組才能在 Azure 中執行。 如果你的虛擬機是Hyper-V外建立的,Linux 安裝程式可能不會在初始 RAM 磁碟(initrd 或 initramfs)中包含 Hyper-V 的驅動程式,除非虛擬機偵測到它正在運行 Hyper-V 環境。

當您使用不同的虛擬化系統(例如 VirtualBox 或 KVM)來準備 Linux 映像檔時,可能需要重建 initrd,讓至少 hv_vmbus 和 hv_storvsc 核心模組可在初始 RAM 磁碟中使用。 這個已知問題主要發生在基於上游 Red Hat 發行版的系統,甚至可能還有其他系統。

重建 initrd 或 initramfs 影像的機制會因分布而異。 請參閱您的發行版文件,或聯絡技術支援以取得正確的處理程序。 這裡有一個用 mkinitrd 工具重建 initrd 的例子:

  1. 備份現有的 initrd 映像檔:

    cd /boot
    sudo cp initrd-`uname -r`.img  initrd-`uname -r`.img.bak
    
  2. 透過使用 hv_vmbus 和 hv_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 Manager 主控台或 Resize-VHD PowerShell 指令碼來調整虛擬機大小。 如果你不是在Windows環境下運行,我們建議使用 qemu-img 來轉換(如有需要)並調整 VHD 大小。

Note

QEMU 2.2.1 版及部分後續版本中的 qemu-img 存在已知錯誤,會導致產生格式不正確的 VHD。 這個問題在 QEMU 2.6 中已經修正。 我們建議使用版本 2.2.0 或更早版本,或使用版本 2.6 或更新版本。

  1. 使用工具 (例如qemu-img或vbox-manage) 直接重新調整 VHD 的大小可能會導致 VHD 無法開機。 我們建議先使用以下程式碼將 VHD 轉換成原始磁碟映像檔。

    如果虛擬機映像檔是以原始磁碟映像檔建立,你可以跳過這個步驟。 在某些虛擬機監控程式(如 KVM)中,預設會將虛擬機映像建立為原始磁碟映像檔。

    sudo qemu-img convert -f vpc -O raw MyLinuxVM.vhd MyLinuxVM.raw
    
  2. 計算磁碟映像所需的大小,使虛擬大小對齊於 1 MB。 以下 Bash Shell 指令碼使用 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 整合服務(LIS)驅動程式直接貢獻給上游的 Linux 核心。 許多包含近期 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/

虛擬機的主動核心必須包含以下修補程式。 這份清單無法涵蓋所有發行版。

Azure Linux 代理程式

Azure Linux Agent(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 Agent 必須為或高於 最低支援版本。

Note

確保 udf 和 vfat 模組都已啟用。 停用模組 udf 會導致配置失敗。 停用模組 vfat 會導致配置和開機失敗。 Cloud-init 版本 21.2 或更新版本可在以下條件同時存在的情況下,無需 UDF 即可配置虛擬機:

  • 你是用 SSH 公鑰而不是密碼來建立虛擬機。
  • 你沒有提供任何自訂資料。

一般 Linux 系統需求

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

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

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

    rhgb quiet crashkernel=auto
    

    圖形化和靜音開機在雲端環境下沒什麼用,因為你希望所有日誌都傳送到序列埠。 如果需要,你可以保留 crashkernel 設定,但這個參數會讓虛擬機的可用記憶體減少至少 128 MB。 對於較小的虛擬機來說,減少可用記憶體可能會有問題。

  2. 編輯完 /etc/default/grub 後,重新建立 GRUB 設定。 只執行適合你發行版的指令。

    針對基於 Debian 或 Ubuntu 的發行版,請執行:

    sudo update-grub
    

    對於提供 grub2-mkconfig,例如 RHEL、Oracle Linux 和 SUSE 的發行版,請執行:

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    

    在提供 grub-mkconfig 的發行版上,請執行:

    sudo grub-mkconfig -o /boot/grub/grub.cfg
    

    GRUB 的設定路徑會因 UEFI 安裝而有所不同。 如果你的發行版使用另一條路徑,請使用該發行版所記錄的路徑。

  3. 將 Hyper-V 模組加入初始的 RAM 磁碟。 只執行與你發行版所用工具相符的程序。

    1. 若是使用 dracut 的發行版,請執行:
    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"
    
    1. 對於使用 mkinitramfs 的發行版,請執行此程序,而非 Dracut 程序:
    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
    
  4. 只有當你要為遠端 NVMe 磁碟控制器建立映像檔時,才要設定並確認 NVMe 開機支援。 否則,請略過此步驟。 具體指令會因分布而異。

    1. 用你發行版的方法,用 NVMe 驅動重新建立 initramfs。

      對於基於 dracut 的發行版,請讓 NVMe 驅動程式在未來的 initramfs 映像中持續存在,並重建目前的 initramfs:

      sudo mkdir -p /etc/dracut.conf.d
      printf '%s\n' 'add_drivers+=" nvme nvme_core "' | sudo tee /etc/dracut.conf.d/azure-nvme.conf
      sudo dracut --force
      

      對於基於 initramfs 工具的發行版,請將 NVMe 驅動程式設為持久化,並重建 initramfs:

      printf '%s\n' nvme nvme_core | sudo tee -a /etc/initramfs-tools/modules
      sudo update-initramfs -u -k all
      
    2. 在現有的核心命令列/etc/default/grub中加入 nvme_core.io_timeout=240 ,然後使用適合你發行版的指令重建 GRUB 配置。

    3. 確認系統上兩個 NVMe 驅動模組皆可用。 執行兩個指令:

      modinfo nvme
      modinfo nvme_core
      

      每個指令必須回傳其模組的資訊。 如果找不到任何模組,請依照你發行版的文件安裝或啟用,再繼續使用。

    4. 確認兩個 NVMe 驅動程式都包含在 initramfs 中。 只執行適用於你的發行版本的指令。

      對於以 dracut 為基礎的發行版,請執行:

      sudo lsinitrd /boot/initramfs-$(uname -r).img | grep -E 'nvme(_core)?\.ko'
      

      若是使用 initramfs-tools 的發行版,請執行:

      sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'nvme(_core)?\.ko'
      

      輸出必須同時顯示 nvme 和 nvme_core 兩個驅動程式。 如果不行,請參考你發行版的文件,並在繼續前重建初始的 RAM 磁碟。

  5. 確定您已安裝 SSH 伺服器,並已設定為在開機時啟動。 這種配置通常是預設的。

  6. 安裝 Azure Linux 代理程式。

    若要在 Azure 上佈建 Linux 映像,必須使用 Azure Linux Agent 代理程式。 許多發行版提供 .rpm 或 .deb 套件形式的代理程式。 該封包通常稱為 WALinuxAgent 或 walinuxagent。 你也可以依照 Azure Linux 代理指南 的步驟手動安裝代理程式。

    Note

    確保 udf 和 vfat 模組都已啟用。 移除或停用它們會導致配置或開機失敗。 Cloud-init 版本 21.2 或更新版本則移除了 UDF 的要求。

    安裝 Azure Linux 代理程式、cloud-init 及其他必要的工具。 只執行你系統上可用的套件管理器指令。

    對 dnf,請執行:

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

    如果您的系統提供的是 yum 而不是 dnf,請在前述指令中將 dnf 替換為 yum。

    若要針對 apt,請執行:

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

    若為 zypper,請執行:

    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
    
  7. 不要在作業系統磁碟上建立交換空間。

    你可以使用 Azure Linux 代理程式或 cloud-init,透過本地資源磁碟設定交換空間。 Azure 在配置後會將這個資源磁碟附加到虛擬機上。 本地資源磁碟是暫時性的,當虛擬機被取消配置時可能會被清空。

    Important

    無論遠端磁碟控制器是 SCSI 還是 NVMe,這些指令都適用。 它們需要包含本地暫存資源磁碟的虛擬機大小。 遠端磁碟控制器類型並不決定是否有資源磁碟可用。

    1. 選擇並設定一種管理交換空間的方法。

      要使用 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 來處理配置,並防止 Azure Linux 代理程式格式化資源磁碟或建立交換空間:

      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
      
    2. 如果你選擇了 cloud-init,請選擇如何提供交換配置。

      你可以在每次建立虛擬機器時,透過 customdata 傳送 cloud-init 設定內容。 用這個方法。

      或者,可以在映像檔中加入 cloud-init 指令,讓每次建立虛擬機時都會設定交換空間。 使用此方法時,請建立一個 .cfg 檔案:

      echo 'DefaultEnvironment="CLOUD_CFG=/etc/cloud/cloud.cfg.d/00-azure-swap.cfg"' | sudo tee -a /etc/systemd/system.conf
      cat << EOF | sudo tee /etc/cloud/cloud.cfg.d/00-azure-swap.cfg
      #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
      
  8. 設定 cloud-init 來處理配置:

    1. 設定 waagent 以使用 cloud-init:

      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
      

      如果你要遷移特定虛擬機,不想建立通用映像檔,可以在 Provisioning.Agent=disabled 設定中設定。

    2. 設定掛接:

      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 資料來源:

      echo "Allow only Azure datasource, disable fetching network setting via IMDS"
      cat << EOF | sudo tee /etc/cloud/cloud.cfg.d/91-azure_datasource.cfg
      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 記錄:

      echo "Add console log file"
      cat << EOF | sudo tee -a /etc/cloud/cloud.cfg.d/05_logging.cfg
      
      # 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
      
  9. 在取消虛擬機器配置前,請先驗證磁碟掛載設定。 此驗證適用於 SCSI 及遠端 NVMe 映像檔。

    1. 檢視 /etc/fstab。 不要使用像 /dev/sd* 或 /dev/nvme*這樣的裝置名稱,因為裝置名稱可能會在重啟或磁碟控制器更換時改變。 改用檔案系統的 UUID 或其他持久識別碼。

      列出區塊裝置及其持久識別碼,以便與以下 /etc/fstab條目進行比較:

      sudo blkid
      
    2. 檢查 /etc/fstab 是否有語法錯誤、無效的掛載選項,以及無法解析的參照:

      sudo findmnt --verify --verbose
      
    3. 只有在為遠端 NVMe 磁碟控制器建立映像檔時,才需確認所設定的 I/O 逾時值。 如果來源虛擬機目前使用 NVMe,請執行:

      cat /sys/module/nvme_core/parameters/io_timeout
      

      值必須是 240。 SCSI 來源虛擬機可能不會暴露此執行時參數;此時,請確認 GRUB 配置中存在該 nvme_core.io_timeout=240 ,且重建後的配置是否包含該設定。

  10. 執行以下指令來解除虛擬機器的配置。

    注意事項

    如果您要移轉特定的虛擬機器,且不想建立一般化映像,則可跳過解除佈建步驟。 執行該指令 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
    

    在 VirtualBox 中,執行 waagent -force -deprovision 後,你可能會看到一則顯示為 [Errno 5] Input/output error 的錯誤訊息。 這個錯誤訊息並不嚴重,你可以忽略它。

  11. 關閉虛擬機,然後把 VHD 上傳到 Azure。

下一步

使用 Azure CLI

對於需要從 SCSI 轉移到 NVMe 的現有 Azure 虛擬機,請使用 Convert Linux 和 Windows 虛擬機從 SCSI 轉到 NVMe。 有關架構與支援資訊,請參閱 NVMe 概述。