extra_config 및 DataSourceVMware를 통한 Terraform + Cloud-Init

extra_config 및 DataSourceVMware를 통한 Terraform + Cloud-Init

질문:

terraform + extra_config + Ubuntu 클라우드 이미지를 사용하여 Cloud Init과 인터페이스하고 메타데이터/사용자 데이터를 제공하는 데 성공한 사람이 있나요? 이것이 DataSourceVMware와 상호 작용할 수 있기를 바라지만 현 단계에서는 확신할 수 없습니다.

내가 한 일:

저는 Terraform을 사용하여 VMware vSphere 7에 Ubuntu 클라우드 이미지를 배포하고 있습니다. vApp 속성을 사용하는 것은 충분히 쉽습니다.

... 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를 모두 제공하고 싶습니다. 그러나 현재 메타데이터(아래 참조)를 사용한 테스트는 호스트 이름이 VM에 설정되지 않았기 때문에 실패한 것으로 나타났습니다.

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"
}

extra_config가 전송되었음을 증명하는 vSphere 로그 항목을 볼 수 있습니다.

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 데이터 소스(cloud-init 21.3 기준) 이전에 호출된 OVF 데이터 소스 공급자가 있다는 것입니다. Terraform은 OVF 데이터 소스 공급자가 좋아하는 데이터를 제공하므로 정보를 처리합니다. 이는 vApp 속성 "user-data"가 cloud-config를 허용하는 이유를 설명합니다.

해결 방법은 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] VM 콘솔을 엽니다.
  5. [VM 콘솔] VM 전원을 켭니다.
  6. [VM 콘솔] BIOS 화면에서 Shift 키를 누르고 있습니다(GRUB가 메뉴를 표시하도록 함).
  7. [VM 콘솔] Ubuntu 고급 옵션을 선택합니다.
  8. [VM 콘솔] 끝에 "(복구 모드)"가 있는 최신 커널 버전을 선택합니다.
  9. [VM 콘솔] "root / 루트 쉘 프롬프트에 놓기"를 선택합니다.
  10. [VM 콘솔] 유지 관리를 위해 Enter 키를 누르세요.
  11. [VM 콘솔] # dpkg-reconfigure cloud-init
  12. [VM 콘솔] VMware 및 None을 제외한 모든 항목을 선택 취소합니다.
  13. [VM 콘솔] # cloud-init clean
  14. [VM 콘솔] # shutdown -h 지금
  15. [VC UI] 설정 편집 / VM 옵션 / 부팅 옵션 / 부팅 지연 = 0ms.
  16. [VC UI] 템플릿으로 변환

답변2

Ubuntu 클라우드 OVA에서도 동일한 작업을 수행하여 이에 대한 약간의 해결 방법을 찾았습니다. 재부팅이 필요하기 때문에 이상적이지는 않습니다. 즉, local-exec인스턴스가 실제로 완료되는 시기를 감지하려면 프로비저너가 필요하지만 작동합니다.

사용자 데이터에 사용하는 두 개의 yaml 파일이 있다고 가정해 보겠습니다. 첫 번째 파일은 이름이 vApp 속성으로 전달 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_fileOVF

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마지막 명령 후 VM이 재부팅되면 새 cloud-init 구성에 정의된 대로 데이터 소스를 읽고 사용자 guest-userdata.yamlmetadata.yaml정의한 경우 이를 처리합니다.

작업이 언제 완료되는지 감지하는 데 있어서는 여전히 최선의 방법을 찾으려고 노력 중입니다. 쉬운 방법은 nc -l 12345끝에서 시작하여 guest-userdata.yaml연결할 수 있을 때 진행되는 로컬 프로비저너를 갖지만 이상적이지 않은 tcp/12345netcat 리스너를 열어 두는 것입니다 .tcp/12345

더 좋은 방법을 찾으시면 답변 부탁드립니다 :)

편집하다

더 나은 방법이 분명 있겠지만...

하단에는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"
  }

관련 정보