19.Februar 2025
In diesem Artikel möchte ich euch Packer vorstellen – das Open-Source-Tool von HashiCorp, das es ermöglicht, automatisiert und konsistent Maschinen-Images für unterschiedliche Plattformen zu erstellen. Wie bereits in meinem Artikel „Testumgebung mit Vagrant“ angekündigt, widmen wir uns heute einem tieferen Einblick in Packer. Dabei erfahrt ihr nicht nur, welche Vorteile Packer bietet, sondern auch, wie ihr mit Hilfe eines HCL-Templates ein Image für Proxmox erstellt und dieses anschließend mit Ansible konfiguriert. Tauchen wir ein in die Welt der Automatisierung und entdecken, wie Packer den Aufbau moderner IT-Infrastrukturen vereinfacht.
2. Warum Proxmox und warum ein Template?
Warum Proxmox?
Proxmox VE ist eine beliebte Open-Source-Virtualisierungsplattform, die häufig zum Einsatz kommt. Es bietet sowohl KVM-basierte virtuelle Maschinen als auch LXC-Container, was für eine flexible Nutzung der Hardware sorgt.
Warum ein Template?
Ein Template ist ein vorinstalliertes, vorkonfiguriertes Image, das als Basis für weitere virtuelle Maschinen dient. Die Vorteile im Überblick:
-
Zeitsparend: Neue VMs können schnell aus dem Template erstellt werden, ohne dass der gesamte Installationsprozess wiederholt werden muss.
-
Konsistenz: Alle Instanzen, die aus dem Template hervorgehen, sind identisch aufgebaut. Das reduziert Fehler und erleichtert Wartung und Updates.
-
Automatisierung: Mit Tools wie Packer und Ansible lässt sich die Erstellung und Konfiguration von Templates vollständig automatisieren – ideal für moderne IT-Infrastrukturen.
Im nächsten Abschnitt erkläre ich Schritt für Schritt, wie wir mit Packer ein solches Template für Proxmox erstellen.
3. Ablauf mit Packer
Der Automatisierungsprozess mit Packer läuft in mehreren klar definierten Schritten ab:
-
VM-Erstellung und Boot: Zunächst erstellt Packer eine virtuelle Maschine. In diese VM wird ein CD-Image eingebunden, das das nötige Installationsmedium enthält. Packer startet dann die Maschine und wartet auf das Boot-Menü.
-
Boot-Parameter und Preseed: Sobald das Boot-Menü erscheint, gibt Packer automatisch die notwendigen Parameter ein. Diese Parameter veranlassen den internen Webserver, der in Packer integriert ist, eine Preseed-Datei zu laden.
- Preseed-Datei: In dieser Datei sind alle Details zur OS-Installation festgelegt – von der Partitionierung über die Einrichtung von Benutzern bis hin zur Installation der gewünschten Software. Am Ende der Installation wird außerdem ein spezieller Ansible-User angelegt und ein SSH-Public-Key übermittelt.
-
Provisionierung: Nachdem die Grundinstallation des Betriebssystems abgeschlossen ist, kommen die Provisioner ins Spiel. Hier gibt es verschiedene Möglichkeiten, beispielsweise die Nutzung eines Shell- oder Ansible-Provisioners. In meinem Artikel zeige ich ein konkretes Beispiel, wie Ansible genutzt wird, um die Maschine weiter zu konfigurieren und anzupassen.
-
Image-Erstellung: Nachdem alle Provisioner-Schritte abgeschlossen sind, erstellt Packer das endgültige Image. Dieses Image enthält das vollständig installierte und konfigurierte Betriebssystem, das als Vorlage für weitere virtuelle Maschinen dient.
Dieser strukturierte Ablauf stellt sicher, dass die Installation reproduzierbar, automatisiert und konsistent abläuft – ein wesentlicher Vorteil, wenn man schnell und zuverlässig neue virtuelle Maschinen aufbauen möchte.
4. Einführung in das HCL Template
Im Folgenden werde ich das HCL-File, das den gesamten Packer-Workflow abbildet, Schritt für Schritt erläutern. Dabei zeige ich, wie die einzelnen Komponenten – von den benötigten Plugins über lokale Variablen bis hin zu den Konfigurationsblöcken für Proxmox und Ansible – zusammenwirken, um ein automatisiertes, wiederverwendbares Template zu erstellen. So bekommt ihr einen umfassenden Einblick, wie ihr mit Packer in Verbindung mit Proxmox und Ansible eine vollständig automatisierte VM-Erstellung und -Konfiguration realisieren könnt.
Image-Erstellung:
Nachdem alle Provisioner-Schritte abgeschlossen sind, erstellt Packer das endgültige Image. Dieses Image enthält das vollständig installierte und konfigurierte Betriebssystem, das als Vorlage für weitere virtuelle Maschinen dient. In meinem Beispiel erstellen wir ein Basis Debian Template mit Cloud-Init, das euch einen schnellen Einstieg in die Automatisierung und Standardisierung eurer Infrastruktur ermöglicht.
1. packer { required_plugins { … } }
In diesem Block definierst du, welche Plugins Packer benötigt und welche Versionen verwendet werden sollen:
proxmox Plugin:
1 proxmox = {
2 version = ">= 1.1.2"
3 source = "github.com/hashicorp/proxmox"
4 }
Dieses Plugin ermöglicht es Packer, mit Proxmox zu kommunizieren und virtuelle Maschinen zu erstellen. Die angegebene Version (>= 1.1.2) stellt sicher, dass eine Version verwendet wird, die die benötigten Features bereitstellt.
ansible Plugin:
1 ansible = {
2 version = "~> 1"
3 source = "github.com/hashicorp/ansible"
4 }
Mit diesem Plugin wird die Integration von Ansible als Provisioner möglich. So kannst du nach der Erstellung der VM automatisierte Konfigurationen über Ansible ausführen.
2. locals
Im locals-Block legst du lokale Variablen fest, die du innerhalb Deines Templates nutzen kannst.
1locals {
2 http_directory = "${path.root}/http"
3}
Hier definierst du den Pfad zu einem Verzeichnis (http_directory), das du später beispielsweise für den HTTP-Server benötigst, der die Preseed-Datei bereitstellt. Das ermöglicht dir, den Pfad zentral zu ändern, falls sich das Verzeichnis verschiebt.
3. source “proxmox-iso” “basebox”
Der source-Block beschreibt die Konfiguration der VM, die erstellt werden soll. Einige wichtige Punkte:
Proxmox-Verbindung:
1 proxmox_url = "https://proxmox-api-url:8006/api2/json"
2 username = "user@pam!packer"
3 token = "46xxxxc-2427-48ed-98e0-dxxxxxx691e"
4 insecure_skip_tls_verify = true
5
6 node = "pve01"
Diese Blöcke definieren die Netzwerkkonfiguration und den Speicher der VM. Du legst fest, über welchen Bridge das Netzwerk angebunden wird, welchen Festplattentyp (hier raw auf einem ZFS-Pool) und welchen SCSI-Controller verwendet wird.
Netzwerk und Storage:
1 network_adapters {
2 bridge = "vmbr1"
3 firewall = false
4 model = "virtio"
5 }
6
7 disks {
8 disk_size = "30G"
9 format = "raw"
10 io_thread = true
11 storage_pool = "local-zfs"
12 type = "scsi"
13 }
14 scsi_controller = "virtio-scsi-single"
Diese Blöcke definieren die Netzwerkkonfiguration und den Speicher der VM. Du legst fest, über welchen Bridge das Netzwerk angebunden wird, welchen Festplattentyp (hier raw auf einem ZFS-Pool) und welchen SCSI-Controller verwendet wird.
ISO und Boot-Konfiguration:
1 iso_file = "local:iso/debian-12.9.0-amd64-netinst.iso"
2 http_directory = "${path.root}/http"
3 http_interface = "enx00249b286b4c"
4 boot_command = [
5 "<wait1><esc><wait1>",
6 "auto ",
7 "priority=critical ",
8 "preseed/interativ=true ",
9 "DEBCONF_DEBUG=5 ",
10 "preseed/url=http://{{.HTTPIP}}:{{.HTTPPort}}/debian12-preseed.cfg ",
11 "<enter><wait>"
12 ]
Hier wird das ISO-Image definiert, das als Installationsmedium dient.
- Mit boot_command gibst du an, welche Tasteneingaben automatisiert werden, um den Bootvorgang anzustoßen und den Installer mit den entsprechenden Parametern zu starten.
- Dabei wird u.a. der Pfad zur Preseed-Datei angegeben, die über den in Packer integrierten HTTP-Server bereitgestellt wird.
Weitere Einstellungen:
1 unmount_iso = true
2 qemu_agent = true
3 cloud_init = true
4 cloud_init_storage_pool = "local-zfs"
Diese Parameter optimieren den Installationsprozess, beispielsweise durch Deaktivieren des ISO-Mounts nach Installation, Aktivierung des QEMU-Agenten und Integration von Cloud-Init-Funktionen.
Hardware- und OS-Spezifikationen:
1 vm_name = "debian129"
2 cpu_type = "x86-64-v2-AES"
3 os = "l26"
4 memory = "8196"
5 cores = "1"
6 sockets = "2"
7 template_name = "debian129-template"
8 ssh_timeout = "15m"
9 ssh_password = "ansible"
10 ssh_username = "ansible"
Hier definierst du die Hardwareparameter (CPU, Memory, Cores, Sockets) sowie Details zur Ziel-VM wie den Namen und das Betriebssystem. Am Ende der Installation wird ein SSH-Zugang mit dem Benutzer ansible eingerichtet, was für die spätere Provisionierung genutzt wird.
4.build
Der build-Block fasst den gesamten Prozess zusammen und definiert, welche Schritte ausgeführt werden sollen:
Quellen-Angabe:
1 sources = ["source.proxmox-iso.basebox"]
Dies verweist auf den zuvor definierten source-Block. Es wird also die VM gemäß dieser Konfiguration erstellt.
Provisionierung mit Ansible:
1 provisioner "ansible" {
2 user = "ansible"
3 playbook_file = "./playbook.yml"
4 extra_arguments = [ "-vvvv" ]
5 }
Nachdem die Grundinstallation der VM abgeschlossen ist, wird mit diesem Provisioner das Ansible-Playbook ausgeführt.
- Der Benutzer ansible wird hierbei verwendet, um die SSH-Verbindung aufzubauen.
- Mit extra_arguments kannst du zusätzliche Optionen an Ansible übergeben (hier im Beispiel für einen erhöhten Detailgrad in den Logs).
Sobald das Playbook seine Konfiguration abgeschlossen hat, erstellt Packer das finale Image – das Template, das du dann für den Einsatz in deiner Proxmox-Umgebung nutzen kannst.
Kurzer Überblick über das Ansible-Playbook
Im obigen Beispiel-Playbook wird die Provisionierung des Images mittels Ansible durchgeführt. Das Playbook umfasst folgende Schritte:
1---
2- name: Provision Image
3 hosts: all
4 gather_facts: no
5 become: true
6 become_user: root
7
8 tasks:
9 - name: Create Cloud Init Configuration
10 ansible.builtin.template:
11 src: templates/cloud.cfg.j2
12 dest: /etc/cloud/cloud.cfg
Erklärung der einzelnen Bestandteile:
-
Playbook-Header: Das Playbook beginnt mit der Definition eines Plays, das auf alle Hosts angewandt wird. Mit gather_facts: no wird die Erfassung von Systeminformationen deaktiviert, um den Prozess zu beschleunigen. Die Anweisungen become: true und become_user: root sorgen dafür, dass alle Tasks mit Root-Rechten ausgeführt werden.
-
Task: Create Cloud Init Configuration (Template anpassen): In dem einzigen definierten Task wird das ansible.builtin.template Modul verwendet, um eine Template-Datei (templates/cloud.cfg.j2) zu bearbeiten und nach /etc/cloud/cloud.cfg zu kopieren. Dieses Template ermöglicht die Konfiguration der Cloud-Init Einstellungen des Systems.
5. Template-Erstellung für Proxmox
Bevor wir den eigentlichen Build-Prozess starten, müssen wir zunächst sicherstellen, dass alle erforderlichen Plugins installiert sind. Dazu führen wir den folgenden Befehl aus:
1packer init template.hcl
Dieser Befehl lädt und installiert alle in der HCL-Datei definierten Plugins (z. B. für Proxmox und Ansible). Sobald dieser Schritt abgeschlossen ist, starten wir den automatisierten Build-Prozess:
1packer build template.hcl
Mit diesem Befehl wird die VM erstellt, die ISO eingebunden, die Preseed-Datei geladen und die weiteren Konfigurationen via Ansible durchgeführt. Nach erfolgreichem Abschluss des Build-Prozesses wird das Template – beispielsweise unter dem Namen „debian129-template“ – in Proxmox hinterlegt.
In Proxmox könnt Ihr dieses Template dann als Basis nutzen, um startbare VMs zu klonen – entweder als Linked Clone oder als Full Clone. Zudem erlaubt die Cloud-Init-Konfiguration in Proxmox, weitere Einstellungen wie Benutzer, SSH-Schlüssel oder Netzwerke individuell anzupassen.
Fazit
Mit diesem Ansatz zeige ich, wie sich Packer, Proxmox und Ansible zu einer leistungsstarken Automatisierungslösung verbinden läst. Anhand des Beispiels haben ich demonstriert, wie ein Basis-Debian-Template mit Cloud-Init erstellt wird – von der Definition der Konfiguration in HCL, über die Einbindung einer Preseed-Datei und die Ausführung eines Ansible-Playbooks bis hin zur finalen Template-Erstellung in Proxmox. Mit nur einem CLI-Befehl (packer build template.hcl) könnt ihr nun ein konsistentes und voll funktionsfähiges Image bauen, das als Grundlage für zahlreiche virtuelle Maschinen dient. Dieses Vorgehen spart nicht nur Zeit, sondern sorgt auch für eine standardisierte und zuverlässige Infrastruktur.
Die vollständige Konfiguration inklusive Ansible, Cloud-Init und Preseed-Datei findet ihr in meinem GitHub Repository.