IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Schlagwort: HDD

Tiered Storage live: Wie ein ZFS special vdev den HDD-Flaschenhals an der Wurzel packt

Ein einzelner ZFS-Pool aus zwei 7200-rpm-Platten war durch Metadaten-Random-I/O ausgebremst. Lösung ganz ohne Neuaufbau: die vorhandenen SSDs zu einem gespiegelten special vdev für Metadaten plus gespiegeltem SLOG umgebaut, zwei zpool add-Befehle im laufenden Betrieb. Resultat: Metadaten-Leselatenz von rund 46 ms auf rund 455 µs, also etwa Faktor hundert, bei voll erhaltener Verschlüsselung und Redundanz.

Drehende Platten sind ein ehrliches Stück Technik. Sie speichern viele Terabyte für wenig Geld und liefern bei sequenziellem Zugriff ordentlichen Durchsatz. Ihre Achillesferse ist der zufällige Zugriff auf viele kleine Blöcke, denn jede Kopfbewegung kostet Latenz im zweistelligen Millisekundenbereich aus Seek und Rotationswartezeit. Und genau dieses ungünstigste Muster produziert ein Copy-on-Write-Dateisystem wie ZFS am laufenden Band: Metadaten. Verzeichnis-ZAPs, dnodes, indirekte Blöcke, also die Block-Pointer-Bäume, dazu Spacemaps. Jedes ls, jedes stat, jeder Snapshot-Vergleich, jeder Scrub und jede find-Traversierung wühlt sich durch viele kleine, über die ganze Platte verstreute Metadatenblöcke. Auf einer HDD ist das der teuerste Spaß, den man haben kann.

Symbolische Darstellung eines ZFS-HDD-Mirrors mit SSD-special-vdev: Metadaten-I/O wird von Festplatten auf schnelle SSDs ausgelagert.

Ich hatte genau diesen Schmerz auf einem dedizierten Server: ein bewusst simpel gehaltener ZFS-Pool, zwei Enterprise-SATA-Platten im Mirror als Kapazitätsspeicher, und ein nagender Verdacht, dass die Spindeln der Flaschenhals sind. Die spannende Frage war nicht, ob man das beheben kann, sondern wie elegant. Die Antwort heißt allocation classes, konkret ein special vdev. Und das Schöne daran: Der Umbau lief komplett im laufenden Betrieb, ohne den Pool neu aufzubauen, ohne Downtime, mit zwei Befehlen. Dieser Beitrag zeigt den ganzen Weg, inklusive der Baseline-Messung, die den Engpass erst beweist, eines Verschlüsselungs-Stolpersteins beim Umbau und der ehrlichen Frage, was so ein special vdev wirklich bringt.

Die Ausgangslage

Der Server läuft auf FreeBSD 15.1-RELEASE (amd64, 12 CPU-Threads, 64 GiB RAM). Ein einziger ZFS-Pool, 2023 ganz bewusst als schlichter Mirror angelegt:

zpool create -o altroot=/mnt -O compress=lz4 -O atime=off -m none -f zroot mirror ada0p3 ada1p3
  • Das Daten-vdev sind zwei 7200-rpm-Enterprise-SATA-Platten mit je 2 TB als Mirror (mirror-0, rund 1,8 TiB nutzbar), der eigentliche Kapazitätsspeicher.
  • Dazu zwei Datacenter-SATA-SSDs mit je 240 GB und Power-Loss-Protection. Die waren vorher suboptimal genutzt: eine als einzelner, nicht gespiegelter SLOG, die andere als L2ARC.
  • ARC-Limit anfangs 16 GiB, poolweit compression=lz4 und atime=off von Anfang an.
  • ashift=12 erzwungen über vfs.zfs.vdev.min_auto_ashift=12, also 4K-Sektor-Alignment, korrekt auch dann, wenn die Platten brav 512-Byte-Sektoren melden.

Die Power-Loss-Protection der SSDs ist kein Detail am Rande, sondern später für die SLOG-Sicherheit relevant: Eine SSD ohne Pufferschutz darf bei einem synchronen Write nicht behaupten, die Daten lägen sicher, solange sie noch im flüchtigen Cache stehen. Datacenter-SSDs mit Kondensator-gestütztem Cache dürfen das, und genau das braucht ein SLOG.

Erst messen, dann bauen

Bevor ich auch nur eine Partition angefasst habe, kam die wichtigste Phase: messen. Ohne Baseline kauft man Hardware nach Bauchgefühl und tunt am falschen Ende. Also lief ein eigener, delta-basierter Sampler über 30 Minuten, 90 Samples zu je 20 Sekunden. Er liest sysctl-Counter für CPU, ARC und Netz sowie iostat -x für die Platten-Busy und die Latenzen. Die wichtigste Spalte zur Einordnung der Last ist net-out, also der ausgehende Netzdurchsatz als Proxy dafür, was während des Laufs tatsächlich los war.

Das Ergebnis der Baseline (16 GiB ARC, alte SSD-Rollen) war eindeutig:

  • Der Flaschenhals ist der HDD-Mirror. Busy im Mittel 58 bis 62 %, Spitzen bis 100 bis 104 %, Latenz im Mittel rund 8 ms, unter Last bis 20 bis 24 ms. In 16 % der Samples war die HDD zu 95 % oder mehr ausgelastet, also gesättigt.
  • Die CPU war zu rund 95 % idle, RAM frei, der Netz-Peak lag bei rund 68 Mbit/s, also nur etwa 7 % des Gigabit-Links. Weder CPU noch RAM noch Netz waren das Limit.
  • Der ARC klebte an seinem 16-GiB-Limit (Mittel 15,7 GiB) bei einer Hit-Rate von rund 94,7 %. Der ARC war schlicht ausgehungert und hätte mehr RAM sofort genutzt.
  • Der einzelne SLOG lief bei rund 42 % Busy, war also nicht gesättigt. Die Spindeln waren das Limit, nicht der SLOG.

Das ist die didaktische Pointe, die ich jedem ans Herz lege: Ohne diese Messung wüsste ich nicht, ob CPU, RAM, Netz oder Platten klemmen, und ich wüsste nicht, ob das Problem auf der Lese- oder der Schreibseite liegt. Messen ist kein Nice-to-have, sondern die Voraussetzung dafür, das richtige Bauteil zu kaufen und am richtigen Hebel zu drehen.

Was ein special vdev ist, und warum nicht einfach All-SSD

Allocation classes sind ein OpenZFS-Feature (feature@allocation_classes), mit dem ein Pool mehrere Klassen von vdevs führen kann. Das special vdev ist die Klasse für Metadaten: ZFS legt dnodes, indirekte Blöcke und poolweite Metadaten bevorzugt dort ab statt auf dem normalen Daten-vdev. Über die Dataset-Property special_small_blocks kann man zusätzlich kleine Datenblöcke unterhalb einer einstellbaren Schwelle aufs special vdev ziehen. Im Kern verschiebt man also genau die Datenklasse, die eine HDD am schlechtesten beherrscht, auf ein Medium, das genau dafür gebaut ist.

Dass das hier der richtige Hebel ist, ist nicht geraten, sondern messbar: Der ARC dieses Servers besteht zu rund 85 % aus Metadaten, konkret 17,4 GB Metadaten gegenüber 3,0 GB Daten im ARC. Der Workload ist also metadaten-dominiert. Metadaten auf SSD zu verlagern trifft den Engpass damit an der Wurzel, denn das ist exakt der Random-I/O, an dem die Platten am meisten leiden. Bevor ich mich für das special vdev entschieden habe, standen aber andere Optionen auf dem Tisch:

  • Kompletter All-SSD-Pool aus zwei großen SSDs: der sauberste Komplettfix, aber teuer und ein großer Umbau mit Pool-Neuaufbau und vollständiger Datenmigration. Overkill, wenn der Großteil der Kapazität aus kalten, überwiegend sequenziell gelesenen Daten besteht.
  • Mehr RAM und ARC: hilft nur der Leseseite und nur, solange der Working Set in den ARC passt. Schreib-Metadaten müssen trotzdem auf stabilen Speicher, daran ändert RAM nichts.
  • L2ARC behalten: abgeschafft. Bei 24 GiB ARC lag die Lese-Hit-Rate schon bei rund 98,5 %. Der L2ARC brachte nur rund 1,3 % zusätzliche Reads, ist flüchtig (nach einem Reboot leer) und kostet sogar ARC-RAM für seine Header. Das Kosten-Nutzen-Verhältnis war negativ.
  • special vdev: die gewählte Lösung. Nutzt die vorhandenen SSDs, kein Pool-Neuaufbau, adressiert exakt den gemessenen Metadaten-Schmerz, inkrementell und live im Betrieb machbar.

Der Umbau Schritt für Schritt

Aus dem alten Zustand mit einem einzelnen SLOG und einem L2ARC sollte ein SLOG-Mirror plus ein special-vdev-Mirror werden. Beide SSDs werden also jeweils zur Hälfte für beide Zwecke genutzt, jeweils gespiegelt. Zuerst die alten Single-Rollen entfernen:

zpool remove zroot ada3p1     # alter L2ARC
zpool remove zroot ada2p1     # alter (einzelner) SLOG

Und hier kam der erste Stolperstein, der so lehrreich ist, dass er einen eigenen Absatz verdient. Das SLOG-Remove schlug zunächst fehl:

cannot remove ada2p1: Mount encrypted datasets to replay logs

Die Ursache: Es existierten verschlüsselte Datasets, deren Keys in diesem Boot nie geladen waren. Der SLOG lässt sich nicht entfernen, solange potenziell noch nicht abgespielte ZIL-Einträge für gesperrte Datasets vorliegen, denn ZFS müsste diese Einträge zum Replay erst entsperren. Erst nach dem Aufräumen und Entsperren ließ sich der SLOG sauber entfernen. Das ist gleichzeitig die perfekte Überleitung zum Verschlüsselungskapitel weiter unten, denn es zeigt, wie tief native ZFS-Encryption in den ZIL-Pfad eingreift.

Danach die SSDs neu partitionieren, sauber 1-MiB-aligned. Pro SSD wird p1 16 GiB groß (SLOG) und p2 rund 208 GiB (special). Das Ergebnis von gpart show ada2 ada3:

=>       40  468862048  ada2  GPT  (224G)
         40       2008        - free -  (1004K)
       2048   33554432     1  freebsd-zfs  (16G)     # p1 -> SLOG
   33556480  435304448     2  freebsd-zfs  (208G)    # p2 -> special
  468860928       1160        - free -  (580K)

Jetzt der eigentliche Akt: gespiegelter SLOG und gespiegeltes special vdev werden hinzugefügt.

zpool add zroot log     mirror ada2p1 ada3p1
zpool add zroot special mirror ada2p2 ada3p2

Beide Befehle bewusst ohne -f. So bleibt der Redundanz-Schutz von ZFS als Sicherheitsnetz aktiv: ZFS verweigert ein nicht-redundantes special oder log neben einem Mirror, solange man es nicht ausdrücklich erzwingt. Und genau dieses Verweigern ist hier gewollt.

Die wichtigste Warnung dieses Beitrags: Ein special vdev ist nicht optional für die Pool-Integrität. Verliert man ein nicht gespiegeltes special vdev, ist der gesamte Pool verloren, denn die Metadaten liegen dort, und ohne sie ist der Rest unlesbar. Das special vdev muss mindestens so redundant sein wie das Daten-vdev, hier also als Mirror. Für den SLOG gilt das in dieser Schärfe nicht, ein verlorener SLOG kostet nur die letzten Sekunden async-bestätigter sync-Writes, aber ein SLOG-Mirror verhindert, dass ein einzelner SSD-Ausfall den ZIL-Schutz aushebelt.

Das fertige Layout sieht in zpool status und zpool list -v dann so aus:

zroot       mirror-0   ada0p3 + ada1p3   1.80T  (Daten, HDD-Mirror)
            special    mirror-3: ada2p2 + ada3p2   206G  (Metadaten, SSD-Mirror)  NEU
            logs       mirror-2: ada2p1 + ada3p1   15.5G (ZIL/SLOG, jetzt gespiegelt)

Zum SLOG-Sizing noch ein Wort, weil es oft falsch gemacht wird. Der SLOG puffert nur die dirty data eines, maximal zweier txg-Flush-Intervalle. Bei vfs.zfs.dirty_data_max = 4 GiB reichen 16 GiB SLOG mit großzügigem Polster, mehr bringt schlicht nichts. Genauso wichtig: Der SLOG beschleunigt nichts direkt. Er ist nur ein schnelles, stromausfallsicheres Zwischenlager für den ZIL, greift ausschließlich bei synchronen Writes (fsync oder O_SYNC) und wird im Normalbetrieb nie gelesen, sondern erst nach einem Crash zum Replay. Wer das verwechselt, sollte sich die Trennung einprägen: Der ZIL ist immer da, das ist das Konzept. Der SLOG ist nur ein optionales separates Gerät dafür.

Die unbequeme Wahrheit: nur neue Metadaten wandern

Hier muss ich ehrlich sein, denn es ist der am häufigsten missverstandene Punkt. Ein special vdev migriert keine bestehenden Metadaten. Es nimmt nur auf, was nach dem Hinzufügen geschrieben wird. Alte Metadaten bleiben auf der HDD liegen, bis sie durch Copy-on-Write ohnehin neu geschrieben werden. Der volle Effekt entsteht also erst über die Zeit oder durch einen optionalen zfs send | zfs recv-Rebuild der großen Datasets. Kein Sofort-magisch-alles-schneller, sondern ein Mechanismus, der sich befüllt. Dass er sich befüllt, sieht man an der Belegung, die mit jedem neuen Metadaten-Write wächst:

special   mirror-3   206G   alloc 5.38G   free 201G   FRAG 27%   CAP 2.60%

Die Messung danach, und wie man sie ehrlich liest

Jetzt kommt der Teil, an dem viele Tuning-Berichte unsauber werden, weil sie einen Vorher-Nachher-Durchsatz behaupten, der unter unterschiedlicher Last gemessen wurde und damit nichts beweist. Ich gehe einen anderen Weg und zeige die Wirkung über drei Argumente, von denen zwei komplett lastunabhängig sind.

Erstens der Latenz-Split pro vdev, das stärkste und lastunabhängige Argument. zpool iostat -lv zeigt die Latenzen getrennt pro vdev. Die folgende Tabelle sind seit-Boot-kumulierte Mittelwerte, also langzeit-repräsentativ und kein zufälliger Augenblick:

                  capacity     operations     bandwidth    total_wait
vdev            alloc   free   read  write   read  write   read   write
mirror-0        1.22T   595G     45      7   434K   601K   46ms   34ms    # HDD (Daten)
  ada0p3                         22      3   217K   300K   56ms   39ms
  ada1p3                         23      3   217K   300K   36ms   29ms
special/mirror-3 5.38G  201G      0     67  5.28K  3.24M  455us    6ms    # SSD (Metadaten)
  ada2p2                          0     33  2.67K  1.62M  447us    5ms
  ada3p2                          0     33  2.61K  1.62M  464us    6ms
logs/mirror-2   31.6M  15.5G      0     45      3   947K    2ms    1ms    # SSD (SLOG/ZIL)

Die Kernaussage steht in zwei Zahlen: Metadaten-Leselatenz 455 µs auf der special-SSD gegen 46 ms auf der HDD, das ist etwa Faktor hundert. Jeder Metadaten-Zugriff, der nicht ohnehin aus dem RAM bedient wird, ist seitdem rund hundertmal schneller. Zu den -l-Spalten kurz: total_wait ist die Gesamtwartezeit inklusive Queue, disk_wait die reine Gerätelatenz, syncq_wait und asyncq_wait die Zeit in den ZFS-internen Queues. Wer ein echtes Zeitfenster statt des Boot-Mittels sehen will, nimmt zpool iostat -lv zroot 10 2 und liest das zweite Sample, denn das erste ist immer der Seit-Boot-Durchschnitt.

Zweitens die ARC-Metadaten-Aufteilung, also die Struktur des Workloads. Sie erklärt, warum es gerade hier so viel bringt:

arcstats.metadata_size          = 17.4 GB     # rund 85 % des ARC sind Metadaten
arcstats.data_size              =  3.0 GB
arcstats.demand_metadata_hits   = 1,133,349,218
arcstats.demand_metadata_misses =    11,594,376   # müssen auf Platte ... jetzt SSD
arcstats.demand_data_hits       =   220,864,693
arcstats.demand_data_misses     =       672,908

Der Workload ist metadaten-dominiert. Die Lifetime-ARC-Hit-Rate liegt bei rund 98,9 %, aber die über 11,5 Millionen Metadaten-Misses müssen zwangsläufig auf Platte, und sie landen jetzt auf SSD statt auf HDD. Hier multipliziert sich der Faktor-hundert-Latenzvorteil mit der schieren Menge an Metadaten-Operationen. Das ist die quantitative Begründung dafür, warum ausgerechnet ein special vdev der wirksamste Hebel war und nicht etwa nur mehr ARC. Begleitend habe ich das ARC-Limit von 16 auf 24 GiB angehoben, weil RAM frei war. Die Folge war eine Hit-Rate von rund 95 % auf rund 99 %. Zwei Hebel, die zusammenwirken: weniger Misses überhaupt, und die verbliebenen sind jetzt SSD-schnell.

Das Herzstück: die 8,5-MB/s-Rechnung

Drittens, und das ist der eigentliche Aha-Moment, eine logische Schlussfolgerung statt eines Durchsatz-Vergleichs. Die Ausgangsmessung lief unter einer ganz konkreten Last: Ein Client lud zeitgleich größere Dateien herunter, ein klassischer Datei-Download. Der Netzdurchsatz dabei lag bei rund 68 Mbit/s, also etwa 8,5 MB/s. Und genau hier wird es interessant.

Eine einzelne 7200-rpm-HDD liefert sequenziell 150 bis 200 MB/s. Ein Download mit 8,5 MB/s ist also kaum 5 % dessen, was eine Platte im Schlaf kann, und hier zogen sogar zwei davon im Mirror mit. Trotzdem zeigte die Messung, dass der HDD-Mirror im Mittel rund 60 % ausgelastet war und in 16 % der Messintervalle voll gesättigt (95 % Busy oder mehr), mit Latenzen bis 20 bis 24 ms.

Das ist ein Widerspruch, und der Widerspruch ist der Beweis. Für sequenzielle 8,5 MB/s darf eine HDD niemals an die Sättigung kommen. Wenn sie es doch tut, dann waren diese Zugriffe nicht sequenziell, sondern seek-gebunden. Die Köpfe wurden permanent quer über die Platte gerissen. Wofür? Für das, was dieses System zu rund 85 % beschäftigt: Metadaten-Random-I/O, also dnodes, indirekte Blöcke und Verzeichnis-Lookups, die sich auf denselben zwei Spindeln mit dem Download um die Köpfe prügelten, verschärft durch die damals hohe Fragmentierung. Ein eigentlich harmloser Download zerfiel so in ein Seek-Gewitter.

Genau diese Konkurrenz wurde mit dem special vdev eliminiert. Die Metadaten-Zugriffe laufen jetzt auf den SSDs mit rund 455 µs statt zig Millisekunden. Die HDD-Köpfe können auf dem Datenstrom bleiben, statt ständig für Metadaten wegzuspringen. Derselbe Download belastet die Spindeln damit nur noch einen Bruchteil. Nicht, weil die Dateidaten schneller kämen, die liegen weiter auf HDD, sondern weil der Lärm daneben weg ist. Diese Schlussfolgerung steht ohne erfundenen Vergleich, sie ist wasserdicht: 8,5 MB/s sättigt physikalisch keine HDD, also waren es Seeks, also Metadaten-Kontention, und genau die habe ich verlagert.

Wie sich der Pool im ruhigen Normalbetrieb anfühlt, zeigt eine zweite, entspannte Momentaufnahme. Sie ist ausdrücklich kein Vorher-Nachher-Vergleich, sondern nur ein Blick auf den Alltag:

CPU idle 96.9 %   ARC hit 99.7 %   ARC 23.3 GiB
HDD busy ~2 %     HDD-Sättigung 0 %   HDD-Latenz ~1.5 ms
SSD busy 4.3 % / 4.5 % (gleichmäßig über beide Mirror-Member)
net-out-Peak 2.0 Mbit/s

Im ruhigen Normalbetrieb langweilt sich der HDD-Mirror, fast alle Reads kommen aus ARC oder SSD. Das illustriert den Alltag. Die eigentliche Wirkung des Umbaus zeigen aber die 8,5-MB/s-Rechnung oben sowie der Latenz-Split und die ARC-Aufteilung, und die gelten unabhängig von der Last.

Sicherheit und Verschlüsselung, die entscheidende Nuance

Die wichtigen Datasets dieses Systems sind nativ mit ZFS verschlüsselt (encryption = aes-256-gcm), die System- und Boot-Datasets nicht. Sobald man ein special vdev einführt, stellt sich sofort die sicherheitskritische Frage: Landet jetzt unverschlüsselter Klartext auf den SSDs, nur weil dort die Metadaten liegen? Die Antwort ist ein klares Nein, und die Begründung ist wichtig genug, um sie sauber auszuführen.

  • ZFS native encryption verschlüsselt Dateiinhalte und die sensiblen Objekt-Metadaten, also Dateinamen, Verzeichnisstruktur, dnodes, Attribute und ACLs. Diese Blöcke sind bereits Ciphertext, bevor der Allocator überhaupt entscheidet, auf welches vdev sie wandern. Ein special vdev ist nur ein anderer Ablageort und ändert an der Verschlüsselung nichts. Verschlüsselte Metadaten bleiben auf der special-SSD verschlüsselt.
  • Was ZFS-Encryption ohnehin nicht verbirgt, special vdev hin oder her, sind die Metadaten auf Pool- und Dataset-Ebene: Dataset-Namen, Pool-Struktur, Anzahl und Größe von Snapshots, die Blockpointer-Struktur. Das ist eine Eigenschaft von ZFS-Encryption und keine neue Schwäche durch das special vdev.
  • aes-256-gcm ist authenticated encryption (AEAD), liefert also Vertraulichkeit und gleichzeitig Integritäts- und Authentizitätsschutz der verschlüsselten Blöcke.

Ein schöner Praxisbezug schließt sich hier zum Umbau-Kapitel: Genau weil verschlüsselte Datasets im Spiel sind, blockierte das zpool remove mit der Meldung über das Mounten verschlüsselter Datasets zum Replay. Das zeigt anschaulich, wie tief Encryption in den ZIL- und SLOG-Pfad eingreift, denn der ZIL kann Einträge für verschlüsselte Datasets enthalten, die sich nur nach dem Entsperren abspielen lassen. Das Fazit zur Sicherheit ist damit eindeutig: Ein special vdev ist verschlüsselungs-neutral. Wer verschlüsselte Datasets nutzt, bekommt verschlüsselte Metadaten auf der special-SSD, kein Klartext-Leak.

Abwägung: Vorteile, Nachteile, Risiken

Was unterm Strich für das special vdev spricht:

  • Es adressiert den gemessenen Engpass, Metadaten-Random-I/O, direkt an der Wurzel.
  • Es nutzt vorhandene SSDs, also keine Neuanschaffung, kein Pool-Neuaufbau, live im laufenden Betrieb hinzugefügt.
  • Rund hundertfach niedrigere Metadaten-Leselatenz (455 µs gegen 46 ms), spürbar bei ls, stat, find, Snapshots, Scrub und allen Workloads mit vielen kleinen Dateien.
  • Über special_small_blocks später fein justierbar, um kleine Datenblöcke nachzuziehen, ohne Downtime und nur für neue Writes.
  • Verschlüsselungs-neutral.
  • Der I/O verteilt sich jetzt gleichmäßig über beide Mirror-Member. Vorher lag eine SSD als einzelner SLOG bei rund 42 % Busy, die andere als L2ARC quasi brach.

Und ehrlich auch die andere Seite, denn ein special vdev ist kein Selbstläufer:

  • Redundanz ist Pflicht, nicht Kür. Ein nicht-redundantes special vdev bedeutet Totalverlust des Pools bei SSD-Ausfall. Mirror ist zwingend.
  • Keine Migration bestehender Metadaten. Nur neue Writes wandern, der volle Effekt kommt erst per send und recv-Rebuild.
  • Das special vdev kann volllaufen. Ist es voll, fallen neue Metadaten auf das langsame Daten-vdev zurück. Das ist kein Fehler, aber der Effekt lässt nach, also Füllgrad mit zpool list -v überwachen.
  • special_small_blocks zu hoch gesetzt verstopft das special vdev mit Datenblöcken und lässt es schneller volllaufen. Vorsichtig hochtasten (von 0 über 4K und 8K bis vielleicht 32K) und dabei den Füllgrad beobachten.
  • Mehr vdevs bedeuten mehr Komplexität und mehr Teile, die ausfallen können. Den SSD-Wear im Blick behalten, hier bewusst Datacenter-SSDs mit Power-Loss-Protection gewählt, weil sie Dauerlast und sync-Writes aushalten.
  • Der zpool remove-Stolperstein mit verschlüsselten Datasets gehört dokumentiert, damit man im Ernstfall nicht in Panik gerät.

Die eigentliche Botschaft

ZFS erlaubt es, die Storage-Architektur inkrementell und im laufenden Betrieb an einen gemessenen Engpass anzupassen, ohne Pool-Neuaufbau, ohne Downtime, ohne Datenmigration als Vorbedingung. Aus einem simplen HDD-Mirror wurde durch zwei zpool add-Befehle ein hybrider, mehrstufiger Pool: kalte Massendaten auf günstigen Spindeln, heiße Metadaten und optional kleine Blöcke auf schnellen SSDs, synchrone Writes über einen gespiegelten SLOG. Diese Flexibilität, tiered storage als Live-Operation, kombiniert mit Checksumming, Compression, Snapshots und nativer Verschlüsselung im selben Dateisystem, ist der eigentliche Kern. Man kauft sich SSD-Speed genau dort, wo die Messung den Schmerz zeigt, und lässt den Rest günstig auf HDD. Kein anderes verbreitetes Dateisystem macht das so geradlinig.

Ausblick

  • special_small_blocks schrittweise anheben, um kleine Dateien und nicht nur Metadaten auf SSD zu ziehen, live und nur für neue Writes.
  • Ein optionaler send und recv-Rebuild der großen Datasets, um bestehende Metadaten auf das special vdev zu migrieren und so den vollen Effekt zu heben.
  • Eine lastgleiche Wiederholungsmessung in einem Hochlast-Fenster für eine saubere Zahl auf der Schreibseite.

Spickzettel

Die Befehle, mit denen man Layout, Latenzen und ARC-Komposition selbst nachsieht:

# Pool-Layout und Auslastung pro vdev
zpool status zroot
zpool list -v zroot

# Latenzen pro vdev (das Geld-Kommando), 2. Sample lesen für ein echtes Zeitfenster:
zpool iostat -lv zroot 10 2

# ARC: Größe und Metadaten/Daten-Split plus Demand-Hits und -Misses
sysctl kstat.zfs.misc.arcstats.size kstat.zfs.misc.arcstats.metadata_size kstat.zfs.misc.arcstats.data_size kstat.zfs.misc.arcstats.demand_metadata_hits kstat.zfs.misc.arcstats.demand_metadata_misses

# allocation_classes-Feature und special_small_blocks
zpool get feature@allocation_classes zroot
zfs get special_small_blocks zroot

# Verschlüsselungs-Status der Datasets
zfs get encryption,keystatus DATASET

# SSD-Partitionierung
gpart show ada2 ada3

# SLOG-Sizing-Kontext
sysctl vfs.zfs.dirty_data_max

# Pool-Historie (zeigt die echten add/remove-Befehle)
zpool history zroot

Siehe auch:

Selbst einen HDD-Pool mit einem special vdev entschärft, oder noch am Abwägen, ob sich der Umbau lohnt? Erzähl mir gern von deinem Layout, oder stell deine fragen.

Datenrettung mit Linux: ntfsundelete, ddrescue und PhotoRec im Praxistest

Ich wollte wissen, wie gut sich Daten mit Linux-Bordmitteln wiederherstellen lassen. Also habe ich eine alte Festplatte genommen und es systematisch ausprobiert. Erst normal gelöschte Dateien, dann ein RAW-Image, und am Ende habe ich die Platte physisch zerstört, um zu sehen was ddrescue und PhotoRec aus den Trümmern holen.

Vorbereitung: Testplatte befüllen

Die älteste funktionierende Platte aus meinem Fundus: eine WD Expert 136BA. Erst komplett mit Nullen überschrieben, dann partitioniert und als NTFS formatiert:

dd if=/dev/zero of=/dev/sdb1
mkfs.ntfs -L TestDatenloeschung -T /dev/sdb1

Einen ca. 1,53 GB großen Ordner mit verschiedensten Dateien habe ich dann so lange auf die Platte kopiert, bis sie voll war.

Dolphin zeigt die Ordner auf der Festplatte
kdf zeigt: Festplatte ist voll

ntfsundelete: Gelöschte Dateien wiederherstellen

Erster Scan, noch ohne etwas gelöscht zu haben:

ntfsundelete -s /dev/sdb1
# Files with potentially recoverable content: 0

Logisch, es wurde ja noch nichts gelöscht. Also ein paar Dateien weg und erneut scannen:

ntfsundelete -s /dev/sdb1
# Files with potentially recoverable content: 154

154 Dateien. Jetzt die Wiederherstellung:

ntfsundelete /dev/sdb1 -u -m '*.*' -p 100 -d /test

Die Optionen: -u für Undelete-Modus, -m '*.*' für alle Dateien (mit -m '*.doc' könnte man nur Word-Dateien holen), -p 100 für nur zu 100 % wiederherstellbare Dateien, -d /test als Zielverzeichnis. Bei Bildern könnte man den Prozentsatz auch niedriger setzen, Teile eines JPEG sind besser als nichts.

Alle 154 Dateien kamen vollständig zurück. Einzige Einschränkung: Dateien mit gleichem Namen werden nicht überschrieben. Sollte man beachten oder per Script lösen.

Arbeiten mit RAW-Images

Im Ernstfall arbeitet man nie mit der Originalplatte. Sobald man den Datenverlust bemerkt, am besten sofort den Stecker ziehen. Jeder weitere Betrieb, selbst ein Herunterfahren, kann die gelöschten Daten überschreiben. Also erst ein RAW-Image ziehen:

dd if=/dev/sdb1 of=/001/TestRettung.img
# 26709984+0 Datensätze ein
# 13675511808 Bytes (14 GB) kopiert, 701,766 s, 19,5 MB/s

ntfsundelete funktioniert genauso mit dem Image-File. Gleiche Ergebnisse, gleiche Wiederherstellung. Genau so soll es sein.

Die Festplatte zerstören

Jetzt wird es interessant. Mich hat natürlich interessiert, was bei einer physisch beschädigten Platte passiert. Also Platte wieder voll gemacht und dann aufgeschraubt.

Festplatte mit freigelegten Gehäuseschrauben
Geöffnete Festplatte, bereit zur Zerstörung

Vorsichtig ein paar Kratzer mit dem Schraubendreher auf die Magnetscheiben gesetzt. Nicht zu viel, aber genug, dass einige Gigabyte unlesbar sein sollten.

Festplatte wird mit einem Schraubendreher zerkratzt
Geöffnete Festplatte wird mit einem Schraubendreher zerkratzt
Geöffnete Festplatte mit zerkratzten Magnetscheiben

ddrescue: 52 Stunden an einer zerkratzten Platte

Platte wieder zugeschraubt und ddrescue drauf losgelassen:

ddrescue -n /dev/sdb1 /001/datenrettung.img /001/datenrettung.log
ddrescue -d -n -r3 /dev/sdb1 /001/datenrettung.img /001/datenrettung.log
ddrescue bei der Arbeit

Nach meiner kleinen Kratzorgie hat ddrescue 52 Stunden an der Platte gefummelt, bevor es durch war.

Wann zum Profi?

Wenn einem die Daten mehr als 3.000 Euro wert sind, sollte man einen professionellen Datenretter aufsuchen. Die nehmen zur Diagnose oft um die 90 Euro und sagen dann, was es wirklich kostet. Bei einem Fall aus 2010 hat ein Kunde mit einer 160 GB HDD und Headcrash einen Kostenrahmen von 15.000 bis 18.000 Euro genannt bekommen. Jede Bewegung an der Platte kann weitere Daten zerstören.

Ich habe selbst mal bei einer Seagate SCSI-Platte die komplette Elektronik von einer baugleichen getauscht, weil sie keinen Spin-Up mehr machte. Lief danach wieder, als wäre nie etwas gewesen. Auch ein Tausch der Schreib-/Leseköpfe hat einmal funktioniert, nachdem einer halb abgerissen war. Die Platte sprang genau ein Mal an, ich konnte sichern, beim nächsten Versuch ging nichts mehr. Solche Experimente klappen nicht immer. Hat man an der Platte herumgefummelt, hat oft auch der Profi keine Chance mehr.

PhotoRec: Dateien anhand des Headers retten

Das ddrescue-Image ließ sich in meinem Fall nicht mehr mounten. Durch die Kratzer war auch das NTFS-Dateisystem total im Eimer, selbst fsck half nicht. Also brauchte ich ein Programm, das Dateien anhand ihres Headers wiederherstellen kann: PhotoRec.

photorec datenrettung_parti_sicher.img
PhotoRec: Auswahl der Festplatte
PhotoRec: Auswahl der Partition
PhotoRec: Auswahl des Dateisystems
PhotoRec bei der Arbeit

PhotoRec hat erstaunlich viele Dateien aus der zerkratzten Platte zurückgeholt. Wer sich das Programm anschaut, sollte sich auch TestDisk vom gleichen Entwickler ansehen. Damit lassen sich gelöschte Partitionen rekonstruieren und noch vieles mehr.

TestDisk mit RAW-Image

Update 2026: Was bei SSDs und NVMe anders ist

Der Beitrag oben ist von 2010 und das merkt man. Die meisten Endgeräte haben heute keine drehende Festplatte mehr, sondern eine SSD oder NVMe. Das ändert das Spiel komplett.

Sobald TRIM oder UNMAP aktiv sind, meldet das Dateisystem dem Controller, welche Blöcke nach einem DELETE freigegeben sind. Der Controller löscht diese Zellen oft sofort oder beim nächsten Garbage-Collection-Lauf. Ergebnis: ntfsundelete oder PhotoRec laufen ins Leere, weil die Daten physisch schon weg sind. Wer ein Recovery-Tool an einer SSD ansetzt, sollte das Laufwerk vorher per Software-Hardware-Befehl ruhigstellen, also nicht mounten und keine TRIM-Befehle mehr absetzen lassen.

NVMe legt noch eine Schaufel drauf. Mit nvme sanitize oder nvme format --ses=1 ist nach Sekunden alles weg, kryptografisch sauber. Das ist gut für Hardware-Verkauf oder -Entsorgung, ein Albtraum für Recovery.

Verschlüsselte Datenträger sind ein eigenes Kapitel. BitLocker, LUKS, FileVault, APFS-Encryption: ohne den Schlüssel oder das Recovery-Passwort hilft kein Tool der Welt. Bei einem PCB-Defekt einer SSD wird es zusätzlich kritisch, weil moderne Controller die Verschlüsselung intern anders handhaben als der Host. Selbst wenn die NAND-Chips noch heile sind, bekommt ohne den passenden Controller-State niemand mehr Klartext zurück. Mit anderen Worten: ein einfacher PCB-Tausch wie bei meiner alten Seagate SCSI ist 2026 nicht mehr drin, schon gar nicht im Selbstbau.

Update 2026: Backup schlägt Recovery

Die ehrliche Wahrheit nach 15 Jahren: ich habe nicht mehr ein einziges Mal in echt eine Datenrettung gemacht. Nicht weil die Tools schlechter geworden wären, sondern weil ich Backups habe. Wenn eine Platte stirbt, ziehe ich den letzten Snapshot zurück und gut ist. Recovery ist die Notlösung, wenn das Backup fehlt oder kaputt ist.

Was ich heute tatsächlich nutze:

  • ZFS-Snapshots mit zfs-auto-snapshot: stündlich, täglich, wöchentlich. Auf der Workstation und im Storage. Versehentliches rm -rf oder ein Crypto-Trojaner sind in Sekunden zurückgerollt.
  • zfs send / zfs recv auf einen externen Pool und auf ein Offsite-System. Inkrementell, verschlüsselt mit zfs send -w, vollautomatisch per Cron.
  • Borg / Restic für die Geräte, die kein ZFS sprechen. Deduplizierend, verschlüsselt, push und pull-Modi.
  • Time Machine auf dem MacBook, weil es genau das macht was es soll.

Die 3-2-1-Regel ist alt und immer noch korrekt: drei Kopien, auf zwei verschiedenen Medien, eine davon räumlich getrennt. Cloud-Sync wie Dropbox, OneDrive oder Google Drive ist dabei kein Backup. Wenn dort etwas gelöscht wird, ist es im selben Moment auch lokal weg. Ein Backup ist immer eine Kopie, die nicht automatisch mitläuft.

Update 2026: Tools und Preise heute

Die guten Nachrichten zuerst: alle vier Tools aus dem Original werden weiter aktiv gepflegt.

  • GNU ddrescue: aktuell Version 1.28, läuft auf jedem Linux/BSD/macOS. Mit ddrescueview gibt es eine GUI, die das Mapfile visualisiert.
  • PhotoRec / TestDisk: Version 7.2, von cgsecurity.org. Versteht inzwischen über 500 Dateiformate, auch moderne wie HEIC, AVIF, MKV-Container.
  • ntfsundelete: Teil der ntfs-3g/ntfsprogs, weiterhin im Standard-Repository jeder Distribution.
  • SMART und Vorhersage: smartctl aus smartmontools ist Pflicht. Die Werte Reallocated_Sector_Ct, Current_Pending_Sector und Offline_Uncorrectable sagen oft schon Tage vorher, dass die Platte sterben wird.

Bei den Preisen für professionelle Datenrettung hat sich einiges getan. Die Diagnose liegt heute meist zwischen 50 und 200 Euro, oft sogar kostenlos wenn man den Auftrag erteilt. Die eigentliche Rettung ist stark gestaffelt: einfache Logikfehler ab etwa 300 Euro, mechanische Defekte mit Reinraum ab 800 bis 1.500 Euro, schwere Schäden mit Plattentausch und Adaption-Tabellen können immer noch vier- bis fünfstellig werden. Anbieter wie CBL, Ontrack oder Stellar geben kostenlose Erstdiagnose, das nutze ich heute auch wenn nur ein Verdacht im Raum steht.

Ein Hinweis noch: SSD- und NVMe-Recovery ist deutlich teurer als HDD-Recovery, weil der Reinraum-Aufwand durch teure Equipment-Setups für NAND-Reads ersetzt wird. Wer also wirklich wichtige Daten auf einer SSD hatte, fährt mit einem soliden Backup-Konzept finanziell und nervlich besser.

Fazit

Für normal gelöschte Dateien auf NTFS reicht ntfsundelete. Bei physischen Schäden ist ddrescue das Mittel der Wahl, um erst ein Image zu sichern. Und wenn das Dateisystem komplett zerstört ist, kann PhotoRec anhand der Datei-Header noch erstaunlich viel retten. Wichtigste Regel: Nie an der Originalplatte arbeiten, immer zuerst ein Image ziehen.

2026 gilt das alles weiter, mit zwei Einschränkungen. Auf SSDs und NVMe kommt man oft schon gar nicht mehr an die Daten. Und: das beste Recovery ist das, das man nie machen muss. Backup, Backup, Backup.

Siehe auch: FreeBSD: Automatische ZFS-Snapshots mit zfs-auto-snapshot, FreeBSD: ZFS-Datensicherung mit Snapshots und zfs send/recv und FreeBSD: Verschlüsseltes ZFS-Backup auf USB-Platte mit geli.

Fragen? Einfach melden.

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑