Terraform mit Proxmox VE Tutorial

Aus Thomas-Krenn-Wiki
Zur Navigation springen Zur Suche springen

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).

Überblick

Der grundsätzliche Workflow in Terraform mit Proxmox VE ist also nach erfolgreicher Einrichtung wie folgt:

  1. Terraform installieren
  2. Proxmox API-Token erstellen: für den Zugriff von Terraform zu Proxmox VE
  3. Terraform Provider erstellen: Terraform mitteilen, dass Proxmox VE das Deployment-Ziel ist
  4. Cloud-Init-Image erstellen: für einfacheres und vollständiges Deployment inklusive IP-Adresse
  5. Terraform Ressourcen erstellen oder modifizieren
  6. Terraform Init: Terraform testet die Verbindung zum Provider
  7. Terraform Plan: Terraform zeigt die geplanten Änderungen an
  8. Terraform Apply: Terraform deployed/modifiziert die Ressourcen

Terraform Installation

Terraform Installation

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

API Token erstellen in PVE

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

Terraform Konfiguration

Terraform Provider erstellen

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
}

API Credentials hinterlegen

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"

Cloudinit unter Proxmox VE

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]

Cloudinit Image erstellen (Ubuntu 22.04)

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"

Template erstellen (Ubuntu 22.04)

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

Cloudinit Image erstellen (Debian 12)

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"

Template erzeugen (Debian 12)

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

Virt-Customize

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

Überblick in Proxmox VE

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.

Terraform-Container und die beiden Templates (9000) und (9001)

Terraform Workflow

Terraform Init

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:~# 

Terraform Ressource erstellen

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.

Terraform Plan

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

Terraform Apply

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.
Terraform provisioniert Proxmox VMs

Weitere Informationen

Einzelnachweise

  1. Terraform Installation (developer.hashicorp.com)
  2. virt-customize - Customize a virtual machine (libguestfs.org)


Foto Jonas Sterr.jpg

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.


Das könnte Sie auch interessieren

Proxmox ISO Upload
Proxmox VM löschen
Wake On LAN Proxmox - Konfiguration inkl. BIOS