ZFS macht keinen Spaß mit wenig RAM – aber es lohnt sich
Wenn du deine erste VM auf einem frisch installierten Proxmox-Node startest und plötzlich die gesamte Systemantwort verlangsamt wird, hast du wahrscheinlich einen klassischen ZFS-IRC (Initial RAM Consumption) erlebt. Ich nenne es liebevoll „Denkpause des Hypervisors“. Der Kernel stoppt einfach kurz alles, um seine internen Datenstrukturen zu initialisieren. Keine Sorge – dein Server brennt nicht durch und du musst auch keine neuen SSDs kaufen. Aber es ist der Moment, in dem dir bewusst wird: ZFS ist kein gewöhnlicher Dateisystem-Plugin, das man per Knopfdruck aktiviert und dann vergessen kann. Es ist ein komplettes Storage-Subsystem, das eng mit dem Linux-Kernel verwoben ist, eigene Caching-Algorithmen implementiert und speicherhungrig sein kann wie ein junger Entwickler nach seinem ersten Energy Drink.
In diesem Artikel zeige ich dir, wie du ZFS in deinem Proxmox-Cluster wirklich produktionsreif konfigurierst. Wir reden über sinnvolle Dataset-Hierarchien, effizientes Snapshotting und vor allem darüber, wie du den Adaptive Replacement Cache (ARC) zähmst, damit dein Host nicht in den Swap ausläuft, wenn die VMs loslegen. Keine Theorie ohne Praxis – wir schauen uns echte Befehle an, die du direkt in deiner Shell ausprobieren kannst.
Warum ZFS im Produktivbetrieb anders tickt
Im Homelab oder Testumfeld funktioniert ZFS oft wie von Zauberhand. Du erstellst einen ZPool aus ein paar SATA-Festplatten, legst eine VM an und voila – Daten sind da. Im echten Betrieb jedoch gibt es Faktoren, die dich unerwartet treffen können. Schreibverstärkung bei SSDs, Fragmentierung bei großen Dateien, oder das ominöse Problem, dass dein Host anfängt zu swapen, obwohl noch genug RAM frei scheint. Das liegt am ARC – einem intelligenten, aber gierigen Cachesystem, das versucht, so viel wie möglich im Arbeitsspeicher vorzuhalten.
Persönliche Einschätzung: Viele Admins unterschätzen, wie viel RAM ZFS braucht. Die Faustregel „4 GB pro TB Speicher“ gilt nur, wenn du keine deduplizierten Daten nutzt. In der Realität solltest du mindestens 8 GB freibleibenden RAM für den ARC einplanen, besonders wenn du viele kleine Dateien hostest oder komprimierte Virtual Machine Disks betreibst. Ignoriere das auf eigene Gefahr – ich habe schon Nodes gesehen, die wegen ungebändigtem ARC mitten in der Nacht abstürzten.
Die richtige Struktur: Von zpools bis datasets
Bevor du überhaupt eine VM anlegst, brauchst du eine klare Strategie für deine Speicherschichten. Ein großer Pool, in dem alles schwimmt, ist der schnellste Weg zu Chaos. Stattdessen solltest du verschiedene zpools für verschiedene Zwecke nutzen – zum Beispiel einen schnellen NVMe-Pool für die virtuellen Festplatten und einen langsameren SATA-Pool für Backups und weniger kritische Daten.
Innerhalb eines Pools kommen dann Datasets ins Spiel. Diese funktionieren ähnlich wie Partitionen in einer klassischen Welt, bieten dir aber zusätzliche Flexibilität. So kannst du einzelnen Datasets spezifische Eigenschaften zuweisen, etwa Komprimierung oder Quotas, ohne den gesamten Pool zu beeinflussen.
Konkrete Umsetzung: Pool und Datasets erstellen
Nehmen wir an, du hast zwei NVMe-Laufwerke (/dev/nvme0n1 und /dev/nvme1n1) und möchtest daraus einen Mirror-Pool namens faststorage erstellen. Dann erstellst du darin zwei Datasets: eines für die virtuellen Festplatten (vm-disks) und eines für Templates (templates).
# Pool erstellen (mirror raid)
zfpool create -o ashift=12 faststorage /dev/nvme0n1 /dev/nvme1n1
# Dataset für VM-Discs erstellen
zfs create -o compression=lz4 faststorage/vm-disks
# Dataset für Templates
zfs create -o quota=50G faststorage/templates
Wichtig ist hier der Parameter -o ashift=12. Er sagt ZFS, dass deine Laufwerke 4K-Sektoren haben (was bei modernen SSDs Standard ist). Ohne diese Angabe könnte ZFS suboptimal schreiben und deine Lebensdauer unnötig verkürzen. Die Komprimierung via lz4 ist fast immer empfehlenswert – sie reduziert I/O, verschlüsselt nichts und verbraucht minimal CPU-Zeit. Bei vielen Workloads sparst du dadurch 20–30% Platz ohne spürbaren Performanceverlust.
Mit quota=50G sicherst du außerdem, dass das Template-Dataset nicht versehentlich den gesamten Pool auffrisst. Solche Begrenzungen gehören in jede Produktivumgebung hinein, egal ob du Container oder VMs hostest.
Persönliche Einschätzung: Ich sehe zu oft, dass Leute alle ihre VM-Images einfach in das Root-Dataset ihres Pools packen. Das ist ein Rezept für Unordnung. Nutzt stattdessen eine Hierarchie wie tank/vms, tank/lxc und tank/backups. Spätestens wenn du später mal einen Pool migrieren musst, wirst du dir selbst danken, dass du sauber getrennt hast. Und ja – Quotas sind gut, aber beachte: Sie werden nicht sofort hart enforced. Wenn eine VM schneller schreibt als das Dataset synchronisiert, kann es kurzzeitig Überschreitungen geben. Plane daher etwas Puffer ein.
Snapshots: Deine Zeitmaschine für VMs
Einer der größten Vorteile von ZFS sind Kopier-bei-Schreiben-Snapshots. Du kannst einen momentanen Zustand deines Datasets festhalten, ohne additionalen Speicherplatz zu belegen – solange sich nichts ändert. Erst wenn neue Daten geschrieben werden, wächst der Snapshot-Baum an. Das macht Recovery extrem schnell und platzsparend, vorausgesetzt, du verstehst die Mechanik dahinter.
Manuelle und automatische Snapshots
Für Tests oder vor großen Änderungen ist ein manueller Snapshot ideal:
# Snapshot erstellen
zfs snapshot faststorage/vm-disks@pre-update
# Alle bestehenden Snapshots auflisten
zfs list -t snapshot
# Snapshot wiederherstellen (Achtung: überschreibt aktuelle Daten!)
zfs rollback faststorage/vm-disks@pre-update
In der Produktion willst du das natürlich automatisieren. Proxmox bietet dafür integrierte Werkzeuge, aber manchmal reicht die UI nicht aus – etwa wenn du granulare Intervalle pro Dataset willst oder Inkrementelle Backups zu einem entfernten Standort schickst.
Dafür kannst du ein kleines Skript schreiben, das via Cronjob läuft:
#!/bin/bash
POOL="faststorage"
DS="vm-disks"
SNAP_NAME="autobackup-$(date +%Y%m%d_%H%M%S)"
# Snapshot erstellen
zfs snapshot ${POOL}/${DS}@${SNAP_NAME}
# Alte Snapshots löschen (nur letzte 7 behalten)
zfs destroy $(zfs list -H -t snapshot -o name -s creation | grep "^${POOL}/${DS}@" | head -n -7)
Speichere das als /usr/local/bin/zfs-snap-clean.sh, mache es ausführbar (chmod +x) und füge es deinem Crontab hinzu (crontab -e):
0 */6 * * * /usr/local/bin/zfs-snap-clean.sh
Damit erzeugst du alle sechs Stunden einen Snapshot und hältst maximal sieben zurück. Mehr Flexibilität als die Standard-Proxmox-Rotation, die oft nur täglcih oder wöchentlich greift.
Persönliche Einschätzung: Vorsicht beim automatischen Löschen! Ich hatte einmal einen Job, der fälschlich alle Snapshots eines ganzen Pools löschte – inklusive jener, die noch von laufenden Clones referenziert wurden. Das Ergebnis war ein korrupter ZFS-Pool und drei Schlaflose Nächte. Daher meine Empfehlung: Teste solche Skripte immer erst auf einer Kopie oder mit dem dry-run-Modus von Tools wie sanoid oder zfs-auto-snapshot, die genau dafür gebaut wurden und deutlich robuster gegen menschliche Fehler sind.
ARC-Tuning: Den Arbeitsspeicher-Greedy domänen
Der Adaptive Replacement Cache (ARC) ist ZFS’ Geheimwaffe für leselastige Workloads. Er lernt Zugriffsmuster und hält häufig genutzte Blöcke im RAM bereit. Klingt toll – bis dein Server beginnt zu swapen, weil der ARC mehr als 80% deines physischen Speichers beansprucht hat. Besonders bei kleineren Nodes (< 16GB RAM) wird das schnell zum Problem, da ZFS standardmäßig aggressiv cacht.
Glücklicherweise kannst du das Verhalten über Sysctl-Parameter steuern. Zwei sind besonders wichtig:
-
vfs.zfs.arc_max: Obergrenze für die Gesamtgröße des ARC (in Bytes) -
vfs.zfs.target: Zielgröße, bei der ZFS versucht, stabil zu bleiben (normalerweise etwas niedriger als arc_max)
Um zu sehen, wie viel RAM dein ARC aktuell frisst, führe folgenden Befehl aus:
arcstat
Das Tool zeigt dir Echtzeitwerte inkl. Hitrate. Eine gute Hitrate liegt zwischen 80–95%. Wenn sie unter 70% fällt, entweder hast du zufällige Zugriffe (dann hilft caching sowieso kaum) oder dein Cache ist zu klein.
Dauerhaftes Tuning unter Proxmox
Standardmäßig setzt Proxmox den ARC-Max-Wert ziemlich hoch. Um ihn zu begrenzen, erstelle eine eigene Konfigurationsdatei unter /etc/sysctl.d/99-zfs-arc-limit.conf:
# Beschränkt ARC auf maximal 4 GB
vfs.zfs.arc_max = 4294967296
# Setzt das Ziel etwas tiefer, um Schwankungen Raum zu geben
vfs.zfs.target = 3758096384
Anschließend lädst du die Änderungen mit sysctl -p /etc/sysctl.d/99-zfs-arc-limit.conf oder starte den Node neu. Ab jetzt wird ZFS nie mehr als 4 GiB für seinen Cache verwenden – egal wie groß dein Pool wird. Für eine Umgebung mit mehreren VMs und begrenztem RAM ist das oft Gold wert.
Willst du noch feiner justieren, kannst du auch l2arc_noprefetch aktivieren, falls du einen zweiten Layer-Cache (L2ARC) auf SSD betreibst. Aber das Thema sprengt den Rahmen dieses Artikels – merk dir einfach: ARC first, L2ARC later.
Persönliche Einschätzung: Mein größter Leidensweg mit ZFS waren Nodes mit 8 GB RAM und drei großen VMs. Ohne ARC-Limit war nach zwei Tagen kaum noch Memory für die Gäste übrig – der Host swapete heftig und die Latenz explodierte. Seitdem setze ich auf jedem Produktivsystem ein festes Limit, selbst wenn theoretisch genug RAM vorhanden wäre. Besser sicher als schlau und später am Telefon mit dem Support stehen, weil niemand versteht, warum suddenly alles einfriert.
Häufige Fehler, die dich teuer zurückwerfen
Hier eine Liste der Fallstricke, die ich am häufigsten sehe – manche davon führen zum Totalausfall:
-
Keine separate Boot-Partition: Installiere Proxmox niemals direkt auf denselben ZFS-Pool, in dem auch deine VM-Daten liegen. Ein kaputter Pool bedeutet dann auch ein nicht bootfähiges System. Nutze für
/bootimmer ein klassisches ext4 auf einer kleinen SSD oder sogar einem USB-Stick (ja, ernsthaft – das funktioniert überraschend gut und entlastet den Hauptpool). -
Skruplesloses Deaktivieren von Attribut-Caching: Manche versuchen, Performanceprobleme zu lösen, indem sie
atimeabschalten oder ähnliche Optimierungen machen. Meistens bringt das nichts, außer dass du Diagnoseinformationen verlierst. Lass solche Optionen ruhen, es sei denn, du weißt genau, was du tust. - Snapshots vergessen: Ja, Snapshots nehmen indirekt Speicher weg (über Refreservation), aber sie sind deine einzige Chance, innerhalb von Sekunden auf einen früheren Zustand zurückzugehen. Ohne sie bist du auf langsame VM-Recovery-Ansätze angewiesen.
- Ungeeignete Hardware mischt: Mische keine SSDs unterschiedlicher Kapazität oder Hersteller in einem Spiegelverband. ZFS wählt das kleinste Teil als Grenze – alles darüber geht verloren. Außerdem reagieren Chipsätze unterschiedlich auf TRIM/BEC-Befehle, was long-term zu Degradation führt.
Fazit und dein konkreter nächster Schritt
ZFS auf Proxmox einzusetzen ist keine Raketenwissenschaft, aber es erfordert Respekt vor dem System. Beginne mit einer klaren Trennung deiner Daten über sensible Datasets, automatisiere Snapshots frühzeitig und – ganz wichtig – beschränke deinen ARC, bevor er dich überrumpelt. Mit diesen Maßnahmen vermeidest du die meisten klassischen Probleme und profitierst von der Robustheit, die ZFS seit Jahren bietet.
Dein nächster konkreteter Schritt? Öffne heute Abend deine Shell, liste deine aktuellen Pools auf (zfs list) und prüfe, ob du bereits Datenseparation hast. Falls nein: Plane morgen eine Wartungsfreizeit ein, erstelle ein neues Dataset für deine wichtigsten VMs und übertrage diese dorthin. Selbst wenn es nur eine temporäre Maßnahme ist – du gewinnst Übersicht und Sicherheit. Und vergiss danach nicht, einen Test-Snapshot zu erstellen und wieder rückgängig zu machen. So lernst du das Gefühl für die Geschwindigkeit, die ZFS im Ernstfall liefern kann.
Top comments (0)