Schlagwort-Archive: ZFS

ZFS/ZOL: Pool UNAVAIL nach Reboot

Nicht schön. Nach dem Reboot eines Server musste ich feststellen, dass diverse Storages nicht mehr zugreifbar waren. Schnell stellte sich heraus, dass alle ZFS-Pools offline waren und die Geräte mit der Meldung „too many errors“ als FAULTED markiert wurden.

Nunja, Consumer-Platten traue ich ja viele defekte zu, aber drei unabhängige Platten gleichzeitig? Eher nein. Auch S.M.A.R.T. zeigte keine wirklich bedenkenswerten Werte. Aufschlussreicher ist da schon das Kernel-Log:

*kick* Da war ja was. ZOL läuft wegen der Lizenzproblematik als Kernel-Modul. Ich hatte zuletzt am Kernel einige Treiber nachgezogen. Hierbei sind zwar Version und Ablageort gleich geblieben, offenbar ist aber die ABI etwas gewandert, sodass SPL/ZFS etwas verwirrt den Dienst quittierten.

Für Gentoo heißt das einmal Module neu Bauen, in meinem Fall

 

Alternativ und in den meisten Fällen zuverlässiger ist es nach jeder Kernel-Änderung alle Module automatisch neu zu erstellen:

Storage online, Admins glücklich, Update-Doku ergänzt. Passt.

ZFS: Dateien trotz vollem Datenträger löschen

Narf – da war der Bug schneller als der Admin hinter dem Monitoring: 0k freier Speicher vermeldet ein ZFS-Storage. Na kein Problem, kaputtes Programm gestoppt und schnell mal den Schrott gelöscht. Oder auch nicht:

Really?!

Ursache wäre wohl „COW“ – Copy on write. Bei Änderungen werden die neuen Daten erst mal auf die Festplatte geschrieben – erst wenn dort kein Fehler auftritt werden die entsprechenden Zeiger im Dateisystem aktualisiert und die vorherigen Daten ungültig.

Die Lösung, welche z.B. bei der Uni Freiburg zu finden ist, ist effektiv, aber mir nicht wirklich verständlich: Anstatt die Datei zu löschen wird sie erst mit /dev/null überschrieben – dies schlägt trotz COW offenbar nicht fehl. Der so freigewordene Speicherplatz, welche zuvor durch den Inhalt der Datei belegt wurde, sollte nun ausreichen um den Löschbefehl umzusetzen:

[ZFS/Linux] Priorisierung und Systemlast durch Scrubbing kontrollieren

Das Scrubbing ist ein wichtiger Part der regelmäßigen Pflege eines ZFS-Systems. Hierbei liest das System alle belegten Dateisystemblöcke, vergleicht den Inhalt mit der hinterlegten Prüfsumme und korrigiert – wenn nötig – Fehler auf dem Speicher. Hierdurch ist sichergestellt, dass kippende Bits auf den Festplatten nicht den Inhalt der Datei beschädigen und Fehler frühzeitig erkannt werden. Ein Scrub wird hierbei über den Befehl „zpool scrub poolname“ gestartet.

Um Wöchentlich ein Scrubbing aller zpools durchzuführen nutze ich etwas Bash-Magie – das folgende Script erstellt eine Liste aller im System bekannten zpools und führt ein scrubbing dieser durch. Da ich zum Teil mehrere zpools auf Partitionen einer Platte habe wird immer nur ein Scrub simultan durchgeführt, so wird das Storage nicht zu stark belastet.

Aber auch ein einzelner Scrub stellt für das System eine nicht unerhebliche Last dar, welche sich negativ bemerkbar machen kann. In meinem Fall ist es eine Datenbank mit vielen kleinen Schreiboperationen, welche während des Scrubs nicht hinzunehmende Delays aufweist. Um hier Abhilfe zu schaffen kann ZFS eine Pause einlegen, sobald IO-Aktivität auf dem Pool entdeckt wird. Kontrolliert wird dieser Wert unter Linux mit dem Parameter /sys/module/zfs/parameters/zfs_scrub_delay – dieser ist per Default auf 4 eingestellt. Die Angabe bezieht sich hierbei laut Dokumentation auf Systemticks, bei den meisten Desktop-PCs ist Tickrate von 1000Hz, bei Server meist 100Hz, üblich. Um zu Prüfen wie das eigene System eingestellt ist kann meist folgender Einzeiler verwendet werden:

Wie zu sehen ist läuft mein System auf 250Hz. Zusammen mit der Angabe oben würde ZFS bei IO also für 16ms (1s/250Hz*4) pausieren. Um mir etwas Zeit zu verschaffen möchte ich diesen Wert auf 250ms erhöhen:

1 Sekunde / 250Hz = 0,004 Sekunden/Tick = 4 Millisekunden/Tick
250 Millisekunden / 4 Millisekunden ~= 63 Ticks

Dieser Wert wird entsprechend dem Parameter zugewiesen.

Wirklich messbar ist der Unterschied nur schwer, da er sich nur bei kleinen, zeitlich verteilten Operationen und nicht bei den benchmarküblichen und konstanten Sequential und Random-Operationen bemerkbar macht, gefühlt ist die Reaktion jedoch trotz scrub besser geworden.

Natürlich sollte man bedenken, dass der Scrub entsprechend länger dauert, die Werte sollten also nur temporär oder mit viel Vorsicht geändert werden.

MySQL/MariaDB unter Linux mit ZFS: Operating system error number 22 in a file operation

Nachdem LVM eine Qual ist wenn es um die Konfiguration von RAID geht (anm: Natives LVM-Raid, nicht md) und btrfs auf mehreren meiner Systeme gerne mal Dateien vergisst habt ich mich nach langer Zeit nochmal an ZFS gewagt. Die Funktionspalette ist beeindruckend: Integriertes RAID, integriertes Volumemanagement, Subvolumes, Kompression, Quota, etc. Alles natürlich verzahnt, sodass ein RAID-Rebuild wirklich nur belegte Dateisystembereiche rekonstruiert. Einzig die statische RAID-Konfiguration ist wenn man von LVM kommt etwas bedauerlich. Ansonsten scheint die Linux-Portierung des eigentlich von Solaris stammenden Systems inzwischen durchaus stabil.

Genug geredet, eigentliches Thema: MySQL unter ZFS. Als guter Einstieg sollte man hier einen Blick auf die Arch-Wiki werfen, welche einen Blick auf die Blockgrößen und Cache-Eigenheiten wirft. Doch egal wie: MySQL bzw. MariaDB haben noch eine Gemeinheit im Paket: Direct IO.

Da MySQL ein eigenes Caching implementiert versucht es über O_DIRECT die Dateicaches des Betriebssystems zu umgehen. Im Falle von ZFS ist dies durch den Aufbau nicht sonderlich hilfreich und wird durch den Linux-Treiber nicht unterstützt. Während die meisten Programme automatisch auf klassisches IO zurückfallen verabschiedet sich MySQL mit folgenden Log-Einträgen:

141019 18:07:42 InnoDB: Operating system error number 22 in a file operation.
InnoDB: Error number 22 means ‚Invalid argument‘.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
InnoDB: File name ./ib_logfile0
InnoDB: File operation call: ‚aio write‘.
InnoDB: Cannot continue operation.

Um das Problem zu beheben kann man die Datenbank über /etc/mysql/my.cnf in den klassischen IO-Modus zwingen, hierzu unter [mysqld] folgenden Eintrag ändern bzw. hinzufügen:

innodb_use_native_aio=0

im Anschluss sollte die Datenbank wieder wie gewohnt starten. Hinweis: Fehlender Direct-IO bringt auch Probleme mit KVM/LibVirt, auch hier sind ggf. Anpassungen notwendig.