Terraform + Cloud-Init 透過 extra_config 和 DataSourceVMware

Terraform + Cloud-Init 透過 extra_config 和 DataSourceVMware

問題:

有沒有人成功使用 terraform + extra_config + Ubuntu 雲端映像與 Cloud Init 交互,提供元資料/使用者資料?我希望這能與 DataSourceVMware 交互,但現階段還不能確定。

我一直在做什麼:

我正在使用 Terraform 在 VMware vSphere 7 上部署 Ubuntu 雲端映像。

... below code snipped from resource "vsphere_virtual_machine" "vm" { }

vapp {
    properties = {
        hostname = var.vm_Name_Lower
        instance-id = var.vm_Name_Lower
        user-data = base64encode(file("${path.module}/userdata.yml"))
    }
}

但任何使用 extra_config 的嘗試都失敗了。我希望能夠提供 guestinfo.metadata 和 guestinfo.userdata。但目前,我對元資料的測試(如下所示)似乎失敗了,因為虛擬機器中未設定主機名稱:

data "cloudinit_config" "metadata" {
    gzip = true
    base64_encode = true
    part {
        content_type = "text/cloud-config"
        content = <<-EOF
            local-hostname: testvm
            instance-id: testvm
        EOF
    }
}

... below code snipped from resource "vsphere_virtual_machine" "vm" { }

extra_config = {
    "guestinfo.metadata" = data.cloudinit_config.metadata.rendered
    "guestinfo.metadata.encoding" = "gzip+base64"
}

我可以看到 vSphere 日誌條目來證明 extra_config 已傳送:

config.extraConfig("guestinfo.metadata"): (key = "guestinfo.metadata", value = "H4sIAAAAAAAA/2SOTUvGMBCE74H8h/De11dPQsSDHz14qIK ... snipped

參考:

版本詳情:

Client system (on which terraform is run): Ubuntu 20.04.3 LTS
ESXi: 7.0.2 / Build: 18538813
vCenter Server: 7.0.2 / Build: 18455184
Cloud Image: https://cloud-images.ubuntu.com/impish/current/impish-server-cloudimg-amd64.ova
Terraform v1.0.7
on linux_amd64
provider registry.terraform.io/hashicorp/template v2.2.0
provider registry.terraform.io/hashicorp/vsphere v1.24.3

答案1

問題是,預設情況下,cloud-init 在新的 VMware 資料來源之前呼叫 OVF 資料來源提供者(從 cloud-init 21.3 開始)。 Terraform 提供 OVF 資料來源提供者喜歡的數據,因此它會處理這些資訊。這解釋了為什麼 vApp 屬性「用戶資料」接受雲端配置。

解決方案是從 cloud-init 中刪除 OVF 資料來源提供者:

  1. [網頁瀏覽器[ 下載 OVA:https://cloud-images.ubuntu.com/impish/current/impish-server-cloudimg-amd64.ova
  2. [VC UI] 從 OVF 部署,接受預設值(磁碟配置除外,使用精簡配置)。
  3. [VC UI] 編輯設定/VM 選項/啟動選項/啟動延遲 = 2000ms。
  4. [VC UI] 開啟虛擬機器控制台。
  5. [虛擬機器控制台] 開啟虛擬機器電源。
  6. [VM Console] 在 BIOS 畫面上按住 Shift 鍵(強制 GRUB 顯示選單)。
  7. [虛擬機器控制台] 選擇 Ubuntu 的進階選項。
  8. [VM Console] 選擇最新的核心版本,末尾帶有「(恢復模式)」。
  9. [VM Console] 選擇“root / Drop to root shell提示”
  10. [虛擬機器控制台]按回車進行維護
  11. [VM 控制台] # dpkg-重新設定 cloud-init
  12. [VM Console] 取消選取 VMware 和 None 以外的所有內容
  13. [虛擬機器控制台] # cloud-init clean
  14. [虛擬機器控制台] # shutdown -h now
  15. [VC UI] 編輯設定/VM 選項/啟動選項/啟動延遲 = 0ms。
  16. [VC UI] 轉換為模板

答案2

對 Ubuntu 雲 OVA 進行同樣的操作,我發現了一些解決方法。這並不理想,因為它涉及重新啟動,這意味著您需要一個local-exec配置程式來檢測實例何時實際完成,但它可以工作。

假設您有兩個用於使用者資料的 yaml 檔案 - 第一個檔案是透過名為 vApp Properties 傳遞的vapp-userdata.yaml,第二個檔案是透過名為 VMware 資料來源傳遞的guest-userdata.yaml

Terraform 中有類似的東西

  vapp {
    properties = {
      user-data = base64encode(data.template_file.vapp_userdata[count.index].rendered)
    }
  }

  extra_config = {
    "guestinfo.metadata"          = base64encode(data.template_file.guest-metadata[count.index].rendered)
    "guestinfo.metadata.encoding" = "base64"
    "guestinfo.userdata"          = base64encode(data.template_file.userdata.rendered)
    "guestinfo.userdata.encoding" = "base64"
  }

vapp-userdata.yaml可以執行一個write_file操作來覆寫當前資料來源定義並OVF在您已經到達該點時將其刪除。

write_files:
  - path: /etc/cloud/cloud.cfg.d/90_dpkg.cfg
    owner: root:root
    permissions: "0644"
    content: |
      datasource_list: [ VMware, None ]

然後在底部重新啟動完成

power_state:
  timeout: 600
  mode: reboot

當虛擬機器在最後一個命令後重新啟動時,它將讀取VMware新的 cloud-init 配置中定義的資料來源,並處理您的資料guest-userdata.yaml來源(metadata.yaml如果您也定義了該資料來源)。

至於檢測它何時完成,我仍在嘗試找出最好的方法。最簡單的方法是從nc -l 12345的末尾開始guest-userdata.yaml,並讓本機設定程式在可以連接到 時繼續tcp/12345,但這會讓您開啟一個tcp/12345不太理想的 netcat 偵聽器。

如果您找到更好的方法,請回覆:)

編輯

絕對會有更好的方法來做到這一點,但是...

在底部guest-userdata.yaml

runcmd:
  - mkdir -p /mnt/sharedfolder
  - sysctl -w vm.overcommit_memory=1
  - sysctl -w kernel.panic=10
  - sysctl -w kernel.panic_on_oops=1
  - curl https://releases.rancher.com/install-docker/${docker_version}.sh | sh
  - usermod -aG docker ubuntu
  - nc -l 1234 & ncpid=$!  #start nc and get PID
  - sleep 20
  - kill $ncpid #kill PID once Terraform has had time to connect

.tf然後作為文件末尾的配置者

  provisioner "local-exec" {
    # Wait for cloud-init userdata cmds
    # Netcat: z (scan port only), w1 (wait 1 second)
    command = "count=0; until $(nc -zw1 ${self.default_ip_address} 1234); do sleep 1; count=`expr $count + 1`; done"
  }

相關內容