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:

EigenschaftBedeutung
usedBelegter Speicher des Datasets + seiner Snapshots
availableFreier Speicher, den das Dataset noch nutzen kann
referencedSpeicher nur des aktiven Datasets (ohne Snapshots)
compressratioErreichtes 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

FlagWirkung
-cKomprimiert den Stream
-iInkrementell zwischen zwei Snapshots
-IInkrementell einschließlich aller Zwischen-Snapshots
-RRepliziert Dataset rekursiv
-sSpeichert Fortsetzungsstatus auf dem Empfänger
-vAusfü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

FunktionZFSBtrfsLVM + ext4XFS
Copy-on-WriteJaJaNeinNein
Integriertes RAIDJa (RAIDZ)Ja (begrenzt)Via LVMNein
Native SnapshotsJaJaVia LVMNein
Send/Receive-ReplikationJa (nativ)JaNeinNein
Prüfsummen / SelbstheilungJaJa (begrenzt)NeinNein
KompressionJa (lz4, zstd)JaNeinNein
ARC/L2ARC-CacheJaNeinNeinNein
Produktionsreife (Linux)Hoch (OpenZFS)MittelSehr hochSehr 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

DatenbankEmpfohlenes recordsizeGrund
PostgreSQL8K oder 16KEntspricht der 8K-Seite
MySQL InnoDB16KEntspricht der InnoDB-Seite
MySQL MyISAM128KBegünstigt sequenzielle Scans
MongoDB16KStandard WiredTiger-Seite
SQLite4KEntspricht 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 snapshot für manuelle Snapshots und sanoid für richtlinienbasierte Automatisierung.
  • zfs send | zfs receive repliziert 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.

Verwandte Artikel