SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor

Jak często wykonywać ZFS scrub na VPS z jednym dyskiem

Proces ZFS scrub weryfikuje sumy kontrolne bloków, ale na pojedynczym dysku nie naprawi błędów. Sprawdź, dlaczego warto uruchamiać go raz w miesiącu w celu wykrycia awarii.

Na czym polega proces ZFS scrub

Operacja ZFS scrub odczytuje każdy przydzielony blok w puli, ponownie oblicza jego sumę kontrolną i porównuje wynik z sumą zapisaną we wskaźniku bloku nadrzędnego. W przypadku rozbieżności ZFS naprawia blok, wykorzystując nadmiarowość dostępną w puli. Żaden inny mechanizm ZFS nie wykonuje tego zadania. Zwykłe operacje odczytu weryfikują tylko te bloki, do których uzyskano dostęp, dlatego plik nieotwierany przez dwa lata pozostaje niezweryfikowany, dopóki proces scrub go nie odczyta.

Proces scrub nie jest odpowiednikiem fsck, czyli trybu naprawy offline wymaganego przez inne systemy plików. Nie istnieje tu faza naprawy strukturalnej, ponieważ ZFS nigdy nie pozostawia formatu zapisu na dysku w stanie uszkodzonym: każdy zapis trafia w nowe miejsce, a uberblock, czyli główny wskaźnik puli, jest aktualizowany jako ostatni. Scrub nie odczytuje również całego urządzenia. Odczytuje wyłącznie przydzielone bloki, dlatego niemal pusta pula kończy proces w kilka minut, podczas gdy ta sama pula zapełniona w 80% wymaga znacznie więcej czasu.

Proces scrub działa z najniższym priorytetem I/O dostępnym w ZFS. W systemie Linux parametr zfs_vdev_scrub_max_active domyślnie wynosi 2, co oznacza, że na jeden vdev (urządzenie wirtualne, czyli grupę dysków traktowaną przez ZFS jako jednostka) przypadają maksymalnie dwa jednoczesne odczyty scrub. Parametr zfs_scrub_min_time_ms domyślnie wynosi 750; jest to minimalny czas, jaki wątek synchronizacji poświęca na pracę scrub pomiędzy zrzutami grup transakcyjnych, czyli okresowymi zatwierdzeniami, w których ZFS grupuje zapisy. Na bezczynnej maszynie scrub wykorzystuje pełną wydajność dysku. Pod obciążeniem proces ustępuje miejsca innym zadaniom. W puli z jednym lub dwoma urządzeniami nie ma miejsca na ustąpienie, dlatego harmonogramowanie jest tam istotniejsze niż w przypadku dużej obudowy z sześćdziesięcioma dyskami.

Dlaczego należy wykonywać scrub puli, która nie może się samodzielnie naprawić?

To zdanie rozstrzyga o wszystkim w przypadku małych pul. Bez redundancji scrub wykrywa uszkodzenie, ale nie potrafi go naprawić. Pojedynczy dysk wirtualny w VPS to pula bez mirrora i bez parzystości. ZFS odczyta uszkodzony blok, zgłosi błąd sumy kontrolnej, zliczy go w kolumnie CKSUM, wskaże nazwę pliku i na tym poprzestanie, ponieważ nie istnieje druga kopia, z której można by dokonać odbudowy.

Warto znać dwa częściowe wyjątki. ZFS domyślnie przechowuje dodatkową kopię metadanych (redundant_metadata=all), zapisywaną w innym obszarze urządzenia, więc scrub może naprawić uszkodzony wpis katalogu lub wskaźnik bloku nawet w puli składającej się z jednego urządzenia. Z kolei dataset z ustawionym copies=2 przechowuje dwie kopie swoich bloków danych, kosztem dwukrotnie większego zużycia miejsca. Żadne z tych rozwiązań nie chroni przed awarią całego urządzenia. Dokumentacja właściwości copies ostrzega dokładnie przed tym: nie należy tworzyć puli typu stripe, ustawiać copies=2 i wierzyć, że posiada się redundancję.

Zatem w puli z jednym urządzeniem scrub daje jedną korzyść: wczesne i dokładne powiadomienie. Zamienia ciche uszkodzenie danych na konkretną nazwę pliku w zpool status -v, podczas gdy kopia zapasowa wciąż zawiera poprawną wersję tego pliku. Jest to argument za tworzeniem kopii zapasowych, a nie przeciwko wykonywaniu scrubu. Jeśli kwestia różnicy między obrazem stanu w czasie a rzeczywistą kopią poza serwerem nie została jeszcze wyjaśniona, należy zacząć od dlaczego snapshot VPS nie jest kopią zapasową, ponieważ wynik scrubu jest użyteczny tylko wtedy, gdy istnieje nienaruszona kopia danych w innym miejscu.

Scrub, który niczego nie wykrywa, również jest wynikiem. Informuje on, że dane, którym zamierzasz zaufać, są nienaruszone, co jest kluczową wiedzą przed przystąpieniem do przywracania danych lub migracji.

Jak często należy wykonywać scrub małej puli na VPS?

Domyślną i zalecaną wartością jest częstotliwość miesięczna, co jest również założeniem większości pakietów. Systemy Debian i Ubuntu zawierają zadanie cron, które wykonuje scrub zdrowych pul w drugą niedzielę każdego miesiąca. System periodic w FreeBSD opiera się na progu wyrażonym w dniach, a daily_scrub_zfs_default_threshold domyślnie ustawia wartość 35, co w dokumentacji określono jako pięć tygodni.

Cotygodniowy scrub w przypadku małej, obciążonej puli zazwyczaj generuje więcej kosztów niż korzyści. Przy jednym lub dwóch urządzeniach proces scrub konkuruje o tę samą kolejkę I/O co aplikacja, a brak jest zapasowego urządzenia, które mogłoby przejąć to obciążenie. Na serwerze VPS limit operacji wejścia/wyjścia jest ograniczony, więc odczyty zużyte przez scrub to odczyty, których nie otrzyma baza danych. W zamian za ten koszt, cotygodniowy scrub zapewnia co najwyżej trzy tygodnie wcześniejszego ostrzeżenia o awarii, której i tak nie można naprawić. Taki kompromis jest opłacalny tylko wtedy, gdy koszt operacji scrub jest niski.

Zmierz czas trwania i podejmij decyzję. Uruchom jeden scrub ręcznie i sprawdź, ile czasu zajmuje jego wykonanie.

  1. Uruchom sudo zpool scrub tank podczas spokojnego wieczoru i zanotuj całkowity czas z zpool status.
  2. Jeśli proces zakończył się znacznie przed upływem godziny, a serwer pozostaje bezczynny w nocy, cotygodniowy scrub jest akceptowalny.
  3. Jeśli proces trwał wiele godzin w czasie, gdy pula obsługiwała ruch, pozostań przy częstotliwości miesięcznej i pozostaw to zadanie domyślnemu harmonogramowi pakietu.
  4. Ponownie zmierz czas, gdy pula znacząco wzrośnie, ponieważ czas trwania scrub zależy od ilości przydzielonych danych, a nie od pojemności dysku.

Niezależnie od wyboru, zapisz tę informację obok innych cyklicznych zadań administracyjnych. Scrub powinien znajdować się na tej samej liście co aktualizacje pakietów i rotacja logów: zobacz miesięczna lista kontrolna konserwacji serwera Linux.

Uruchamianie, wstrzymywanie i zatrzymywanie procesu scrub

sudo zpool scrub tank
sudo zpool status tank

Wstrzymanie i zatrzymanie to odrębne operacje. Wybór niewłaściwej może skutkować koniecznością powtórzenia wielu godzin pracy.

sudo zpool scrub -p tank
sudo zpool scrub tank
sudo zpool scrub -s tank

-p służy do wstrzymywania. Stan oraz postęp procesu są okresowo zapisywane na dysku, dzięki czemu wstrzymany scrub przetrwa eksport puli lub restart systemu: po ponownym załadowaniu pula pozostanie w stanie wstrzymania, oczekując na dalsze instrukcje. Ponowne uruchomienie zpool scrub wznawia operację od ostatniego punktu kontrolnego zapisanego na dysku. -s natomiast całkowicie zatrzymuje scrub, co oznacza, że kolejne uruchomienie rozpocznie proces od początku. Polecenia -p należy używać, gdy zasoby dyskowe są potrzebne przez krótki czas. Polecenia -s należy używać, gdy proces ma zostać całkowicie przerwany.

Warto znać jeszcze dwie dodatkowe flagi. -w powoduje, że polecenie oczekuje na zakończenie scrubu przed zwróceniem kontroli; jest to pożądane zachowanie w skryptach, aby kolejne kroki nie rozpoczęły się przedwcześnie. -e ogranicza scrub wyłącznie do plików z wykrytymi błędami danych, zgłoszonymi przez zpool status -v. Jest to szybki sposób na potwierdzenie, że plik przywrócony z kopii zapasowej jest poprawny.

ZFS wykonuje tylko jeden proces scrub lub resilver (odbudowę po wymianie urządzenia) jednocześnie na pulę, ponieważ obie operacje są intensywne pod kątem operacji wejścia/wyjścia (I/O). Jeśli trwa proces resilver, scrub oczekuje na swoją kolej.

Jak odczytać status zpool podczas trwania scrub

Uruchom sudo zpool status tank i analizuj własne wartości, zamiast porównywać je z danymi innych użytkowników. Podczas operacji scrub wiersz scan: zawiera liczbę przeskanowanych danych, liczbę wysłanych żądań, sumę całkowitą, liczbę naprawionych błędów, procent ukończenia oraz szacowany czas pozostały do końca.

Scanned to faza metadanych: ZFS przeszukuje drzewo bloków i gromadzi adresy wymagane do odczytu. Issued to faza danych: operacje odczytu faktycznie wysłane do urządzenia, posortowane według kolejności dyskowej. Sortowanie operacji scrub jest powodem istnienia dwóch liczników, przy czym to issued wskazuje rzeczywisty postęp. Na wczesnym etapie wartość scanned znacznie wyprzedza issued, a szacowany czas jest mało wiarygodny. Należy oceniać go dopiero po przekroczeniu dziesięciu procent.

Repaired zlicza bajty nadpisane z poprawnej kopii. W puli bez redundancji wartość ta pozostaje zerowa niezależnie od tego, co wykryje scrub, co stanowi liczbowe potwierdzenie wcześniejszego założenia.

Następnie należy sprawdzić kolumny dla poszczególnych urządzeń. READ i WRITE zliczają błędy I/O zgłoszone przez samo urządzenie. CKSUM zlicza bloki, które nie przeszły weryfikacji sumy kontrolnej; kolumna CKSUM jest głównym celem operacji scrub. Niezerowa wartość CKSUM na urządzeniu, które wydaje się sprawne, jest faktycznym błędem: dane zostały odczytane, ale ich zawartość jest nieprawidłowa.

Ostatni wiersz zawiera werdykt. errors: No known data errors oznacza wynik pozytywny. Każdy inny komunikat oznacza konieczność uruchomienia sudo zpool status -v tank, co wyświetli pełną listę błędów danych od czasu ostatniego pełnego scrubu, w tym nazwy plików, których dotyczą. Należy przywrócić te pliki z kopii zapasowej, uruchomić sudo zpool clear tank w celu wyzerowania liczników, a następnie ponownie wykonać scrub. Każdy pełny scrub przebudowuje tę listę, więc plik, którego nazwa nie pojawia się po pełnym, poprawnym skanowaniu, jest trwale utracony.

Które okresowe zadanie scrub jest skonfigurowane w systemie?

Nie należy zakładać, że takie zadanie istnieje, ani że jest tylko jedno. Mechanizm różni się w zależności od platformy i pakietu. Format puli jest wszędzie identyczny, co ułatwia zapomnienie o tym, że narzędzia wokół niej są różne, a sposób dystrybucji ZFS w FreeBSD w porównaniu z Linuxem stanowi tu kluczową różnicę.

W systemie FreeBSD zadanie znajduje się w systemie periodic. Należy je skonfigurować w /etc/periodic.conf:

daily_scrub_zfs_enable="YES"
daily_scrub_zfs_pools="tank"
daily_scrub_zfs_default_threshold="35"

daily_scrub_zfs_pools to rozdzielona spacjami lista nazw pul; pozostawienie jej pustej spowoduje wykonanie scrubu dla każdej puli. daily_scrub_zfs_default_threshold określa liczbę dni między operacjami scrub, gdy nie ustawiono progu dla konkretnej puli; dokumentacja podaje 35 jako wartość domyślną. Zadanie dzienne uruchamia się codziennie, ale rozpoczyna scrub tylko wtedy, gdy upłynął określony próg czasowy.

W systemie Linux zależy to od pakietu ZFS danej dystrybucji, a niektóre systemy obsługują oba mechanizmy jednocześnie. Istnieją timery systemd dla poszczególnych pul, zfs-scrub-monthly@tank.timer oraz zfs-scrub-weekly@tank.timer, włączane dla każdej puli z osobna. Debian i Ubuntu dostarczają również /etc/cron.d/zfsutils-linux, który uruchamia skrypt wykonujący scrub każdej puli w stanie ONLINE w drugą niedzielę miesiąca. Przed dodaniem czegokolwiek należy sprawdzić bieżącą konfigurację:

systemctl list-timers 'zfs-*'
ls /etc/cron.d/ | grep -i zfs
sudo zpool history tank | grep scrub

zpool history stanowi najbardziej wiarygodne źródło informacji, ponieważ rejestruje daty faktycznie rozpoczętych operacji scrub dla danej puli. Dwa zadania scrub w miesiącu oznaczają, że oba mechanizmy są aktywne i jeden z nich należy wyłączyć. Aby włączyć timer, należy wykonać:

sudo systemctl enable --now zfs-scrub-monthly@tank.timer

Wolne miejsce jest ważniejsze niż jakiekolwiek parametry dostrajania

Czas trwania operacji scrub w małej puli zależy od ilości przydzielonych danych oraz stopnia ich rozproszenia. Wypełnienie puli pogarsza oba te czynniki.

Zalecenia OpenZFS wskazują na utrzymywanie wolnego miejsca w puli powyżej 10%. Poniżej tej wartości metaslaby, czyli fragmenty, na których operuje alokator, zaczynają przekraczać próg 4% wolnego miejsca, a alokator przełącza się z trybu first-fit na best-fit. Tryb best-fit jest znacznie bardziej obciążający dla procesora. Opóźnienia zapisu rosną, pojawia się fragmentacja, a kolejny scrub trwa jeszcze dłużej, ponieważ ta sama ilość danych jest odczytywana jako większa liczba mniejszych operacji.

Pierwszym krokiem nie jest zatem zmiana parametrów, lecz usunięcie zbędnych danych. Najczęstszą przyczyną problemów na serwerach ZFS są stare snapshoty, a następnie nieusunięte obrazy i warstwy Docker oraz pakiety jądra pozostawione po aktualizacjach. Przed podjęciem jakichkolwiek innych działań należy uruchomić zfs list -o space, ponieważ pozwala to odróżnić miejsce zajmowane przez snapshoty od miejsca zajmowanego przez aktywne dane.

Poniżej krótki opis parametrów. W systemie Linux bieżące wartości można odczytać za pomocą:

cat /sys/module/zfs/parameters/zfs_scrub_min_time_ms
cat /sys/module/zfs/parameters/zfs_vdev_scrub_max_active

System FreeBSD udostępnia te same parametry poprzez sysctl, więc można je sprawdzić za pomocą sysctl -a | grep scrub. Zwiększenie ich wartości przyspiesza zakończenie operacji scrub, ale spowalnia działanie aplikacji. Zmniejszenie ich wartości przynosi odwrotny skutek. W przypadku puli z jednym lub dwoma urządzeniami żadne ustawienie nie zapewni obu korzyści jednocześnie, ponieważ dostępna jest tylko jedna kolejka do podziału. Parametry rzadko rozwiązują problemy projektowe. Jeśli comiesięczny scrub powoduje spadek wydajności, oznacza to, że pula jest zbyt pełna lub urządzenie jest zbyt wolne, a dostrajanie parametrów jedynie przesuwa problem w czasie.

Czas scrub to prognoza czasu resilver

Proces resilver wykonuje ten sam przegląd co scrub: odczytuje przydzielone bloki, weryfikuje je i zapisuje brakujące dane na urządzeniu zastępczym. Czas trwania operacji scrub stanowi zatem najbardziej wiarygodną prognozę czasu odbudowy puli oraz okresu, w którym pula będzie pracować z ograniczoną redundancją.

ZFS planuje zadania resilver bardziej agresywnie niż scrub, dlatego odbudowa zazwyczaj kończy się szybciej niż scrub tej samej puli. Czas scrub należy traktować jako konserwatywną górną granicę. Jeśli scrub trwa 9 godzin, należy zaplanować okno serwisowe o podobnej skali i pamiętać, że awaria drugiego urządzenia w tym czasie doprowadzi do utraty puli. Jest to praktyczny argument za stosowaniem par lustrzanych zamiast jednej szerokiej grupy raidz, ponieważ raidz, czyli układ parzystości stosowany w ZFS zamiast RAID 5, wymaga do odbudowy odczytu każdego sprawnego urządzenia.

W puli opartej na pojedynczym urządzeniu proces resilver nie występuje. Awaria urządzenia oznacza utratę puli. Czas odzyskiwania danych jest w takim przypadku równy czasowi przywracania z kopii zapasowej, dlatego należy mierzyć właśnie ten parametr. Procedura przywracania, która nigdy nie została przetestowana, nie stanowi planu odzyskiwania danych.

Co zmienia wynajęcie dysku

Na serwerze VPS urządzenie blokowe jest wirtualne. Hypervisor prezentuje wolumen, pod którym może znajdować się lokalny nośnik NVMe lub replikowany wolumen sieciowy z własną parzystością. Dla operacji scrub wynikają z tego dwie konsekwencje.

Po pierwsze, redundancja platformy jest niewidoczna dla ZFS i ZFS nie może z niej korzystać. Jeśli platforma naprawi błąd nośnika na niższym poziomie, ZFS nigdy nie wykryje problemu. Jeśli platforma przekaże błędny blok, ZFS go wykryje, ale nie będzie mógł naprawić, ponieważ poprawna kopia znajduje się po drugiej stronie tej granicy.

Po drugie, zazwyczaj nie można odczytać danych SMART (self-monitoring, analysis and reporting technology) dla urządzenia znajdującego się pod wirtualnym dyskiem, więc wczesne ostrzeżenia, od których zależy monitorowanie stanu dysku na VPS, mogą być całkowicie niedostępne. Licznik CKSUM z operacji scrub staje się głównym sygnałem, jakim dysponujesz.

Jeśli chcesz, aby ZFS naprawiał błędy, a nie tylko je zgłaszał, pula musi zawierać więcej niż jedno urządzenie w ramach tej samej instancji, co jest decyzją dotyczącą planu, a nie optymalizacji. Wybór serwera VPS typu storage zamiast zwykłego VPS zapewnia pojemność, choć to, czy otrzymasz dwa niezależne urządzenia, zależy od planu. Uruchom lsblk i sprawdź to przed utworzeniem mirrora na czymś, co może okazać się dwoma wycinkami tego samego wolumenu. Wynajmujemy serwery z systemem Linux i FreeBSD, a nie zarządzane urządzenie ZFS, więc harmonogram operacji scrub oraz kopie zapasowe należą do Twoich obowiązków. Taki jest układ: pełna kontrola nad pulą, pełna odpowiedzialność za jej utrzymanie.

FAQ

Jak często należy wykonywać scrub puli ZFS na VPS?

Dla większości małych pul wystarczająca jest częstotliwość miesięczna, co jest zgodne z domyślnymi ustawieniami pakietów: zadanie cron w drugą niedzielę miesiąca w systemach Debian i Ubuntu oraz domyślny próg 35 dni w systemie periodic w FreeBSD. Częstotliwość cotygodniowa jest uzasadniona tylko wtedy, gdy po zmierzeniu czasu trwania operacji scrub widać, że kończy się ona szybko na nieobciążonym serwerze. W przypadku intensywnie używanej puli z jednym lub dwoma urządzeniami, cotygodniowy scrub zużywa realne zasoby I/O aplikacji, oferując w zamian jedynie kilka tygodni wcześniejszego ostrzeżenia.

Czy scrub puli ZFS na pojedynczym dysku jest bezcelowy?

Nie, o ile użytkownik jest świadomy korzyści. Przy braku redundancji scrub wykrywa uszkodzenia, ale nie może ich naprawić, z wyjątkiem metadanych, których dodatkową kopię ZFS przechowuje domyślnie. Użytkownik otrzymuje listę uszkodzonych plików w zpool status -v, co pozwala na ich przywrócenie, dopóki poprawna kopia istnieje w innym miejscu. Właściwą reakcją jest poprawa strategii kopii zapasowych, ponieważ scrub wskazuje dokładnie, który plik wymaga przywrócenia.

Czy można wstrzymać scrub ZFS i dokończyć go później?

Tak. Polecenie zpool scrub -p tank wstrzymuje operację, a stan wstrzymania oraz postęp są okresowo zapisywane na dysku, dzięki czemu scrub pozostaje wstrzymany nawet po eksporcie puli lub restarcie systemu. Należy ponownie uruchomić zpool scrub tank, aby wznowić proces od ostatniego punktu kontrolnego. Nie należy używać do tego celu zpool scrub -s tank: -s przerywa scrub, a kolejny proces rozpocznie się od początku.

Dlaczego scrub ZFS trwa tak długo i czy można go przyspieszyć?

Czas trwania scrubu zależy od ilości przydzielonych danych i fragmentacji, a nie od pojemności dysku. Pula zapełniona w ponad 90% działa wolno, ponieważ metaslaby z wolnym miejscem poniżej 4% zmuszają alokator do przejścia z trybu first-fit na best-fit, a wynikająca z tego fragmentacja zamienia scrub w operację wielu małych odczytów. Zwolnienie miejsca zazwyczaj pomaga bardziej niż jakakolwiek zmiana parametrów konfiguracyjnych. Można zwiększyć wartości zfs_scrub_min_time_ms lub zfs_vdev_scrub_max_active, aby przydzielić scrubowi większy udział w kolejce, jednak w przypadku puli z jednym lub dwoma urządzeniami odbywa się to kosztem wydajności aplikacji.