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 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