Sprawdzanie i raportowanie stanu puli ZFS

Warto zautomatyzować proces sprawdzania stanu puli ZFS i powiadamiania o problemach celem umożliwienia podjęcia szybkich działań. Poniższy skrypt pozwala sprawdzić jak się ma nasza pula:

#!/bin/bash
if [ "$(/usr/sbin/zpool status -x)" != "all pools are healthy" ]; then
echo -e "Jest jakiś problem z ZFS po wywołniu: zpool status -x\n\nPoniżej treść komunikatu:\n\n$(/usr/sbin/zpool status -x)" | mail -s "Problem z ZFS na $HOSTNAME" UŻYTKOWNIK_MAJĄCY_DOSTAĆ_WIADOMOŚĆ
else
sleep 1s
fi

Skrypt wywołujemy cyklicznie z crona dodając do crontab poniższą linię:

*/5 * * * *     /PATH_TO_SCRIPT/zpoolStatusCheck.sh

Sprawdzanie stanu dysków z użyciem S.M.A.R.T

Zdarzają się sytuacje w których system kontroli dysku przewiduje awarie ale w żaden sposób nie jest jeszcze ona widoczna dla ZFS. Poniższy skrypt zaraportuje nam, że z dyskiem może być coś nie tak. Zaznaczyć trzeba, że usterka dysku może się zdarzyć kompletnie bez wcześniejszych ostrzeżeń.

#!/bin/bash
/usr/sbin/smartctl -a /dev/disk/by-id/ata-XX > /dev/null
if [ $? != 0 ]; then
echo -e "Mamy problem z dyskiem /dev/disk/by-id/ata-XX\n\nPoniżej zrzut danych S.M.A.R.T\n\n$(/usr/sbin/smartctl -a /dev/disk/by-id/ata-XX)" | mail -s "Problem z dyskiem na $HOSTNAME" UŻYTKOWNIK_MAJĄCY_DOSTAĆ_WIADOMOŚĆ
else
sleep 1s
fi

/usr/sbin/smartctl -a /dev/disk/by-id/ata-YY > /dev/null
if [ $? != 0 ]; then
echo -e "Mamy problem z dyskiem /dev/disk/by-id/ata-XX\n\nPoniżej zrzut danych S.M.A.R.T\n\n$(/usr/sbin/smartctl -a /dev/disk/by-id/ata-YY)" | mail -s "Problem z dyskiem na $HOSTNAME" UŻYTKOWNIK_MAJĄCY_DOSTAĆ_WIADOMOŚĆ
else
sleep 1s
fi

Skrypt wywołujemy cyklicznie z crona dodając do crontab poniższą linię:

*/5 * * * *     /PATH_TO_SCRIPT/diskStatusCheck.sh

Różne drobne sprawy

Rzeczywiście zajęta przestrzeń na dysku:

zfs get used

Logiczny rozmiar danych zapisanych na dysku:

zfs get logicalused

Informacja o zastosowanym algorytmie kompresji:

zfs get compression

Informacja o współczynniku skompresowania danych na dysku:

zfs get compressratio

Specyficzne ustawienia ZFS

W pliku /etc/modprobe.d/zfs.conf możemy zmieniać ustawienia, które wypływają na to jak funkcjonuje system plików ZFS. Zwykle domyślne ustawienia są optymalne dla większości przypadków, ale jeżeli dokładnie wiemy co chcemy osiągnąć to warto nieco pozmieniać standardowe ustawienia.

Wszystkie parametry podajemy w jednej linii, która zaczyna się od: options zfs

Plik będzie miał postać: options zfs PARAMETR_1=WARTOŚĆ PARAMETR_2=WARTOŚĆ PARAMETR_3=WARTOŚĆ

Niże opisy poszczególnych parametrów:

  • zfs_txg_timeout=300 - zapisywanie grup transakcji na dyski co 5 minut (wcześniej tylko jeśli przepełni się bufor). Domyślą wartością jest 5 sekund.
  • zfs_arc_max=4294967296 - ogranicza zajmowaną przez ARC pamieć RAM do 4GB
  • zfs_dirty_data_max=1504967296 - maksymalna ilość danych przeznaczonych do zapisu na dysk, która może być przechowywana w pamięci RAM. Po jej przekroczeniu dane będą od razu zapisywane na dysk.

Bieżące ustawienia parametrów można podejrzeć w katalogu /sys/module/zfs/parameters/.

L2ARC

L2ARC potrafi przyśpieszyć pracę systemu ale nie zawsze i nie wszystkie dane muszą przechodzić przez ten poziom cache. Możemy wpływać na to, które datasety/woluminy będą przyśpieszane przez L2, mimo tego, że wcześniej L2ARC zostało uruchomione dla całej puli.

Jeżeli mamy wolumen na którym przetrzymujemy dane, których nie ma sensu buforować (archiwum wideo, zdjęcić, muzyki bądź pliki ISO) warto całkowicie wyłączyć ten wolumen z buforowania. Woluminy na których znajdują się dane, które są używane bardzo rzadko możemy od razu całkowicie wyłączyć z cache L2 wydając polecenie:

zfs set secondarycache=none NAZWA_PULI/DATASET

W przypadku jeśli z danego zbioru danych nie odczytujemy pełnych często danych ale często występuje potrzeba dostępu do metadanych możemy buforować tylko metadane. Tak sytuacja występuje kiedy dataset wykorzystujemy jako backup - zrzucamy na niego dane za pomocą rsync ale rzadko jest odczytujemy. Rsync przy każdej synchronizacji będzie szukał informacji o rozmiarze i dacie utworzeniu pliku (czyli będzie chciał dostępu do metadanych). Takie dane zgromadzone w L2ARC pozwolą uniknąć ogromnej ilości drobnych odczytów z głównych dysków naszej puli. Poniższym poleceniem ustawimy przetrzymywanie w L2ARC tylko metadanych dla danego datasetu:

zfs set secondarycache=metadata NAZWA_PULI/DATASET

Przywrócenie pełnego buforowania dla datasetu można uzyskać poleceniem:

zfs set secondarycache=all NAZWA_PULI/DATASET

Jeżeli L2ARC znajduje się na dysku SSD warto pozwolić systemowi na wysyłanie informacji o zwolnionych blokach do mechanizmów wear leveling dysku, w tym celu należy zmienić wartość parametru l2arc_trim_ahead z 0 na inną. Wartość wyrażana jest w %, w przypadku jeśli ustawimy 100% to TRIMowane będą bloki o rozmiarze ustawionym w l2arc_write_max ale nie mniej niż 64MB.

Trwały L2ARC

Standardowo cache L2 dla ZFS przepadał w momencie restartu systemu. Od mniej więcej 2021 roku pojawiła się funkcja pozwalająca przechować zawartość cache między restartami. l2arc_rebuild_enabled=1 dzięki temu ustawieniu między restartami systemu nie tracimy zawartości cache L2ARC.

Należy mieć na uwadze, że w przypadku jeśli L2ARC ma rozmiar 1GB lub mniej to standardowo mechanizm odpowiedzialny za odbudowę cache po restarcie nie zadziała. Wynika to z faktu, że ilość metadanych potrzebnych do odbudowy cache po restarcie jest stosunkowo duża i korzyści przy małym L2ARC zaczynają być iluzoryczne. Niemniej można zmienić parametr określający dolny limit pozwalający na odbudowę cache mniejszego niż 1GB. Do tego celu służy parametr l2arc_rebuild_blocks_min_l2size, jego domyślna wartość to 1073741824 czyli właśnie 1GB.

Problem ze sporadycznymi błędami zapisu na niektórych sprawnych dyskach SATA

Zdarza się, że ZFS potrafi zaraportować błędy odczytu/zapisu na zupełnie sprawnych dyskach. Problemem wtedy zwykle jest okablowanie albo kontroler ale nie zawsze. Jeżeli jest pewność, że dyski są OK (przetestowane w inny sposób niż w macierzy ZFS) a okablowanie i kontroler działają bezłędnie to rozwiązaniem problemu może być wyłączenie NCQ dla dysków sprawiających problemy. NCQ dla konkretnego dysku można wyłączyć wydając polecenie:

echo 1 > /sys/block/sd*/device/queue_depth

Zmiana nie wymaga ponownego uruchomienia systemu.

Ewentualnie można to zrobić dla całego systemu podając jako parametr startowy dla jądra libata.force=noncq

Poprzedni wpis Następny wpis