Story
ZFS — das einzige Dateisystem, dem ich noch traue
Der Nighthog erklärt, warum ZFS nach all den Jahren immer noch sein Lieblingsdateisystem ist — mit den Shell-Befehlen, die im Alltag wirklich zählen: Pool, Datasets, Snapshots, Send/Receive und Scrub.
ZFS — das einzige Dateisystem, dem ich noch traue
Es gibt Dateisysteme, mit denen man arbeitet. Und es gibt eines, auf das man sich verlässt.
Ich habe in dreißig Jahren viele kommen und gehen sehen. ext2, ext3, ext4, ReiserFS (bis Hans den Reißverschluss zog), XFS, btrfs, NTFS, exFAT. Manche waren schnell. Manche waren stabil. Manche waren schnell und stabil — bis zum nächsten Stromausfall.
Und dann gibt es ZFS.
ZFS ist nicht schneller als alles andere. ZFS ist nicht moderner als alles andere. ZFS macht nur einen Job — Daten sicher aufbewahren — und macht ihn so gründlich, dass man irgendwann aufhört, sich darüber Gedanken zu machen.
Das ist viel verlangt für ein Dateisystem. Genau deshalb ist es mein Liebling.
Warum ich aufgehört habe, anderen Dateisystemen zu vertrauen
Es gab eine Nacht — wenn ich „eine Nacht” sage, meine ich exakt eine Nacht — in der mir ein ext4-Dateisystem still und leise einzelne Bytes verfälschte. Kein Crash. Keine Fehlermeldung. Eine Datenbank-Datei, die monatelang scheinbar funktionierte, war an einer Stelle korrupt. Backup auch. Weil das Backup brav die korrupte Version mitkopiert hatte.
Ich saß um vier Uhr morgens vor dem Server. Ich trank kalten Kaffee. Ich dachte über meine Berufswahl nach.
Was fehlte: Prüfsummen pro Block. Das Dateisystem hätte wissen können, dass ein Bit gekippt ist. Es hätte den Fehler melden können. Es hätte aus einem RAID-Spiegel die korrekte Version lesen können. Es tat nichts davon, weil ext4 so etwas schlicht nicht hat.
ZFS hat es. Standardmäßig. Auf jedem Block. Mit sha256 oder fletcher4. Wer einmal zpool scrub durchlaufen lassen hat und eine Meldung wie „42 Blöcke korrigiert, 0 Blöcke nicht reparabel” gesehen hat, vergisst die Notwendigkeit nie wieder.
Die Grundbegriffe, kurz und schmerzlos
ZFS denkt anders als klassische Dateisysteme. Statt eine Partition zu formatieren, legt man einen Pool über eine oder mehrere Festplatten. In dem Pool wachsen Datasets — das sind Quasi-Dateisysteme mit eigenen Eigenschaften (Kompression, Quota, Snapshots).
Pool anlegen, einfaches Mirror aus zwei Platten:
zpool create tank mirror /dev/sda /dev/sdb
zpool status tank
Pool als RAIDZ-1 aus vier Platten (eine darf ausfallen):
zpool create tank raidz /dev/sd{c,d,e,f}
Das war’s. Kein mkfs, kein mount, kein Eintrag in /etc/fstab. ZFS kümmert sich.
Datasets darin, mit ihren jeweils sinnvollen Eigenschaften:
zfs create -o compression=lz4 -o atime=off tank/backups
zfs create -o quota=200G tank/home
zfs create -o recordsize=16K tank/postgres
LZ4-Kompression kostet praktisch keine CPU und spart oft 30 bis 50 Prozent Plattenplatz. Es gibt keinen Grund, sie nicht einzuschalten.
Snapshots — das Feature, das alles verändert
Wenn jemand fragt, was ZFS einzigartig macht, ist es das hier:
zfs snapshot tank/home@vor-update
Dieser Befehl ist augenblicklich. Er kostet kein Byte mehr Plattenplatz, solange sich nichts ändert. Ab dem Moment, in dem eine Datei modifiziert wird, behält ZFS die alte Version als Snapshot. Copy-on-Write erledigt den Rest.
Bestand prüfen:
zfs list -t snapshot
Snapshot zurückrollen, falls das Update danebenging:
zfs rollback tank/home@vor-update
Aus einem Snapshot eine Datei holen, ohne den ganzen Stand zurückzurollen — der .zfs/snapshot/-Pfad ist still da:
cp /tank/home/.zfs/snapshot/vor-update/wichtig.docx /tmp/
Ich habe vor Jahren einen Kunden um drei Uhr nachts vor verlorenen Buchhaltungsdaten gerettet. Die Wiederherstellung dauerte acht Sekunden. Es war ein Snapshot vom Vorabend. Der Kunde war beeindruckt. Ich war wie immer.
Send/Receive — Backups, wie sie sein sollten
Die zweite Eigenschaft, die ZFS in eine eigene Liga hebt: zfs send überträgt einen Snapshot als Datenstrom. Das ist die Grundlage für inkrementelle Replikation.
Volltransfer auf einen Backup-Server:
zfs snapshot tank/home@2026-04-26
zfs send tank/home@2026-04-26 | ssh backup zfs receive backup/home
Inkrementell ab dem letzten Snapshot:
zfs snapshot tank/home@2026-04-27
zfs send -i @2026-04-26 tank/home@2026-04-27 | ssh backup zfs receive backup/home
Es überträgt nur die Block-Differenz. Auf einem System mit 2 TB Daten, von denen sich pro Nacht 200 MB ändern, dauert das Backup keine Minute. Verschlüsselt mit sanoid/syncoid als Wrapper, wird daraus ein Werkzeug, das jede klassische Backup-Lösung müde aussehen lässt.
Scrub — das System, das sich selbst überprüft
Einmal pro Woche oder Monat liest ZFS jede Datei vollständig zurück und vergleicht sie mit ihrer gespeicherten Prüfsumme:
zpool scrub tank
zpool status tank
Findet er einen Fehler, repariert er ihn aus der Spiegelplatte oder der RAIDZ-Parität — automatisch. Im status-Output steht hinterher etwas wie:
errors: 0 known data errors
Oder, im Ernstfall:
scan: scrub repaired 12K in 02:14:33, 0 errors
Diese Zeile ist das Wertvollste, was ein Dateisystem ausspucken kann: „Ich habe einen Fehler bemerkt, ich habe ihn behoben, du hast nichts gemerkt.”
Wenn eine Platte stirbt
Eine Platte stirbt — das ist keine Frage des ob, sondern des wann.
zpool status tank
zeigt im Ernstfall den DEGRADED-Status mit der konkreten betroffenen Platte. Tausch:
zpool replace tank /dev/sdc /dev/sdg
ZFS resilvert die neue Platte aus den noch lebenden — Block für Block, mit Prüfsummen, ohne ein einziges Byte falsch zu kopieren. Während der Pool weiterläuft. Während die Nutzer weiterarbeiten.
Ich war in den Neunzigern dabei, als RAID-Controller den Resilver aus Versehen die gesunde Platte überschrieben haben. Mit ZFS ist das nicht mehr möglich.
Mountpoints — wo der Pool im Dateisystem auftaucht
Standardmäßig mountet ein Dataset unter /<poolname>/<datasetpfad>. tank/home taucht also automatisch unter /tank/home auf. Das ist meist sinnvoll, manchmal nicht.
Mountpoint schon beim Anlegen explizit setzen — am Pool oder am einzelnen Dataset:
zpool create -m /srv/storage tank mirror /dev/sda /dev/sdb
zfs create -o mountpoint=/var/lib/postgres tank/postgres
Nachträglich ändern — ZFS unmountet kurz und mountet am neuen Ort:
zfs set mountpoint=/srv/backups tank/backups
Drei Sonderwerte tauchen im Alltag immer wieder auf:
mountpoint=none— das Dataset hat keinen Mountpoint. Sinnvoll für reine Container-Datasets, die nur als Eltern für Kinder dienen.mountpoint=legacy— ZFS mountet nicht selbst, der Eintrag muss in/etc/fstabmit Typzfsstehen. Manchmal nötig für Bind-Mounts oder Container-Hostpfade.canmount=noauto— Mountpoint bleibt erhalten, automatisches Mounten beim Boot ist aber aus.
zfs set canmount=noauto tank/optional
zfs mount tank/optional # nur bei Bedarf
Wenn der Pool nicht automatisch mountet
Der häufigste Anruf um halb sieben morgens: „Server läuft, aber der Pool ist weg.” Der Pool ist nicht weg — er ist nur nicht gemountet. Die typischen Ursachen, in der Reihenfolge, in der ich sie abklopfe:
1. Pool ist gar nicht importiert. Beim Boot wird der Pool aus /etc/zfs/zpool.cache importiert. Fehlt er da, hilft:
zpool import # zeigt importierbare Pools
zpool import tank # importiert ihn
Damit er beim nächsten Boot wiederkommt, gehört er in den Cachefile:
zpool set cachefile=/etc/zfs/zpool.cache tank
2. systemd-Units nicht aktiv. Auf frisch installierten Debian-Servern gerne übersehen:
systemctl enable zfs-import-cache.service zfs-mount.service zfs.target
3. Mountpoint-Verzeichnis ist nicht leer. ZFS weigert sich, über ein nicht-leeres Verzeichnis zu mounten. Häufiger Auslöser: ein Skript hat dort hineingeschrieben, bevor der Pool gemountet war.
ls -la /tank/home # was liegt dort, ohne dass der Pool gemountet ist?
zfs mount tank/home # liefert im Fehlerfall die genaue Begründung
4. canmount=off oder mountpoint=legacy. Schnell zu prüfen:
zfs get canmount,mountpoint tank/home
5. Verschlüsseltes Dataset, Schlüssel nicht geladen. Bei nativer ZFS-Verschlüsselung muss der Schlüssel nach dem Import explizit geladen werden — vor dem Mounten:
zfs load-key tank/encrypted
zfs mount tank/encrypted
6. Devices waren beim Import noch nicht da. USB-, iSCSI- oder Multipath-Geräte, die später erscheinen als die ZFS-Import-Unit, lassen den Pool initial fehlschlagen. Der Ausweg ist zfs-import-scan.service statt zfs-import-cache.service, oder eine explizite systemd-Abhängigkeit auf das Block-Device.
Wer sich diese sechs Punkte merkt, deckt 95 Prozent aller realen Fälle ab. Die restlichen fünf Prozent sind interessant — aber selten.
ZFS unter Proxmox — der natürliche Lebensraum
In Proxmox VE ist ZFS nicht eine Option neben anderen — es ist die erste Option, die der Installer anbietet, und nach meiner Erfahrung fast immer die richtige. Wer einen Proxmox-Server aufsetzt und genug Arbeitsspeicher hat, sollte Boot- und VM-Storage auf ZFS legen.
Was Proxmox besonders elegant macht:
- rpool beim Installer. Mirror oder RAIDZ wird im grafischen Installer ausgewählt — der Pool entsteht darunter, ohne dass man die
zpool-Befehle selbst tippen muss. - VM-Disks als zvols. Statt qcow2-Dateien legt Proxmox Block-Volumes an (
tank/vm-100-disk-0). Ein Snapshot der VM ist ein ZFS-Snapshot — augenblicklich, atomar, beliebig viele. - Replikation zwischen Cluster-Knoten. Über
pvesr(Proxmox Storage Replication) werden VMs perzfs send -iregelmäßig auf den Backup-Knoten gespiegelt. Beim Failover läuft die VM dort mit wenigen Sekunden Verzögerung weiter.
Storage-Lage ansehen:
cat /etc/pve/storage.cfg
zpool status rpool
zfs list
Replikationsjob zwischen zwei Knoten via CLI anlegen — alle 15 Minuten:
pvesr create-local-job 100-0 backup-node --schedule "*/15"
pvesr status
Ein Tuning-Detail, das oft vergessen wird: für VM-Volumes (zvols) heißt die Blockgröße volblocksize und wirkt nur beim Neuanlegen. Sinnvoller Wert für gemischte Datenbank-Workloads:
zfs set volblocksize=16K tank/vms # gilt nur für künftig angelegte zvols
Mehr zur Plattform: Proxmox VE im Werkzeugkasten.
Was ehrlich gesagt nicht trivial ist
Damit nichts unter den Tisch fällt:
- RAM. ZFS mag Arbeitsspeicher, mit 8GB würde ich erst gar nicht starten. Faustregel: 1 GB RAM pro 1 TB Pool zusätzlich. Für ECC-RAM gibt es seit Jahren religiöse Debatten — ich nehme, wenn möglich immer ECC, schon aus Prinzip.
- Linux-Kernel-Lizenzdrama. ZFS steht unter CDDL, der Linux-Kernel unter GPLv2 — die beiden vertragen sich juristisch nicht. ZFS auf Linux (ZoL) liefert daher ein DKMS-Modul, das beim Kernel-Update neu gebaut wird. Auf Proxmox-Servern ist das nahtlos integriert; auf reinen Debian-Systemen muss man wissen, was man tut.
- Recordsize tunen. Für allgemeine Daten passt der Default. Für Datenbanken (PostgreSQL: 16K, MariaDB InnoDB: 16K) und Virtualisierungs-Volumes (z. B. 64K oder 128K) lohnt sich das Tuning. Wer es ignoriert, lebt mit messbarer Performance-Einbuße.
- Kein
shrink. Pools wachsen, aber sie schrumpfen nicht. Wer eine vdev hinzufügt, kann sie nicht trivial wieder entfernen. Bei Mirrors geht es; bei RAIDZ klassischerweise nicht. Plant das Layout vorher.
Das sind keine Showstopper — das sind Dinge, die man beim ersten Mal lernt und dann nie wieder vergisst.
Wenn ich mich auf eines einigen müsste
Es würde ZFS sein.
Nicht weil es das modernste Dateisystem ist — bcachefs ist neuer, btrfs hat ähnliche Ambitionen, apfs ist eleganter. Sondern weil ZFS in den letzten zwanzig Jahren auf einer Skala produktiv im Einsatz war, die nichts anderes erreicht hat: Petabyte-Storage in Forschungsinstituten, FreeBSD-Server seit 2008, Solaris-Erbe, OpenZFS heute auf Linux, FreeBSD, illumos und macOS.
Ich vertraue Werkzeugen, die den Test der Zeit überlebt haben. ZFS ist eines davon.
Und am Ende, um vier Uhr morgens, wenn der Kaffee kalt ist und die Logs durchgesehen sind, ist das das einzige Kriterium, das wirklich zählt: Kann ich ruhig schlafen, wenn der Pool läuft?
Bei ZFS: ja.
Bei den anderen: kommt darauf an.
Teilen
LinkedInPassende Werkzeuge