Kubernetes, hier im speziellen K3S läuft leider nicht ohne Probleme auf ZFS. Der zugehörige Bug wurde bereits 2021 geschlossen und das Thema leider nicht weiter bearbeitet. Um dennoch K3S in meinem Proxmox zum laufen zu bekommen, habe ich den hier vorgestellten Workaround gefunden.
LVM-over-ZFS in Proxmox einrichten
Zuerst erzeuge ich ein ZFS Volume auf dem ZFS-Pool, welches als Root-Filesystem für den LXC-Container verwendet werden soll. Das Volume sollte eine geeignete Größe haben, ich verwende hier 100 GB.
#> zfs create -V 100G rpool/lvmroot
Proxmox installiert einen LVM-Filter, welcher verhindert, dass ZFS-Volumes als LVM verwendet werden können. Dieser muss angepasst werden. Dazu ist zunächst die ID des ZFS-Volumes zu ermitteln:
#> ls -al /dev/zvol/rpool/lvmroot lrwxrwxrwx 1 root root 10 Apr 20 20:52 /dev/zvol/rpool/lvmroot -> ../../zd32
Die ID hier ist „zd32“. Der Filter ist ganz unten in /etc/lvm/lvm.conf definiert. Dieser muss wie folgt angepasst werden:
# Filter vorher: global_filter=["r|/dev/zd.*|"] # Angepasster Filter: global_filter=["a|/dev/zd32|","r|/dev/zd.*|"]
Nun kann auf dem ZFS Volume eine physisches LVM Volume angelegt werden und eine LVM Volume Group erstelt werden:
#> pvcreate /dev/zvol/rpool/lvmroot Physical volume "/dev/zvol/rpool/lvmroot" successfully created. #> vgcreate lvmroot /dev/zvol/rpool/lvmroot Volume group "lvmroot" successfully created
Die Volume-Group wird sofort in der Weboberfläche von Proxmox unter PVE->Disks->LVM sichtbar. Diese kann nun als Storage für LCX-Root-Dateisysteme konfiguriert werden.
Unter Datacenter -> Storage wird dazu ein neues Storage hinzugefügt. Als Type wird „LVM“ ausgewählt. Als ID wähle ich „local-lvm“ (analog zum bestehenden Storage „local-zfs“). Das Storage wird auf der existierenden Volume Group „lvmroot“ erzeugt. Als content wähle ich hier nur „Container“.
LXC-Container erzeugen
Nun kann ich meinen Container erzeugen, in dem ich nachher K3S installieren möchte. Als Storage wähle ich „local-lvm“ aus. Außerdem deaktiviere ich das Häkchen bei „Unprivileged container“. Alle anderen Einstellungen wähle ich wie bei jedem anderen Container (d.h. ich bleibe im Grunde bei den Standard-Einstellungen). Als System installiere ich ein Debian 11.
Bevor ich das System starte, muss ich auf dem Proxmox-Host noch die Konfiguration anpassen, damit systemd sauber im privilegierten Container läuft. Dazu editiere ich die Datei /etc/pve/lxc/105.conf (mein Container hat die ID 105) und füge die folgenden Zeilen hinzu.
lxc.apparmor.profile: unconfined lxc.cgroup.devices.allow: a lxc.cap.drop: lxc.mount.auto: "proc:rw sys:rw"
Im Ergebnis erhalte ich ein System auf einem ext4-Filesystem, auf welchem K3S sauber laufen sollte. Ich boote den Container, logge ein und überprüfte noch, dass das Root-FS wirklich vom Typ ext4 ist:
root@homehost:~#> mount /dev/mapper/lvmroot-vm--105--disk--0 on / type ext4 (rw,relatime,stripe=2) [...]
K3S installieren
Auf dem Proxmox-Host lade ich das Modul „br_netfilter“, welches für das Kubernetes Networking relevant ist und mache das Laden des Modules persistent:
#> modprobe br_netfilter #> echo br_netfilter >> /etc/modules
Nun installiere ich K3S im Container und erzeuge ein paar Verzeichnisse und Symlinks. Ich möchte damit erreichen, dass alle Dateien von K3S unter /k3s liegen. Den Ordner nehme ich später ins Backup auf.
root@homehost:~# apt -y install curl root@homehost:~# curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_ENABLE=true sh - root@homehost:~# mkdir -p /etc/rancher/k3s /k3s root@homehost:~# touch /k3s/config.yaml root@homehost:~# ln -s /k3s/config.yaml /etc/rancher/k3s/config.yaml
Die Konfigurationsdatei /k3s/config.yaml sieht bei mir wie folgt aus:
data-dir: /k3s write-kubeconfig: /k3s/kubeconfig default-local-storage-path: /data/k3s/volumes disable-helm-controller: true disable: - traefik tls-san: - "homehost"
Unter /data/k3s/volumes binde ich später ein ZFS-Volume ein, auf dem die Volumes der Kubernetes-Dienste liegen werden.
Als letztes muss ich noch dafür sorgen, dass Kubernetes auf /dev/kmsg schreiben kann. Das Devices, welches zu Loggen verwendet wird, exstiert in LXC leider nicht. Die Option „lxc.kmsg = 1“ wird von Proxmox nicht unterstützt. Am einfachsten ist es, /dev/kmsg auf /dev/console zu linken. Dies geschieht persistent durch einen Eintrag in tempfiles.d:
root@homehost:~# ln -s /dev/console /dev/kmsg root@homehost:~# echo 'L /dev/kmsg - - - - /dev/console' > /etc/tmpfiles.d/kmsg.conf
Jetzt kann ich K3S starten und in den Logs prüfen, dass alles sauber hochfährt:
root@homehost:~# systemctl enable --now k3s; journalctl -f -u k3s root@homehost:~# kubectl get pods --namespace kube-system
K3S läuft, ich kann beginnen, Anwendungen darin zu deployen.