Zum Inhalt springen
Serkan Köse
Akzent

Homelab: Proxmox

Single-Node-Proxmox-Homelab, komplett mit Ansible provisioniert. Vom preseedeten Debian-Installer bis zu laufenden Kubernetes-Clustern: ZFS für Storage, cloud-init für VM-Templates, Kubespray für die Cluster.

ansibleproxmoxkuberneteskubesprayzfscloud-init
Quellcode

Überblick

Infrastructure as Code für meine Proxmox Node, von der nackten Maschine bis zum laufenden Kubernetes-Cluster. Jeder Schritt ist ein eigenes Playbook oder eine Role, alles idempotent.

Credits

Das Proxmox-Setup nutzt die Role lae.proxmox, ZFS die Role mrlesmithjr.zfs, beide in requirements.yml gepinnt und über ansible-galaxy installiert. Die Cluster werden mit Kubespray bootstrapped. Die Build-Technik für das Preseed-ISO (Initrd per cpio neu packen, mit xorriso re-mastern) habe ich von Paul Lockabys Preseed-Projekt übernommen und in eine Ansible-Rolle gepackt.

Stack & Architektur

  • Ansible für Host- und VM-Provisioning
  • Proxmox VE als Hypervisor
  • ZFS als Storage
  • Debian Preseed für den Bare-Metal-Installer
  • cloud-init mit Ubuntu-Cloud-Images für die VM-Templates
  • Kubespray für Kubernetes
  • go-task als Task-Runner, verwaltet über mise
  • yamllint und ansible-lint, über GitHub Actions und pre-commit
  • Renovate für automatisierte Dependency-Updates

Bare Metal: Die Role debian_preseed_iso baut aus einem Debian-Netinst-ISO einen preseedeten Installer. Locale, Netzwerk, Root-Account und SSH-Keys kommen aus Variablen; die Role rendert die Config und kapselt das Build-Skript. Ergebnis ist ein Root-only-Host mit vmbr0-Bridge, fertig für Proxmox.

Host: ZFS-Pools und Proxmox werden über zwei Playbooks konfiguriert. Erst ZFS, dann Proxmox VE darauf, inklusive PCIe/IOMMU-GPU-Passthrough für die RTX 3060 (OVMF, vfio, Treiber-Blacklist).

Templates: Die Role proxmox_cloudinit_template lädt ein Ubuntu-Cloud-Image, prüft die SHA-256-Checksumme, resized es und kapselt es in eine VM mit cloud-init-Vendor-Snippet, dann wird daraus ein Template. Es gibt drei Templates: ein generisches, ein Kubernetes-fertiges (Swap aus, Kernel-Module, Sysctls) und ein NVIDIA/AI-Dev-Template.

VMs: Die Role proxmox_vm klont ein Template (Full Clone), setzt das Sizing, resized die Disk und wendet cloud-init-Netzwerk- und User-Config an. Damit werden die Kubernetes-Nodes und die Dev-VM provisioniert.

Cluster: Ein Taskfile steuert Kubespray im offiziellen Container-Image. Ein Inventory pro Cluster unter inventory/kubespray/. Es gibt Targets zum bootstrappen der Cluster, für Upgrades und um die kubeconfig von der ersten Control-Plane-Node zu holen.

Storage

Ein Pool-Layout, drei Rollen. zpool_k8s sind vier Samsung-SATA-SSDs als zwei Mirror-Vdevs, gestriped (für Kubernetes-PVs, per Proxmox-csi). zpool_nvme ist eine einzelne 1-TB-NVMe für die VM-Disks. zpool_backup ist eine 2-TB-HDD. Properties pro Dataset (Compression, Recordsize, atime) und ARC-Limits werden im Playbook gesetzt.

Dependency-Automatisierung

Renovate (.renovaterc.json5) hält die externen Roles, die GitHub Actions, die pre-commit-Hooks und die Kubespray-Version aktuell. Die Bumps bekommen Kontext direkt im PR. Bei Kubespray merged ein Workflow den Upstream-Sample-Diff per 3-Wege-Merge in die customizten group_vars und postet die Release-Notes der Versionen dazwischen. Bei den Roles lae.proxmox und mrlesmithjr.zfs kommentiert ein Workflow den defaults/main.yml-Diff und markiert, welche der von mir gesetzten Variablen entfernt, umbenannt oder mit geändertem Default kommen.

Geplant

  • Die RTX 3060 tatsächlich nutzen: GPU-Passthrough in eine Workload-VM
  • Deklarative Backups für die ZFS-Pools