TL;DR — Kurzzusammenfassung
ZFS-Snapshots sichern Linux-Daten per Copy-on-Write ohne Speicherkosten. Erstellen, rollback, klonen und replizieren mit zfs send/receive und sanoid.
ZFS-Snapshots gehören zu den leistungsfähigsten Datenschutz-Tools unter Linux. Im Gegensatz zu herkömmlichen Backup-Ansätzen, die ganze Datasets kopieren, nutzen ZFS-Snapshots die Copy-on-Write (COW)-Semantik, um den genauen Zustand eines Dateisystems zu einem bestimmten Zeitpunkt zu erfassen — sofort und ohne initialen Speicherbedarf. Dieser Leitfaden behandelt alles von den ZFS-Grundlagen bis hin zu automatisierten Snapshot-Pipelines mit sanoid und syncoid.
Voraussetzungen
- Ubuntu 22.04/24.04 LTS (oder eine beliebige Distro mit OpenZFS 2.1+)
- Ein oder mehrere Blockgeräte zum Testen
sudo-Zugriff- Grundkenntnisse der Linux-Gerätebenennung (
/dev/sd*,/dev/vd*)
Grundlegende ZFS-Konzepte
Copy-on-Write (COW): ZFS überschreibt niemals aktive Daten an Ort und Stelle. Wenn ein Block geändert wird, schreibt ZFS die neue Version an einen freien Speicherort und aktualisiert atomisch den Zeiger. Der alte Block bleibt unangetastet — das nutzen Snapshots aus.
Pools und Datasets: Ein Pool (zpool) ist der übergeordnete Speichercontainer, der aus einem oder mehreren vdevs besteht. Ein Dataset (zfs create) ist ein einhängbares Dateisystem innerhalb eines Pools.
Prüfsummen: Jeder Block trägt eine 256-Bit-Prüfsumme. Beim Lesen überprüft ZFS die Prüfsumme und kann sich automatisch aus einer redundanten Kopie reparieren, wenn der primäre Block beschädigt ist.
ZFS unter Ubuntu installieren
sudo apt update
sudo apt install zfsutils-linux -y
zfs --version
Pools erstellen
# Mirror (RAID-1-Äquivalent)
sudo zpool create tank mirror /dev/sdb /dev/sdc
# RAIDZ1 — 1 Paritätsdisk, toleriert 1 Ausfall
sudo zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd
# RAIDZ2 — 2 Paritätsdisks, toleriert 2 Ausfälle (empfohlen für >=6 Disks)
sudo zpool create tank raidz2 /dev/sd{b,c,d,e,f,g}
zpool status tank
zpool list
Dataset-Verwaltung
# Dataset mit LZ4-Kompression
zfs create -o compression=lz4 tank/data
# Expliziter Einhängepunkt
zfs set mountpoint=/srv/data tank/data
# zstd-Kompression für bessere Ratio
zfs set compression=zstd tank/data
# Recordsize für Datenbanken anpassen
zfs set recordsize=16K tank/postgres # PostgreSQL
zfs set recordsize=128K tank/mysql # MySQL InnoDB
# Kontingente und Reservierungen
zfs set quota=500G tank/data
zfs set reservation=100G tank/data
Wichtige Überwachungseigenschaften:
| Eigenschaft | Bedeutung |
|---|---|
used | Belegter Speicher des Datasets + seiner Snapshots |
available | Freier Speicher, den das Dataset noch nutzen kann |
referenced | Speicher nur des aktiven Datasets (ohne Snapshots) |
compressratio | Erreichtes Kompressionsverhältnis (z.B. 2.14x) |
Snapshot-Grundlagen
Snapshots erstellen
# Einzelner Snapshot
zfs snapshot tank/data@2026-03-22
# Rekursiver Snapshot
zfs snapshot -r tank@2026-03-22
# Mit Shell-Zeitstempel
zfs snapshot tank/data@$(date +%Y-%m-%dT%H%M)
Snapshots auflisten
zfs list -t snapshot
zfs list -t snapshot -o name,used,referenced,creation
Zurücksetzen (Rollback)
zfs rollback tank/data@2026-03-22
# Falls neuere Snapshots existieren
zfs rollback -r tank/data@2026-03-21
Snapshot-Inhalt ohne Rollback zugreifen
ls /srv/data/.zfs/snapshot/
# Einzelne Datei wiederherstellen
cp /srv/data/.zfs/snapshot/2026-03-22/wichtig.sql /srv/data/wiederhergestellt.sql
Snapshots löschen
zfs destroy tank/data@2026-03-20
# Bereich von Snapshots
zfs destroy tank/data@2026-03-01%2026-03-15
Klone: Beschreibbare Snapshots
Ein Klon ist ein beschreibbares Dataset, das aus einem Snapshot abgeleitet wird. Er teilt anfänglich alle Blöcke mit der Quelle, ideal für Staging-Umgebungen.
# Klon erstellen
zfs clone tank/data@2026-03-22 tank/data-staging
# Einhängepunkt setzen
zfs set mountpoint=/srv/staging tank/data-staging
# Klon unabhängig machen
zfs promote tank/data-staging
Send/Receive: ZFS-Replikation
Vollständige Erstübertragung
# Lokale Kopie
zfs send tank/data@2026-03-22 | zfs receive backup/data
# Über SSH mit Kompression
zfs send -c tank/data@2026-03-22 | ssh backup-host zfs receive backup/data
Inkrementelle Übertragungen
# -i = einzelnes Inkrement
zfs send -ci tank/data@2026-03-21 tank/data@2026-03-22 | \
ssh backup-host zfs receive -F backup/data
# -I = einschließlich Zwischen-Snapshots
zfs send -cI tank/data@2026-03-20 tank/data@2026-03-22 | \
ssh backup-host zfs receive -F backup/data
Unterbrochene Übertragungen fortsetzen
zfs get receive_resume_token backup/data
zfs send -t <token> | ssh backup-host zfs receive -s backup/data
Replikations-Flags Referenz
| Flag | Wirkung |
|---|---|
-c | Komprimiert den Stream |
-i | Inkrementell zwischen zwei Snapshots |
-I | Inkrementell einschließlich aller Zwischen-Snapshots |
-R | Repliziert Dataset rekursiv |
-s | Speichert Fortsetzungsstatus auf dem Empfänger |
-v | Ausführliche Ausgabe |
Automatisierte Snapshots mit Sanoid
Sanoid installieren
sudo apt install sanoid -y
Richtlinien konfigurieren
# /etc/sanoid/sanoid.conf
[tank/data]
use_template = production
recursive = yes
[template_production]
hourly = 24
daily = 30
monthly = 3
autosnap = yes
autoprune = yes
Systemd-Timer aktivieren
sudo systemctl enable --now sanoid.timer
sudo sanoid --take-snapshots --verbose
sudo sanoid --prune-snapshots --verbose
Syncoid für Replikation
syncoid tank/data backup-host:backup/data
syncoid --recursive tank backup-host:backup
Scrubbing und Selbstheilung
sudo zpool scrub tank
zpool status tank | grep -A5 scrub
echo "0 2 1 * * root /sbin/zpool scrub tank" | sudo tee /etc/cron.d/zfs-scrub
ZFS im Vergleich zu Alternativen
| Funktion | ZFS | Btrfs | LVM + ext4 | XFS |
|---|---|---|---|---|
| Copy-on-Write | Ja | Ja | Nein | Nein |
| Integriertes RAID | Ja (RAIDZ) | Ja (begrenzt) | Via LVM | Nein |
| Native Snapshots | Ja | Ja | Via LVM | Nein |
| Send/Receive-Replikation | Ja (nativ) | Ja | Nein | Nein |
| Prüfsummen / Selbstheilung | Ja | Ja (begrenzt) | Nein | Nein |
| Kompression | Ja (lz4, zstd) | Ja | Nein | Nein |
| ARC/L2ARC-Cache | Ja | Nein | Nein | Nein |
| Produktionsreife (Linux) | Hoch (OpenZFS) | Mittel | Sehr hoch | Sehr hoch |
Produktionsmuster
Boot Environments
sudo zfs snapshot -r rpool/ROOT/ubuntu@before-upgrade
Docker auf ZFS
echo '{"storage-driver": "zfs"}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
zfs set recordsize=128K tank/docker
Recordsize für Datenbanken
| Datenbank | Empfohlenes recordsize | Grund |
|---|---|---|
| PostgreSQL | 8K oder 16K | Entspricht der 8K-Seite |
| MySQL InnoDB | 16K | Entspricht der InnoDB-Seite |
| MySQL MyISAM | 128K | Begünstigt sequenzielle Scans |
| MongoDB | 16K | Standard WiredTiger-Seite |
| SQLite | 4K | Entspricht der Standard-Seite |
Sonderfälle und Warnhinweise
- Importiere denselben Pool niemals auf zwei Hosts gleichzeitig: Dies verursacht Split-Brain und Pool-Korruption.
- Deduplizierung lohnt sich selten: Sie benötigt ~5 GB RAM pro TB eindeutiger Daten.
- Swap auf ZFS: Vermeide die Verwendung eines ZFS-Zvols als Swap — unter extremem Speicherdruck können Deadlocks auftreten.
Zusammenfassung
- ZFS-Snapshots sind sofortige, speichereffiziente Point-in-Time-Kopien auf Basis von Copy-on-Write.
- Nutze
zfs snapshotfür manuelle Snapshots und sanoid für richtlinienbasierte Automatisierung. zfs send | zfs receiverepliziert Datasets effizient — nur geänderte Blöcke werden übertragen.- Monatliches Scrubbing erkennt stille Korruption, bevor sie sich ausbreitet.
- Snapshots im selben Pool ersetzen keine Off-Pool-Backups — repliziere immer auf einen separaten Host.