Dieser Artikel ist ein Einstieg in die Nutzung von Terraform mit Proxmox VE. Sie erfahren alle notwendigen Informationen - von der Installation von Terraform bis hin zum ersten Deployment einer Proxmox-Ressource (VM).
Der grundsätzliche Workflow in Terraform mit Proxmox VE ist also nach erfolgreicher Einrichtung wie folgt:
Als Basis habe ich einen Debian 12 Container erstellt und danach Terraform mit folgenden Kommandos installiert:[1]
apt install curl unzip && curl -O https://releases.hashicorp.com/terraform/1.5.3/terraform_1.5.3_linux_amd64.zip && unzip terraform_1.5.3_linux_amd64.zip mv terraform /usr/local/bin
Zuerst muss in Proxmox VE ein API-Token erstellt werden, dies passiert auf Datacenter Ebene unter dem Punkt Permissions -> API-Tokens -> Add
. Wichtig ist, dass die Privilege Separation
für diesen Funktionstest auf No
gestellt ist, bzw. Sie bei der Erstellung des API Tokens den Haken nicht setzen. Bitte kopieren Sie sich den API-Key nach der Erstellung, da dieser danach nicht mehr nachträglich eingesehen werden kann. In unserem Fall ergeben sich dann folgende Credentials:
root@pam!terraform2 b057aea1-a092-49c3-b530-a53fd9e6fccc
Damit Terraform weiß, dass es Proxmox als Provider verwenden soll, muss eine provider.tf
-Datei erstellt werden:
touch provider.tf nano provider.tf
terraform { required_providers { proxmox = { source = "telmate/proxmox" version = "2.9.14" } } } variable "proxmox_api_url" { type = string } variable "proxmox_api_token_id" { type = string sensitive = true } variable "proxmox_api_token_secret" { type = string sensitive = true } provider "proxmox" { pm_api_url= var.proxmox_api_url pm_api_token_id = var.proxmox_api_token_id pm_api_token_secret = var.proxmox_api_token_secret pm_tls_insecure = true }
Zusätzlich muss sich Terraform nun mit dem API-User und API-Key gegenüber Proxmox VE authentifizieren, hier kann man sich an der folgenden Konfig-Datei credentials.auto.tfvars
orientieren und an die eigene Umgebung anpassen:
touch credentials.auto.tfvars nano credentials.auto.tfvars
proxmox_api_url = "https://10.2.1.130:8006/api2/json" proxmox_api_token_id = "root@pam!terraform2" proxmox_api_token_secret = "b057aea1-a092-49c3-b530-a53fd9e6fccc"
da in Terraform die Verwendung von Cloud-Images sinnvoll ist, ein kurzer Einblick, wie man ein solches Cloud-Image erstellt und modifiziert. Dazu wird auf dem Proxmox-Hypervisor ein Ubuntu Image runtergeladen und es wird das Paket libguestfs-tools
installiert, welches benötigt wird, um Anpassungen im Cloud-Image vornehmen zu können.[2]
cd /mnt/pve/cephfs/template/iso wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img && apt update -y && apt install libguestfs-tools -y && virt-customize -a /mnt/pve/cephfs/template/iso/jammy-server-cloudimg-amd64.img --install qemu-guest-agent && virt-customize -a /mnt/pve/cephfs/template/iso/jammy-server-cloudimg-amd64.img --root-password password:relation && virt-customize -a /mnt/pve/cephfs/template/iso/jammy-server-cloudimg-amd64.img --run-command "echo -n > /etc/machine-id"
Aus dem Cloud-Image jammy-server-cloudimg-amd64.img
wird nun ein VM-Template erzeugt:
qm create 9000 --name "ubuntu2204-ci" --memory 8096 --cores 2 --net0 virtio,bridge=vmbr0 && qm importdisk 9000 /mnt/pve/cephfs/template/iso/jammy-server-cloudimg-amd64.img vm_nvme && qm set 9000 --scsihw virtio-scsi-pci --scsi0 vm_nvme:vm-9000-disk-0 && qm set 9000 --boot c --bootdisk scsi0 && qm set 9000 --ide2 vm_nvme:cloudinit && qm set 9000 --serial0 socket --vga serial0 && qm set 9000 --agent enabled=1 && qm resize 9000 scsi0 +50G && qm template 9000
Zur Vollständigkeit auch anhand eines Debian 12 Images:
cd /mnt/pve/cephfs/cloudinit && wget https://cloud.debian.org/images/cloud/bookworm/20230723-1450/debian-12-generic-amd64-20230723-1450.raw && apt update -y && apt install libguestfs-tools -y && virt-customize -a /mnt/pve/cephfs/cloudinit/debian-12-generic-amd64-20230723-1450.raw --install qemu-guest-agent && virt-customize -a /mnt/pve/cephfs/cloudinit/debian-12-generic-amd64-20230723-1450.raw --root-password password:relation && virt-customize -a /mnt/pve/cephfs/cloudinit/debian-12-generic-amd64-20230723-1450.raw --run-command "echo -n > /etc/machine-id"
qm create 9001 --name "debian12-ci" --memory 8096 --cores 2 --net0 virtio,bridge=vmbr0 && qm importdisk 9001 /mnt/pve/cephfs/cloudinit/debian-12-generic-amd64-20230723-1450.raw vm_nvme && qm set 9001 --scsihw virtio-scsi-pci --scsi0 vm_nvme:vm-9001-disk-0 && qm set 9001 --boot c --bootdisk scsi0 && qm set 9001 --ide2 vm_nvme:cloudinit && qm set 9001 --serial0 socket --vga serial0 && qm set 9001 --agent enabled=1 && qm resize 9001 scsi0 +50G && qm template 9001
Das Virt-Customize Tool ist sehr umfangreich und kann unter Anderem folgende Optionen:
--run SCRIPT --touch FILE --firstboot SCRIPT --mkdir DIR --move SOURCE:DEST --install PKG,PKG --firstboot-install PKG,PKG --append-line FILE:LINE
Die Templates sind vorbereitet und man kann anhand dieser Templates nun beliebig viele VMs deployen, in dem folgenden Beispiel 4 sofort lauffähige VMs inklusiver IP-Konfiguration, Hostname usw. Dazu wurden 3 weitere Ressource-Dateien mit den Namen srv_demo_2.tf
, srv_demo_3.tf
und srv_demo_4.tf
angelegt und an unsere Bedürfnisse angepasst.
Danach kann man zum ersten Mal testen, ob Terraform auf den Proxmox Host zugreifen könnte via API. Dazu verwendet man terraform init
:
root@js-terraform-01:~# terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of telmate/proxmox from the dependency lock file - Using previously-installed telmate/proxmox v2.9.14 Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary. root@js-terraform-01:~#
Ziel von Terraform ist es, vereinfacht einzelne Ressourcen hochziehen zu können auf diversen Hypervisoren (in diesem Fall Proxmox VE). Dazu definiert man Terraform-Konfigdateien, welche beschreiben, wie die zu provisionierende Ressource auszusehen hat. Ein Beispiel der Datei srvdemo1.tf
Es wird ein Clone verwendet, dazu benötigen wir das VM-Template ubuntu2204-ci
, welches später anhand eines Cloud-Images erstellt wird.
touch srvdemo1.tf nano srvdemo1.tf
resource "proxmox_vm_qemu" "srv_demo_1" { name = "srv-demo-1" desc = "Ubuntu-Server" target_node = "PMX4" sshkeys = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj8ipwPHVSI/yvERzILBD52zL1jj6Ja3ptWlVhR0WK6ElBekwKL314Sps79xAitJb> agent = 1 clone = "ubuntu2204-ci" qemu_os = "l26" # this l26 is a small l like linux cores = 2 sockets = 1 cpu = "host" memory = 8096 scsihw = "virtio-scsi-pci" vga { type = "std" } disk { storage = "vm_nvme" type = "scsi" size = "83212M" discard = "on" ssd = "1" } network { bridge = "vmbr0" model = "virtio" } ## muss dem Template matchen os_type = "cloud-init" ipconfig0 = "ip=dhcp" nameserver = "192.168.110.61" ciuser = "tk" }
Es wird eine VM erstellt inklusive IP-Konfiguration, zusätzlich wird ein Cloud-Image verwendet, welches man an seine eigenen Bedürfnisse auch anpassen kann.
Mit terraform plan
kann man dann die VM mittels terraform planen lassen, das heißt es wird noch keine Ressource erzeugt, die Konfig-Datei und Verbindung zum Provider wird getestet und validiert.
root@js-terraform-01:~# terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # proxmox_vm_qemu.srv_demo_1 will be created + resource "proxmox_vm_qemu" "srv_demo_1" { + additional_wait = 5 + agent = 1 + automatic_reboot = true + balloon = 0 + bios = "seabios" + boot = (known after apply) + bootdisk = (known after apply) + ciuser = "tk" + clone = "ubuntu2204-ci" + clone_wait = 10 + cores = 2 + cpu = "host" + default_ipv4_address = (known after apply) + define_connection_info = true + desc = "Ubuntu-Server" + force_create = false + full_clone = true + guest_agent_ready_timeout = 100 + hotplug = "network,disk,usb" + id = (known after apply) + ipconfig0 = "ip=dhcp" + kvm = true + memory = 8096 + name = "srv-demo-1" + nameserver = "192.168.110.61" + onboot = false + oncreate = true + os_type = "cloud-init" + preprovision = true + reboot_required = (known after apply) + scsihw = "virtio-scsi-pci" + searchdomain = (known after apply) + sockets = 1 + ssh_host = (known after apply) + ssh_port = (known after apply) + sshkeys = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj8ipwPHVSI/yvERzILBD52zL1jj6JaSKoN1t1ftXEKbp+cuwZPUWykvSaR13ptWlVhR0WK6ElBekwKL314Sps79xAitJbbD35yDuMVtLUK/Bo+j2ehuWWmFZMwi1UKsPgCzF/YarsX12aCIS2Gyyf2NnscgOGlQKIdcgtfO23Xz18yxQxmFuRFVbFscd7gghRoQWsoKKwldbCKS8JEbXE8Mrb5mA7XD1C4dQLMnFvoJUvx3UqZinQHc20lWjqlZIOZ0uxRz6ssVFoCn+bKKNdf43JEnwPhcxQC2vGmKWunojNsXCifdx16fvd/wegXrdL8uw2oWUAvNsjCIUYCFn+VOn5JXEAxlXCAUNN9Z9H6/64QhwTjAXibwzB8Yj2+mGqd2ODy9ZIs+nzqxsmITA8+ayaEigZngol54f6vafmQzRHrM6Zn768UEYqEGb2LgYtI/0eTClO+E0HAPVfwpRwy6T1MhmIY8otSizE3PN3pg+fcyxv9oyMnxVsYCpspzE= root@js-terraform-01>" + tablet = true + target_node = "PMX4" + unused_disk = (known after apply) + vcpus = 0 + vlan = -1 + vmid = (known after apply) + disk { + backup = true + cache = "none" + discard = "on" + file = (known after apply) + format = (known after apply) + iops = 0 + iops_max = 0 + iops_max_length = 0 + iops_rd = 0 + iops_rd_max = 0 + iops_rd_max_length = 0 + iops_wr = 0 + iops_wr_max = 0 + iops_wr_max_length = 0 + iothread = 0 + mbps = 0 + mbps_rd = 0 + mbps_rd_max = 0 + mbps_wr = 0 + mbps_wr_max = 0 + media = (known after apply) + replicate = 0 + size = "83212M" + slot = (known after apply) + ssd = 1 + storage = "vm_nvme" + storage_type = (known after apply) + type = "scsi" + volume = (known after apply) } + network { + bridge = "vmbr0" + firewall = false + link_down = false + macaddr = (known after apply) + model = "virtio" + queues = (known after apply) + rate = (known after apply) + tag = -1 } + vga { + type = "std" } }
Mit terraform apply
können die Ressourcen dann erstellt werden, einmal mit yes
bestätigen und dann werden (in diesem Fall 4 VMs) deployed. Die Ausgabe wurden zur besseren Übersichtlichkeit gekürzt, sodass nur die vollständige Ausgabe von srv_demo_1
ausgegeben wird:
root@js-terraform-01:~# terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # proxmox_vm_qemu.srv_demo_1 will be created + resource "proxmox_vm_qemu" "srv_demo_1" { + additional_wait = 5 + agent = 1 + automatic_reboot = true + balloon = 0 + bios = "seabios" + boot = (known after apply) + bootdisk = (known after apply) + ciuser = "tk" + clone = "ubuntu2204-ci" + clone_wait = 10 + cores = 2 + cpu = "host" + default_ipv4_address = (known after apply) + define_connection_info = true + desc = "Ubuntu-Server" + force_create = false + full_clone = true + guest_agent_ready_timeout = 100 + hotplug = "network,disk,usb" + id = (known after apply) + ipconfig0 = "ip=dhcp" + kvm = true + memory = 8096 + name = "srv-demo-1" + nameserver = "192.168.110.61" + onboot = false + oncreate = true + os_type = "cloud-init" + preprovision = true + reboot_required = (known after apply) + scsihw = "virtio-scsi-pci" + searchdomain = (known after apply) + sockets = 1 + ssh_host = (known after apply) + ssh_port = (known after apply) + sshkeys = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj8ipwPHVSI/yvERzILBD52zL1jj6JaSKoN1t1ftXEKbp+cuwZPUWykvSaR13ptWlVhR0WK6ElBekwKL314Sps79xAitJbbD35yDuMVtLUK/Bo+j2ehuWWmFZMwi1UKsPgCzF/YarsX12aCIS2Gyyf2NnscgOGlQKIdcgtfO23Xz18yxQxmFuRFVbFscd7gghRoQWsoKKwldbCKS8JEbXE8Mrb5mA7XD1C4dQLMnFvoJUv= root@js-terraform-01>" + tablet = true + target_node = "PMX4" + unused_disk = (known after apply) + vcpus = 0 + vlan = -1 + vmid = (known after apply) + disk { + backup = true + cache = "none" + discard = "on" + file = (known after apply) + format = (known after apply) + iops = 0 + iops_max = 0 + iops_max_length = 0 + iops_rd = 0 + iops_rd_max = 0 + iops_rd_max_length = 0 + iops_wr = 0 + iops_wr_max = 0 + iops_wr_max_length = 0 + iothread = 0 + mbps = 0 + mbps_rd = 0 + mbps_rd_max = 0 + mbps_wr = 0 + mbps_wr_max = 0 + media = (known after apply) + replicate = 0 + size = "83212M" + slot = (known after apply) + ssd = 1 + storage = "vm_nvme" + storage_type = (known after apply) + type = "scsi" + volume = (known after apply) } + network { + bridge = "vmbr0" + firewall = false + link_down = false + macaddr = (known after apply) + model = "virtio" + queues = (known after apply) + rate = (known after apply) + tag = -1 } + vga { + type = "std" } } # proxmox_vm_qemu.srv_demo_2 will be created # proxmox_vm_qemu.srv_demo_3 will be created # proxmox_vm_qemu.srv_demo_4 will be created Plan: 4 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes proxmox_vm_qemu.srv_demo_4: Creating... proxmox_vm_qemu.srv_demo_2: Creating... proxmox_vm_qemu.srv_demo_3: Creating... proxmox_vm_qemu.srv_demo_1: Creating... ... proxmox_vm_qemu.srv_demo_4: Creation complete after 39s [id=PMX4/qemu/103] proxmox_vm_qemu.srv_demo_3: Creation complete after 47s [id=PMX4/qemu/101] proxmox_vm_qemu.srv_demo_1: Creation complete after 49s [id=PMX4/qemu/102] proxmox_vm_qemu.srv_demo_2: Creation complete after 53s [id=PMX4/qemu/104] Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Autor: Jonas Sterr Ich beschäftige mich mit den Themen Software Defined Storage, Proxmox Virtualisierung auf Basis von KVM, QEMU & Ceph im Produktmanagement der Thomas-Krenn.AG in Freyung. Proxmox ist meine absolute Leidenschaft und ich freue mich gerne über Kontaktanfragen und einen Austausch auf LinkedIn.
|