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
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
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
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 4GBzfs_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 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.
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.
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