部署到 vSphere 時,靜態 IP 位址需要 Cloud Assembly 產生 vSphere 自訂規格,這可能會影響 cloud-init 命令。

問題

  • Cloud Assembly 雲端範本包含 assignment: static,可將靜態 IP 位址套用至 vSphere 虛擬機器。
  • 此雲端範本還包含 cloudConfig 區段,其中包括使用 cloud-init 執行的初始化命令。
  • 若要為虛擬機器提供靜態 IP,Cloud Assembly 會動態產生要套用的 vSphere 自訂規格。
  • 每當套用自訂規格時,最後一個作業將會重新啟動虛擬機器。
  • 自訂規格不知道 cloud-init 命令正在執行中,因此,重新啟動操作會中斷這些命令。
  • cloud-init 命令僅在首次開機時執行,並且在中斷後不會自動復原。
  • 產生的虛擬機器僅保持部分設定狀態。

因應措施

建立包含定時停用 cloud-init 的機器範本。然後,根據範本部署機器,以便自訂規格和重新啟動能夠先於 cloud-init 執行。

範例程序 - Ubuntu 18.04

下列步驟適用於 Ubuntu 18.04。您可能需要進行調整,使此處顯示的構想適用於其他 Linux 版本或產品。

  1. 建立虛擬機器,並使用您所需的版本更新和套件使其保持最新狀態。

    請注意,其他 Linux 產品可能並未預先安裝 cloud-init,但 Ubuntu 18.04 已預先安裝。

  2. 重新設定 cloud-init,將資料來源設定為 OVF。

    sudo dpkg-reconfigure cloud-init

  3. 編輯以下檔案。

    /etc/cloud/cloud.cfg

    1. 新增以下行以啟用傳統客體作業系統自訂 (GOSC)。

      disable_vmware_customization: true

    2. 請確保網路組態已啟用。刪除停用設定或為其添加註解 (如果存在)。
      network:
        # config: disabled

      或者,檢查下列目錄中的所有組態檔。

      /etc/cloud/cloud.cfg.d/*

      刪除包含 network: {config: disabled} 設定的任何檔案。

  4. 編輯以下檔案。

    /usr/lib/tmpfiles.d/tmp.conf

    • 透過為設定添加註解,防止清除暫存目錄。

      # D /tmp 1777 root root –

  5. 編輯以下檔案。

    /lib/systemd/system/open-vmtools.service

    • 透過在 [Unit] 區段下新增以下行,將 open-vmtools 設定為在 dbus.service 之後啟動。

      After=dbus.service

  6. 建立新的空白檔案,該檔案將停用 cloud-init。

    sudo touch /etc/cloud/cloud-init.disabled

  7. 建立 re_init.sh 指令碼。在針對自訂規格暫停的 cron 工作延遲後,指令碼會重新啟用並初始化 cloud-init。
    sudo rm -rf /etc/cloud/cloud-init.disabled
    sudo cloud-init init
    sleep 20
    sudo cloud-init modules --mode config
    sleep 20
    sudo cloud-init modules --mode final
  8. 將指令碼設定為可執行檔。

    sudo chmod +x re_init.sh

  9. 建立將在啟動時睡眠 90 秒後執行的 cron 工作。輸入 crontab -e,然後輸入下列內容:

    @reboot ( sleep 90 ; sh /script_path/delay_init.sh )

    如果完成自訂規格和重新啟動需要更長的時間,則可以套用 90 秒以上。

  10. 建立用於清理範本的 cleaner.sh 指令碼。將 cloudadmin 取代為在作業系統安裝期間設定的您自己的使用者。

    此範例指令碼是特定於 Ubuntu 的。若要為其他 Linux 產品建立指令碼,請務必包含反白顯示的必要區段。

    #!/bin/bash
    
    # Add usernames to add to /etc/sudoers for passwordless sudo users=("ubuntu" "cloudadmin") for user in "${users[@]}" do cat /etc/sudoers | grep ^$user RC=$? if [ $RC ! = 0 ]; then bash -c "echo \"$user ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers" fi done
    
    #grab Ubuntu Codename
    codename="$(lsb_release -c | awk {'print $2}')"
    
    
    #Stop services for cleanup
    service rsyslog stop
    
    #clear audit logs
    if [ -f /var/log/audit/audit.log ]; then
    cat /dev/null > /var/log/audit/audit.log
    fi
    if [ -f /var/log/wtmp ]; then
    cat /dev/null > /var/log/wtmp
    fi
    if [ -f /var/log/lastlog ]; then
    cat /dev/null > /var/log/lastlog
    fi
    
    #cleanup persistent udev rules
    if [ -f /etc/udev/rules.d/70-persistent-net.rules ]; then
    rm /etc/udev/rules.d/70-persistent-net.rules
    fi
    
    #cleanup /tmp directories
    rm -rf /tmp/*
    rm -rf /var/tmp/*
    
    #cleanup current ssh keys
    #rm -f /etc/ssh/ssh_host_*
    
    #cat /dev/null > /etc/hostname
    
    #cleanup apt
    apt-get clean
    
    #Clean Machine ID truncate -s 0 /etc/machine-id rm /var/lib/dbus/machine-id ln -s /etc/machine-id /var/lib/dbus/machine-id #Clean Cloud-init cloud-init clean --logs --seed
    
    #cleanup shell history
    history -w
    history -c
    
  11. 將範本清理指令碼設定為可執行檔。

    sudo chmod +x cleaner.sh

  12. 在 Ubuntu 18.04 中,清理指令碼需要 root 權限。編輯以下檔案。

    /etc/ssh/sshd_config

    1. 請確保可以切換為 root 使用者。

      PermitRootLogin yes

    2. 為根使用者設定密碼。

      sudo passwd root

  13. 執行清理指令碼。

    sudo ./script_path/cleaner.sh

  14. (選用) 出於安全性考慮,請還原步驟 12 以防進一步的 root 登入。
  15. 關閉虛擬機器,然後使用 vSphere 將其轉換為範本。

範本更新

cron 工作會在您每次更新範本時執行。如果更新所需的時間超過延遲時間 (例如 90 秒),則需要重新新增 /etc/cloud/cloug-init.disabled 檔案,並在關閉範本前重新執行清理指令碼。否則,在首次開機時將不會停用 cloud-init,且自訂規格重新啟動會恢復以中斷 cloud-init 命令。

疑難排解

如果您懷疑 vSphere 自訂規格會阻止 cloud-init 完成,請暫時停用自訂規格,並確定 cloud-init 是否可以按預期完成。若要暫時停用自訂規格,請使用 customizationGuestOs: false 內容。

    properties:
      image: ubuntu
      cpuCount: 1
      totalMemoryMB: 8192
      customizationGuestOs: false