2 Punkte von GN⁺ 2023-09-06 | 1 Kommentare | Auf WhatsApp teilen
  • Ein Einsteigerleitfaden, der ausgehend von einem ZFS-Ausfall bei FreeNAS Fehlerbehebung, die Konfiguration neuer Volumes und Backup-Strategien behandelt und die beim ersten Betrieb von ZFS nötige Struktur und Befehle in einem durchgehenden Ablauf erklärt
  • ZFS bietet Dateisystem und logischen Volume-Manager in einem und nutzt, nachdem es bei Sun Microsystems begann, unter Linux und FreeBSD überwiegend den OpenZFS-Code
  • Die Grundstruktur besteht aus vdevs, die physische Datenträger bündeln, daraus aufgebauten Pools, Datasets als Dateisystem-Komponente und Volumes in Form von Blockgeräten; RAIDZ-1/2/3 verkraften jeweils den Ausfall von 1, 2 bzw. 3 Datenträgern
  • Im praktischen Betrieb stehen die Befehle zpool create/status/list/import/export/destroy/scrub und zfs create/mount/list/get/set/snapshot/diff/rollback/send/recv/destroy im Zentrum; um Probleme durch geänderte Gerätenamen zu vermeiden, wird die Verwendung von Device-UUIDs bevorzugt
  • Snapshots schützen den Zustand zu einem bestimmten Zeitpunkt mit geringem Aufwand und lassen sich per zfs send/recv auf andere Pools oder Systeme replizieren, sind für sich allein jedoch kaum ein Ersatz für Backups oder DR

Grundkonzepte von ZFS

  • ZFS ist sowohl ein lokales Dateisystem wie ext4, NTFS oder exFAT als auch ein logischer Volume-Manager ähnlich LVM unter Linux
  • Es wurde von Sun Microsystems entwickelt, und der ZFS-Quellcode war bis zur Übernahme von Sun durch Oracle unter einer Open-Source-Lizenz veröffentlicht
  • Da der bereits veröffentlichte Code auf verschiedene Betriebssysteme portiert worden war, entstand später das Projekt OpenZFS, dessen Code heute auf den meisten Unix-artigen Systemen wie Linux und FreeBSD verwendet wird
  • Der Text ist aus Sicht von Einsteigern aufbereitet, damit Personen mit erstem Kontakt zu ZFS dessen Struktur und Betriebsbefehle verstehen können

Bestandteile von ZFS

  • Ein vdev besteht aus einem oder mehreren physischen Laufwerken und kann neben Festplatten auch Dateien umfassen
    • Es kann als Mirror oder RAIDZ aufgebaut werden
    • Es gibt 7 vdev-Typen, darunter wichtige Typen wie Hot Spare, L2ARC und ZIL
  • Ein Pool besteht aus einem oder mehreren vdevs; üblicherweise werden darin Volumes oder Datasets angelegt
    • Beim Erstellen eines Pools mit dem Befehl zpool werden die vdevs direkt mit definiert
    • Verschiedene vdev-Typen lassen sich kombinieren, um RAIDZ-Stufen aufzubauen
  • Ein Dataset ist in ZFS die Komponente, die einem Dateisystem entspricht
    • Dafür lassen sich Benutzerzugriff, Quota, Komprimierung, Snapshots usw. festlegen
  • Ein Volume ist einem Dataset ähnlich, stellt aber ein Blockgerät dar
    • Es bietet nur einen Teil der Dataset-Funktionen
    • Es ist nützlich, wenn auf ZFS ein anderes Dateisystem betrieben oder ein iSCSI-Extent exportiert werden soll

RAIDZ-Typen

  • Dynamic/Simple Stripe, also RAID0, verteilt Daten ohne Parität; fällt ein Gerät aus, gehen alle Daten verloren
  • MIRROR, also RAID1, spiegelt Datenträger und wird mit 2 bis 4 oder mehr Laufwerken verwendet
  • RAIDZ-1, also RAID5, verteilt Parität zusammen mit den Daten und verkraftet bis zum RAID-Ausfall den Verlust eines physischen Laufwerks
    • Für RAIDZ sind mindestens 3 Datenträger erforderlich
  • RAIDZ-2, also RAID6, verkraftet den Verlust von bis zu 2 physischen Laufwerken
    • Für RAIDZ-2 sind mindestens 4 Datenträger erforderlich
  • RAIDZ-3 verkraftet den Verlust von bis zu 3 physischen Laufwerken
    • Mindestens 4 Datenträger sind erforderlich, sinnvoll ist es jedoch meist erst ab 5 oder mehr

Pool erstellen und Status prüfen

  • Ein ZFS-Pool wird im Format zpool create [pool] [devices] erstellt
    • Beispiel für einen Pool mit einer einzelnen Platte: zpool create tank /dev/sdb
    • Beispiel für einen Stripe mit 3 Platten: zpool create tank /dev/sdb /dev/sdc /dev/sdd
    • Beispiel für einen Mirror mit 2 Platten: zpool create tank mirror sdb sdc
    • Beispiel für einen RAIDZ-Pool: zpool create tank raidz sdb sdc sdd
    • RAIDZ2/3 können im Format zpool create [pool name] raidz[1,2,3] [devices] erstellt werden
  • Beim Erstellen des Pools kann mit dem Flag -m der standardmäßige Mount-Point festgelegt werden
    • Beispiel: zpool create tank -m /mnt/tank mirror sdb sdc
  • In den Beispielen werden Gerätenamen in der Form /dev/sdx verwendet, um Boot-Probleme durch geänderte Gerätenamen zu vermeiden, wird jedoch die Nutzung von Device-UUIDs bevorzugt
  • zpool status ist der grundlegende Befehl zum Prüfen des Pool-Status
    • state zeigt an, ob der Pool online ist
    • status zeigt zusätzliche Informationen zum Pool an
    • action zeigt nötige Folgeschritte an
    • scan zeigt den Fortschritt eines Scrubs oder den Status des letzten Scrubs an
    • errors zeigt an, ob es Probleme im Pool gibt
  • zpool list zeigt Details wie Größe, Belegung, freien Speicher, Fragmentation, Capacity, Dedup und Health des Pools
  • zpool history zeigt die Befehlschronik der seit der Erstellung am Pool vorgenommenen Konfigurationsänderungen

Pool importieren, exportieren, löschen und scrubben

  • Nach der Erstellung wird ein Pool normalerweise automatisch importiert und gemountet, bei der Fehlerbehebung oder nach einer System-Neuinstallation kann jedoch ein manueller Import nötig sein
  • Wird zpool import ohne Pool-Namen ausgeführt, zeigt es die Liste importierbarer Pools an
    • Wenn kein importierbarer Pool vorhanden ist, erscheint no pools available to import
    • Wird ein Pool-Name angegeben, wird dieser Pool importiert; der Import-Befehl mountet den Pool auch
    • zpool import -a importiert alle importierbaren Pools
  • Mit -R, etwa in zpool import -R /mnt/tank2 tank, wird unter einem alternate root gemountet
    • Dabei handelt es sich nicht um den Mount-Pfad des Pools selbst, sondern um einen alternativen Root-Ordner
  • zpool export [pool name] ist das Gegenstück zu Import und versucht nach dem Unmounten der im Pool eingehängten Dateisysteme den Export
    • Falls das Unmounten des Dateisystems fehlschlägt, kann mit -f ein erzwungenes Unmounten versucht werden
    • Wenn ein verwendetes ZFS-Volume vorhanden ist, schlägt der Export selbst mit -f fehl
  • zpool destroy löscht den Pool samt untergeordneten Datasets oder Volumes
    • Dabei werden auch alle Daten und Snapshots gelöscht, daher ist Vorsicht nötig
  • Ein ZFS-Scrub prüft alle Blöcke eines Pools, indem sie mit bekannten Checksummen verglichen werden, um die Datenintegrität zu verifizieren
    • Bei vdevs mit Parität werden beschädigte Daten anhand der Daten auf intakten Laufwerken wiederhergestellt
    • Um den Systemzustand zu erhalten, sollte ein Scrub regelmäßig geplant ausgeführt werden
    • Start: zpool scrub [pool]
    • Status prüfen: Bereich scan in zpool status
    • Stoppen: zpool scrub -s [pool]

Dataset erstellen und mounten

  • zfs create erzeugt ein neues Dateisystem oder Volume; hier liegt der Fokus eher auf Datasets als auf Volumes
  • zfs create tank/dataset1 erstellt dataset1 unter tank
    • Das Dataset tank wird beim zpool create automatisch angelegt
  • zfs create -p erstellt ähnlich wie mkdir -p auch fehlende übergeordnete Datasets
    • Fehlt ein übergeordnetes Dataset, schlägt ein normales zfs create fehl
  • Wird zfs mount ohne Argumente ausgeführt, zeigt es die aktuell gemounteten ZFS-Dateisysteme und ihre Mount-Points an
    • Diese Ausgabe enthält keine Child-Datasets
  • zfs mount [pool|dataset] mountet das angegebene Dateisystem
    • zfs mount -a mountet alle Dateisysteme
  • Child-Datasets können auch ohne ihr Parent-Dataset gemountet werden
    • In diesem Fall werden die im Betriebssystem-Dateisystem erforderlichen Pfade erstellt
    • Wenn später das Parent-Dataset gemountet werden soll, kann wegen der erzeugten Verzeichnisse der Fehler directory is not empty auftreten
  • zfs unmount [dataset] unmountet das angegebene Dataset

Dataset anzeigen und Eigenschaften setzen

  • zfs list [dataset name] zeigt Informationen zum angegebenen Dataset an
    • Statt des Dataset-Namens kann auch der Mount-Point als Argument übergeben werden
  • Wird zfs list ohne Dataset-Namen ausgeführt, zeigt es rekursiv alle Datasets des Systems an
  • Wird beim Angeben eines Dataset-Namens das Flag -r verwendet, kann alles unterhalb dieses Datasets rekursiv angezeigt werden
  • ZFS-Properties steuern das Verhalten von Dateisystem, Volume, Snapshot und Clone
    • Sie können Mount-Optionen ähneln
  • zfs get all [dataset] zeigt alle Properties eines Datasets an
  • Der Wert einer bestimmten Property lässt sich etwa mit zfs get compression tank prüfen
  • Zum Setzen von Properties wird zfs set verwendet
    • Beispiel: zfs set compression=lz4 tank
    • Danach kann mit zfs get compression tank bestätigt werden, dass compression auf lz4 geändert wurde

Funktionsweise und Nutzung von Snapshots

  • Ein Snapshot speichert den Zustand eines Dateisystems zu einem bestimmten Zeitpunkt, kopiert dabei aber keine Dateien
  • Ein Snapshot markiert vorhandene Daten als schreibgeschützt, und auch wenn danach neue Daten zum Dateisystem hinzukommen, bleiben die durch den Snapshot geschützten vorhandenen Datenblöcke unverändert
  • Der beispielhafte Ablauf ist wie folgt
    • In einem Dateisystem mit vorhandenen Daten A wird Snapshot 1 erstellt
    • Danach werden Daten B hinzugefügt und Snapshot 2 erstellt
    • Danach werden Daten C hinzugefügt
    • Snapshot 1 schützt Daten A, Snapshot 2 schützt Daten A und Daten B
    • Selbst wenn Snapshot 1 gelöscht wird, bleiben Daten A weiterhin durch Snapshot 2 geschützt
  • Der durch einen Snapshot belegte Datenumfang ist sehr klein
    • Denn statt Dateien zu kopieren, wird nur der oberste Metadatenblock des Dateisystems aufgezeichnet, der zu diesem Snapshot gehört
  • Snapshots sind nützlich für Softwaretests oder als Failsafe vor Upgrades
  • Snapshots allein sollten nicht als Backup- oder DR-Lösung betrachtet werden

Snapshot-Befehle

  • Snapshots werden im Format zfs snapshot [pool/dataset@snapshot_name] erstellt
    • Beispiel: zfs snapshot tank/dataset1@snapshot1
  • Die Snapshot-Liste lässt sich mit zfs list -t snapshot anzeigen
  • Wenn mehrere Child-Datasets vorhanden sind, kann auf dem Top-Level-Dataset ein Snapshot erstellt oder mit dem Flag -r ein rekursiver Snapshot angelegt werden
    • Beispiel für einen normalen Snapshot: zfs snapshot tank@snapshot-master
    • Beispiel für einen rekursiven Snapshot: zfs snapshot -r tank@recursive
  • zfs diff [older snapshot] [newer snapshot] vergleicht die Unterschiede zwischen Snapshots
    • In der Ausgabe lassen sich hinzugefügte Dateien und geänderte Pfade erkennen
  • Die Wiederherstellung eines Snapshots erfolgt mit zfs rollback [pool/dataset@snapshot_name]
    • Bei einem Rollback werden Dateien gelöscht, die nach dem Snapshot erstellt wurden
    • Auch neuere Snapshots werden gelöscht; in diesem Fall kann die Verwendung der Option -r verlangt werden

ZFS send/recv und Replikation

  • ZFS send kann Snapshots als Datenstrom übertragen
  • Snapshots und Datasets lassen sich in Dateien, in andere Pools oder per SSH auf andere Systeme replizieren
  • In den Beispielen werden zwei Pools mit den Namen tank und backup verwendet
    • Im Dataset tank/Movies liegen 1.50G Daten
    • Vor der Übertragung wird mit zfs snapshot tank/Movies@$(date '+%Y-%m-%d_%H-%M') ein Snapshot erstellt
    • Mit zfs send tank/Movies@2020-11-03_15-29 | zfs recv backup/Movies wird der Snapshot in den Backup-Pool übertragen
  • Nach der Übertragung sind in zfs list sowohl backup/Movies als auch tank/Movies sichtbar, und in zfs list -t snapshot sind die Snapshots auf beiden Seiten zu sehen
  • zfs send ist eine Funktion mit vielen Optionen und Einsatzszenarien; zusammen mit RAIDZ und Snapshots kann sie das Dateisystem robuster machen

Datasets und Snapshots löschen

  • Ein Dataset wird im Format zfs destroy [pool/dataset] gelöscht
    • Das Flag -r kann ebenfalls verwendet werden
  • Auch für das Löschen eines Snapshots wird zfs destroy [pool/dataset@snapshot_name] verwendet
    • Auch beim Löschen von Snapshots kann das Flag -r verwendet werden
  • ZFS bietet noch viele weitere Funktionen, aber dieses Material ist eher ein Einstiegspunkt zum Erlernen der Grundkonzepte und Befehle

Referenzen

1 Kommentare

 
GN⁺ 2023-09-06
Meinungen auf Hacker News
  • Ich habe gerade erst mit ZFS angefangen, und die Lernkurve ist steiler als erwartet. Es wäre schön, wenn es einen einfachen Wrapper gäbe, der häufige Anwendungsfälle stark vereinfacht.
    Zum Beispiel sollte man beim Erstellen eines Pools einfach vernünftige Defaults wie ashift=12, lz4-Kompression, xattr=sa, acltype=posixacl und atime=off verwenden können, und Verschlüsselung sollte statt vieler Optionen nur Ein/Aus sein.
    Er sollte Verschlüsselungsschlüssel erzeugen, einen systemd-Dienst einrichten, der den Pool beim Booten entschlüsselt, und zum Backup der Schlüssel anleiten. zfs list sollte anzeigen, ob ein Dataset gemountet ist, ob es verschlüsselt ist und ob der Schlüssel geladen ist.
    Rekursive Datasets sollte man abschaffen und Pool und Dataset statt mit {pool}/{dataset} klar mit {pool}:{dataset} voneinander trennen. Auch Pool- oder Snapshot-Namen sollte man nicht selbst vergeben müssen; stattdessen wären automatisch vergebene Regeln wie {hostname}-[A-Z] oder {pool name}_{datetime created} sowie numerische Kurznamen sinnvoll.
    Beim Erstellen eines Pools sollte man keine Disk-IDs direkt eingeben müssen; man sollte ihn mit /dev/sda, /dev/sdb anlegen können, und ZFS sollte Metadaten auf den Disks speichern, damit es auch nach geänderter Laufwerksreihenfolge nicht durcheinanderkommt.
    Fortschritt sollte immer mit pv angezeigt werden, und wöchentliche Scrubs sowie stündliche/tägliche/wöchentliche/monatliche Snapshots samt Aufräumen sollten automatisch eingerichtet werden.
    Wenn man auf eine Disk ohne Pool sendet, sollte nach Bestätigung ein Single-Disk-Pool mit denselben Einstellungen wie der sendende Pool erstellt werden, und zpool und zfs sollten zu einem einzigen Kommando zusammengeführt werden.
    Beim Senden verschlüsselter Datasets sollte automatisch --raw verwendet werden, als Send-Default sollte --replicate gelten, und wenn möglich sollte -I genutzt werden. Snapshot-Dateisysteme sollten nicht in versteckten Verzeichnissen verborgen werden; außerdem braucht es eine einfache Möglichkeit, Snapshot-Datasets zu mounten und zu durchsuchen.
    • Das ist eine Mischung aus vernünftigen Vorschlägen und sehr starken persönlichen Vorlieben. Den Default ashift=12 oder die Syntax {pool}:{dataset} kann ich nachvollziehen, aber das jetzt noch zu ändern wirkt schwierig, und manche Vorschläge könnten unbekannte Use Cases kaputtmachen.
      Pools nach dem Hostnamen zu benennen passt nicht zu SAN-Pools, die von mehreren Hosts importiert werden können.
      Wöchentliche Scrubs, periodische Snapshots und periodisches Aufräumen sehe ich als Aufgabe des Betriebssystem-Schedulers. zpool und zfs zusammenzuführen wäre zwar möglich, aber am Ende hätte man dann etwas wie zfs -pool XXXX, zfs -volume XXXX – ich sehe nicht, warum das nötig wäre.
      Rekursive Datasets sind in der Praxis manchmal nützlich. Andererseits stimme ich völlig zu, dass zfs list anzeigen sollte, ob etwas gemountet ist, ob es verschlüsselt ist und ob der Schlüssel geladen ist.
      Der Punkt, keine Disk-IDs eingeben zu müssen, ist unklar. Man kann Disks über ID, WWN, Label, sdX usw. angeben, aber irgendwie muss man ZFS trotzdem mitteilen, welche Disk verwendet werden soll.
      Die Funktion, Metadaten auf der Disk zu speichern, sodass sie auch nach geänderter Reihenfolge gefunden wird, gibt es bereits. Wenn man ein paar Laufwerke umsteckt und den Pool importiert, werden sie gefunden.
      Einige Vorschläge wären als Defaults in Ordnung, aber bei manchen scheint die eigene Nutzung und der Bedarf außerhalb davon nicht ausreichend bedacht zu sein. ZFS richtet sich an sehr viel mehr Anwender.
    • Einen Pool mit /dev/sda, /dev/sdb zu erstellen und dann zu sagen, ZFS komme durcheinander, ist ehrlich gesagt weniger ein ZFS-Problem als eher ein Problem eines Nutzers, der es nicht zeitgemäß verwendet.
      Unter Linux gibt es schon seit ziemlich langer Zeit vollständige Referenzen wie /dev/disk/by-id/ata-$manufactuer-$serial-$whatever. Beim Erstellen eines Pools sollte man solche Pfade verwenden.
    • Viele Vorschläge sind stark geschmacksabhängig; das ist an sich nichts Schlechtes, wirkt aber so, als würden bestehende Konventionen unnötig aufgerüttelt. Zum Beispiel verstehe ich nicht, warum es {pool}:{dataset} sein sollte.
      Wenn du Snapshot-Namen nicht selbst vergeben willst, könnte mein kleines Tool https://github.com/rollcat/zfs-autosnap passen.
      Wenn man zfs-autosnap snap stündlich in cron einträgt und zfs-autosnap gc täglich, rotiert es die Snapshot-Historie entsprechend der Aufbewahrungsrichtlinie.
      Einen einfachen ZFS-Kommando-Wrapper zu schreiben ist nicht schwer; du kannst also meinen Code nehmen und dir dein eigenes Tool bauen.
    • Ich habe einmal gelesen, dass eine der letzten Aufgaben eines Schmiedelehrlings darin bestand, alle Werkzeuge selbst herzustellen, die ein echter Schmied braucht: Amboss, Hammer, Zangen und so weiter.
      Auch bei der Arbeit habe ich mehrere Skripte geschrieben, die ZFS-Arrays passend zu der jeweils vorgesehenen Deployment-Form erstellen. Darin enthalten waren das Erzeugen eines LUKS-verschlüsselten Volumes für zvols, die Standardisierung von Namensregeln sowie Defaults wie ashift=12 und lz4-Kompression.
      Das war lange bevor ZFS eigene Verschlüsselung bekam, und da die heutige Methode für uns weiterhin funktioniert, habe ich die Skripte nicht aktualisiert, um ZFS-Verschlüsselung zu unterstützen.
      Inzwischen erinnere ich mich nicht mehr an viele Flags, aber die Skripte dienen als Dokumentation, und die anderen im Team müssen nur make-zfs-big-mirror oder make-big-zfs-undundant-raid0 ausführen.
      Falls ich eines Tages mehr als 20-mal im Jahr Systeme provisionieren muss, kann selbst das noch in die Provisionierung automatisiert werden.
    • Wie andere schon gesagt haben, sind das sehr meinungsstarke Vorschläge. Eine Meinung zu haben ist völlig okay, aber viele Punkte reichen von „das ist nicht die Art, wie ich es unter Linux gewohnt bin“ bis hin zu tatsächlich problematischen Vorschlägen.
      Keine Pool-Namen vergeben zu wollen ergibt keinen Sinn. Man erstellt Pools nicht so häufig, also vergib einfach einen Namen.
      Wenn du Snapshot-Namen nicht selbst vergeben willst, kannst du httm und zfs allow verwenden. httm -S . erzeugt zum Beispiel einen Snapshot wie rpool/ROOT/ubuntu_tiebek@snap_2022-12-14-12:31:41_httmSnapFileMount.
      zfs und zpool sind jeweils hervorragende Unix-Kommandos mit mehreren Unterbefehlen. Ich halte es für eine sehr kluge Entscheidung der ZFS-Designer, kein komplexeres einzelnes Verwaltungskommando gebaut zu haben.
      Snapshot-Datasets explizit zu mounten und zu durchsuchen ist mit zfs mount ebenfalls leicht möglich. Man sollte aber auch anerkennen, dass eine stabile virtuelle Schnittstelle die Suche über alle Dateiversionen hinweg erleichtert, und dass dies bei btrfs und anderen deutlich schwieriger ist. httm ist ebenfalls einen Blick wert.
      [0]: https://kimono-koans.github.io/opinionated-guide/#dynamic-sn...
  • Es gibt noch weitere nützliche Dinge in ZFS. Es ist gut, den Unterschied zwischen zpool-attach(8) und zpool-replace(8) zu kennen, und zfs list -t all -o space zeigt, wofür Speicherplatz verwendet wird.
    Zum Schutz des Betriebssystems vor größeren Änderungen oder Upgrades sind ZFS Boot Environments das beste Feature. Als Einstieg kann https://is.gd/BECTL hilfreich sein.
    zpool history poolname zeigt die gesamte Pool-Konfiguration und Änderungshistorie. Dort werden zum Beispiel Änderungen wie zpool create, autotrim=on, atime=off, compression=zstd oder recordsize=1m protokolliert.
    Im Guide fehlt auch eine wichtige Information: Bei einem 3-way Mirror bleiben die Daten erhalten, selbst wenn 2 von 3 Platten ausfallen; bei einem 4-way Mirror bleiben sie erhalten, wenn 3 von 4 ausfallen; und bei einem N-way Mirror bleiben die Daten erhalten, solange von N Platten höchstens N-1 ausfallen.
    Das ist nützlich, wenn die Daten das Wichtigste sind, aber nicht viele Slots oder Platten vorhanden sind.

    • Ein N-way Mirror hat außerdem die Eigenschaft, dass ZFS Lesevorgänge auf mehrere Platten verteilen kann. Bei rotierenden Festplatten, bei denen die Zahl der I/O-Operationen begrenzt war, war das ziemlich wichtig.
  • Ich betreibe seit Jahren große PostgreSQL-Datenbanken im Multi-TB-Bereich auf ZFS. Dank ZFS sind Backups, das Erstellen von Testumgebungen auf Basis alter Snapshots und das Sparen von Plattenplatz durch integrierte Kompression sehr einfach geworden.
    Wer Interesse hat, kann unsere Erfahrungen unter https://lackofimagination.org/2022/04/our-experience-with-po... nachlesen.

  • Beim Einstieg in ZFS waren für mich das ZFS Handbook von FreeBSD und die Artikel von Aaron Toponce am hilfreichsten.
    [0] https://docs.freebsd.org/en/books/handbook/zfs/
    1 https://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux...

    • Ich mag die FreeBSD-Dokumentation.
      Ich habe FreeBSD auf einem alten HP Microserver mit 1 GB ECC-RAM installiert, der noch herumstand, und hatte auch fünf alte 500-GB-Festplatten. Anhand des FreeBSD Handbook habe ich sie als 5x-Mirror eingerichtet. Es war mein erstes Mal mit FreeBSD, und es ging sehr reibungslos.
  • Vor Kurzem habe ich viel Infrastruktur neu aufgebaut, hauptsächlich LAMP-Server, und mich entschieden, alles für effiziente Backup-Replikation und Verschlüsselung auf ZFS unter Linux aufzusetzen.
    Ich nutzte ZFS zusammen mit rsync schon lange für Backups und war daher ziemlich vertraut damit; am Ende hat es gut funktioniert. Aber der Versuch, es wirklich sauber zu machen, kostete deutlich mehr Zeit als erwartet. Besonders zu Datenbanken und Replikation findet man im Web viele falsche Ratschläge.
    Bei Datenbanken sollte man mindestens grundlegendes Tuning wie Blockgrößen-Ausrichtung vornehmen. Zu mariadb/InnoDB war das Material von Let’s Encrypt unter https://github.com/letsencrypt/openzfs-nvme-databases mit Abstand am besten. Es ist sehr wertvoll, weil jeder Punkt begründet und mehrere Quellen zitiert werden.
    Wenn man weiter im Web sucht, findet man endlos widersprüchliche Ratschläge, Anekdoten und Mythen, oft unvollständig und mit unbelegten Theorien. Am Ende muss man selbst testen, verstehen, was man einstellt, und es ist auch in Ordnung, sich bewusst gegen ein Tuning zu entscheiden.
    Für Replikation empfehle ich wirklich die Manpages. ZFS stellt robuste Replikationswerkzeuge bereit, aber sie sind so allgemein gehalten, dass sie sich wie Git-Plumbing-Kommandos anfühlen. Da ZFS nicht annimmt, dass man SSH verwendet, muss man die Teile selbst zusammenstecken; und wenn man automatisieren will, muss man auch Randbedingungen bedenken, was anfangs einschüchternd wirkt.
    Deshalb greifen viele zu Tools wie syncoid, aber an Replikationsskripten der syncoid-Art gab es etwas Schreckliches: Sie verwenden nicht den send --replication-Modus von ZFS, sondern implementieren ihn in Perl unvollständig neu, mit dem Argument, das sei flexibler.
    Beim ersten Testen und anschließenden Restore neu anzufangen und dann zu sehen, dass alle Encryption Roots kaputt sind und Dataset-Properties nicht vollständig automatisch synchronisiert werden, macht einen wahnsinnig. Wenn man einfach die eingebaute rekursive Replikationsoption verwendet, erledigt ZFS das.
    Wenn man sich vornimmt, selbst ein Skript zu schreiben, ist es nicht schwer. Man muss es schlicht halten und nicht wie syncoid jede Menge unnötige Dinge in die Pipeline stopfen. In realen Tests bremsen solche Dinge sogar. Den Fortschritt sieht man mit pv, und dann schiebt man es einfach durch; das läuft schnell.
    Vielleicht veröffentliche ich irgendwann mein Replikationsskript. Ich habe den Eindruck, dass es kaum gute Referenzskripte gibt, die die Grundlagen abdecken, ohne Replikation schlecht neu zu implementieren.

    • Dieses Material erwähnt das Tuning von io_capacity und io_capacity_max, aber wenn man in der MySQL-Dokumentation nachliest, welche Rolle diese Parameter tatsächlich spielen, sind sie leider nicht besonders nützlich.
      Diese Werte steuern Hintergrund-I/O wie das Zusammenführen des Change Buffers und können I/O von Hauptprozessen abziehen, die tatsächlich Arbeit zu erledigen haben.
      Aus Erfahrung mit einer recht ausgelasteten MySQL-DB mit 120K QPS musste ich keinen der beiden Werte anfassen. Wenn man meint, das sei nötig, sollte man zuerst überwachen, wie lange es dauert, bis das Redo Log voll läuft, und wie hoch der Anteil schmutziger Seiten im Buffer Pool ist. Wahrscheinlich ist es besser, andere Parameter anzupassen.
      [0] https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.ht...
    • Beim grundlegenden Tuning von Datenbanken, etwa bei der Blockgrößen-Ausrichtung, gibt es einen Punkt, den man überraschenderweise prüfen sollte. Üblicherweise heißt es, man solle die Record Size anpassen, und praktisch läuft das darauf hinaus, die Record Size des ZFS-Dateisystems zu reduzieren, auf dem die Daten liegen.
      Auf einer bestimmten Ebene kann das effizienter sein, aber meiner Erfahrung nach verschlechtert es die Kompressionsrate deutlich.
      Als interessanter Nebeneffekt kann sich, je nach Workload, der Durchsatz sogar verschlechtern, wenn die Plattenbandbreite der Engpass ist. Durch Kompression kann man schneller lesen und schreiben, als die physische Platte eigentlich leisten würde; wenn man die Kompression ruiniert, kann das die Lese-/Schreibbandbreite negativ beeinflussen.
  • Ich nutze ZFS unter Linux seit ein paar Jahren, und insgesamt lief es reibungslos.
    Das Einzige, was mich wirklich überrascht hat, war, dass der Standardwert für volblocksize für die meisten RAIDZ-Konfigurationen ziemlich ungünstig ist. Man muss den Wert erhöhen, wenn man nicht 50 % des rohen Plattenplatzes verlieren will.
    Die relevanten Beiträge sind diese:
    https://jro.io/nas/#overhead
    https://openzfs.github.io/openzfs-docs/Basic%20Concepts/RAID...
    https://www.delphix.com/blog/zfs-raidz-stripe-width-or-how-i...
    Am Ende bin ich sogar bei einer der ZFS-Tabellen gelandet:
    ZFS overhead calc.xlsx
    https://docs.google.com/spreadsheets/d/1tf4qx1aMJp8Lo_R6gpT6...
    RAID-Z parity cost
    https://docs.google.com/spreadsheets/d/1pdu_X2tR4ztF6_HLtJ-D...

    • Persönlich halte ich die 50 % Effizienz von Mirror-vdevs für einen fairen Preis, wenn man die Einfachheit und die deutlich bessere Performance bedenkt. Inzwischen lassen sich zwar auch RAIDZ-Pools erweitern, aber es ist immer noch deutlich komplexer und die Performance ist entsprechend schlechter.
  • Als ich jünger und noch dümmer war, las ich viele Beiträge von Enthusiasten darüber, wie großartig Open-Source-NAS-OS, vermutlich FreeNAS, und ZFS seien. Ich kaufte bei eBay einen gebrauchten HP MicroServer mit sehr niedriger Ausstattung und stürzte mich hinein, ohne wirklich zu wissen, was ich tat.
    Ich stellte ein paar Fragen in den Community-Foren, aber die meisten Antworten lauteten: „Hast du die Doku gelesen?“ und „Hast du genug RAM?“
    Diese Doku bestand aus schwer lesbaren PowerPoint-Folien, in einem leicht missionarischen Ton, mit vielen vorausgesetzten Kenntnissen, und sie wurde auch nicht regelmäßig aktualisiert. Wie viel RAM man brauchte, blieb ebenfalls vage; der Schwerpunkt lag einfach darauf, so viel wie möglich einzubauen.
    Am Ende ignorierte ich alle Warnsignale in Bezug auf die Technik, den Hype und meinen eigenen Wissensstand und verlor eine Menge Daten. Ich habe viel gelernt.

    • Ich frage mich, ob du noch weißt, wie lange das ungefähr her ist. ZFS gibt es seit Anfang der 2000er, und FreeNAS hat, soweit ich mich erinnere, 2005 angefangen.
      Das Dateisystem ist deutlich stabiler geworden, und auch die Dokumentation ist meiner Meinung nach klarer geworden.
      Trotzdem ist es mächtiger und fortgeschrittener als ein traditionelles Journaling-Dateisystem wie ext3, und damit gibt es auch mehr Möglichkeiten, sich selbst ins Knie zu schießen.
  • Um noch ein paar Dinge für später festzuhalten: Sämtliche Redundanz in ZFS liegt auf der vdev-Ebene. Ein zpool besteht aus einem oder mehreren vdevs, und egal in welchem Fall: Verliert man auch nur ein vdev innerhalb eines zpool, ist der zpool dauerhaft zerstört.
    Historisch ließ sich RAIDZ, also Parity-RAID, nicht durch Hinzufügen von Festplatten erweitern. Die einzige Möglichkeit, ein RAIDZ zu vergrößern, bestand darin, jede Platte im Array einzeln durch eine größere zu ersetzen und zu hoffen, dass während des Rebuilds keine Platte ausfällt.
    Nach sehr laienhafter Einschätzung würde ich RAIDZ nur bei einer großen Anzahl von Platten in Betracht ziehen, etwa RAIDZ2 oder RAIDZ3. Bei n<=6 und wenn das Budget es zulässt, würde ich mehrere Mirror-vdevs verwenden. In einer Produktionsumgebung sollte man die Lese-/Schreib-Performance-Kennzahlen der verschiedenen RAID-Varianten genauer untersuchen.

    • Mirror-Pools sind in der Regel tatsächlich der sicherere Ansatz.
      RAIDZ1 würde ich nur empfehlen, wenn es ein vollständiges Vor-Ort-Backup gibt und man den eigenen Fähigkeiten sowie dem Monitoring ziemlich vertraut.
      In meinem Fall habe ich einen Pool mit 3x3 Laufwerken und sende Snapshots an ein Backup-Ziel ein paar Höheneinheiten weiter unten im Rack. Dieses Backup-Ziel wacht täglich auf, hat einen Pool mit 3x4 Laufwerken und ist ebenfalls RAIDZ1.
      Wenn im NAS eine Platte ausfällt, ist mein Plan, das Backup sofort zu starten, die Snapshots entgegenzunehmen und dann die Platte zu ersetzen. So lässt sich die Wahrscheinlichkeit minimieren, dass während des Resilverings ein zweites Laufwerk ausfällt und Daten verloren gehen.
      Wirklich wichtige Daten liegen natürlich auch extern.
  • Ich habe ein ZFS-Problem, das ich nicht verstehe. Bei einem bestimmten zpool gibt zpool status eine Liste erkannter Fehler aus, aber sie erscheinen nicht bei Dateien, sondern immer nur bei Snapshots und vermutlich bei hexadezimalen Einträgen, die wie gelöschte Snapshots wirken.
    Wenn ich die als fehlerhaft markierten Snapshots lösche und zpool scrub zweimal laufen lasse, verschwinden die Fehler, und der Scrub findet ebenfalls keine Fehler. zpool status hat noch nie bei irgendeinem Gerät Fehler angezeigt.
    Es gibt keine Fehler in Dateien, keine Fehler auf Geräten, und auch beim Scrub werden keine Fehler erkannt, aber im laufenden Betrieb tauchen pro Tag ein Dutzend neue „Fehler“ in zpool status auf. Ich verstehe nicht, wie so etwas passieren kann.

    • Wirklich gute Frage. Ich habe gerade keine Zeit, selbst nach Duplikat-Issues zu suchen, aber du könntest in der Mailingliste https://zfsonlinux.topicbox.com/groups/zfs-discuss und in den GitHub-Issues https://github.com/openzfs/zfs/issues suchen oder dort fragen.
      Ersteres sieht seltsam aus, ist aber das normale Web-Frontend der Mailingliste.
    • Ich habe dasselbe Problem. Manchmal scheint eine Datei nicht nur im Snapshot, sondern auch in der aktuellen Dateiversion beschädigt zu sein.
      Man kann sie nicht verschieben oder ändern, nur löschen. Ich habe keinerlei Anhaltspunkt, warum diese Dateien beschädigt werden. Zum Glück waren es alles große Linux-ISOs, also war es nicht kritisch.