SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor

Як часто запускати scrub у ZFS на VPS

scrub перевіряє кожен виділений блок, але на pool з одним пристроєм знаходить пошкодження, яке не може виправити. Дізнайтеся рекомендований графік.

Що насправді робить scrub у ZFS

scrub у ZFS читає кожен виділений блок у pool, повторно обчислює його checksum і порівнює результат із checksum, збереженим у батьківському block pointer. Якщо значення не збігаються, ZFS відновлює блок із доступної в pool надлишковості. Жоден інший механізм ZFS не виконує цього завдання. Звичайні операції читання перевіряють лише ті блоки, до яких ви звертаєтеся. Тому файл, який ви не відкривали два роки, залишатиметься неперевіреним, доки scrub його не прочитає.

scrub — це не fsck, офлайновий етап відновлення, потрібний іншим файловим системам. Етапу структурного відновлення немає, оскільки ZFS не залишає дисковий формат у пошкодженому стані: кожен запис виконується в нове місце, а uberblock, кореневий pointer pool, оновлюється останнім. scrub також не читає весь пристрій. Він читає лише виділені блоки. Саме тому scrub майже порожнього pool триває кілька хвилин, а для того самого pool із заповненням 80% — значно довше.

scrub виконується з найнижчим пріоритетом I/O, доступним у ZFS. У Linux zfs_vdev_scrub_max_active за замовчуванням дорівнює 2, тому для кожного vdev (virtual device, групи дисків, яку ZFS розглядає як один пристрій) одночасно виконуються не більш як два читання під час scrub. zfs_scrub_min_time_ms за замовчуванням дорівнює 750 — це мінімальний час, протягом якого sync thread витрачає між flush transaction group на роботу scrub. Transaction group — це періодичні commit, у які ZFS об’єднує записи. На не завантаженій машині scrub використовує весь диск. Під навантаженням він поступається іншим операціям. У pool з одним або двома пристроями поступатися особливо нікому, тому планування тут важливіше, ніж на великому chassis із шістдесятьма дисками.

Навіщо виконувати scrub для пулу, який не може самостійно відновлювати дані?

Це речення визначає все інше для невеликого пулу. Без надлишковості scrub виявляє пошкодження, але не може його виправити. Один virtual disk у VPS — це пул без mirror і без parity. ZFS прочитає пошкоджений блок, виявить помилку checksum, врахує її в колонці CKSUM, вкаже файл і зупиниться, оскільки немає другої копії, з якої можна відновити дані.

Варто знати про два часткові винятки. За замовчуванням ZFS зберігає додаткову копію metadata (redundant_metadata=all) в іншій області пристрою, тому scrub може виправити пошкоджений запис каталогу або вказівник на блок навіть у пулі з одним пристроєм. А dataset із copies=2 зберігає дві копії блоків даних, подвоюючи витрати дискового простору. Жоден із цих механізмів не допоможе, якщо пристрій стане недоступним. Документація до властивості copies прямо попереджає про це: не створюйте striped pool, не встановлюйте copies=2 і не вважайте, що отримали надлишковість.

Тому в пулі з одним пристроєм scrub дає вам одну перевагу: раннє й точне повідомлення. Він перетворює непомітне пошкодження на ім’я файлу в zpool status -v, поки backup ще містить справну версію цього файлу. Це аргумент на користь backup, а не проти scrub. Якщо ви ще не визначили різницю між образом на певний момент часу та справжньою копією поза сервером, почніть із матеріалу чому snapshot VPS не є backup, оскільки результат scrub корисний лише тоді, коли десь є неушкоджена копія.

Scrub, який нічого не виявив, також є результатом. Він повідомляє, що дані, яким ви збираєтеся довіряти, не пошкоджені. Саме це потрібно знати перед відновленням або міграцією.

Як часто слід виконувати scrub у невеликому пулі VPS?

Щомісячний запуск є оптимальним значенням за замовчуванням, і саме його вже передбачають пакети. Debian і Ubuntu постачають cron-завдання, яке виконує scrub справних пулів у другу неділю кожного місяця. Система periodic у FreeBSD працює на основі порога в днях, а daily_scrub_zfs_default_threshold за замовчуванням дорівнює 35, що в посібнику описано як п’ять тижнів.

Щотижневий scrub у завантаженому невеликому пулі зазвичай коштує більше, ніж дає користі. Якщо пристроїв один або два, scrub конкурує за ту саму чергу з вашим застосунком, і немає резервного пристрою, який міг би прийняти це навантаження. На VPS доступна пропускна здатність I/O обмежена, тому читання, які витрачає scrub, — це читання, недоступні вашій базі даних. За таку ціну щотижневий scrub дає щонайбільше на три тижні раніше попередження про несправність, яку все одно неможливо усунути. Такий компроміс має сенс лише тоді, коли scrub не створює значного навантаження.

Виміряйте тривалість і вирішіть. Запустіть один scrub вручну та простежте, скільки часу він займає.

  1. Запустіть sudo zpool scrub tank тихого вечора та зафіксуйте загальний час від zpool status.
  2. Якщо виконання завершилося значно менше ніж за годину, а сервер уночі простоює, щотижневий запуск є прийнятним.
  3. Якщо scrub тривав багато годин, коли пул обслуговував мережевий трафік, залиште щомісячний графік і доручіть його виконання завданню з пакета.
  4. Повторно вимірюйте тривалість щоразу, коли пул помітно збільшується, оскільки тривалість scrub залежить від обсягу виділених даних, а не від місткості диска.

Який би варіант ви не обрали, занотуйте його поруч з іншими регулярними завданнями на сервері. Scrub має бути в тому самому списку, що й оновлення пакетів та ротація журналів: див. щомісячний контрольний список обслуговування Linux-сервера.

Запуск, призупинення та зупинка scrub

sudo zpool scrub tank
sudo zpool status tank

Призупинення та зупинка — це різні операції. Неправильний вибір може призвести до повторного виконання роботи протягом кількох годин.

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

-p призупиняє scrub. Стан і перебіг операції періодично синхронізуються з диском, тому призупинений scrub переживає експорт пулу або перезавантаження: пул знову стає доступним, а scrub залишається призупиненим і очікує на вашу дію. Повторний запуск zpool scrub продовжує операцію з останньої контрольної точки, записаної на диск. Натомість -s зупиняє scrub, і наступний запущений scrub починається з початку. Використовуйте -p, коли диск потрібно звільнити на годину. Використовуйте -s, коли потрібно повністю скасувати scrub.

Варто знати ще два прапорці. -w очікує завершення scrub перед поверненням керування. Це потрібно в скрипті, щоб наступний крок не почався зарано. -e перевіряє лише файли з відомими помилками даних, про які повідомляє zpool status -v. Це швидкий спосіб переконатися, що файл, відновлений із резервної копії, тепер не містить помилок.

ZFS запускає для кожного пулу лише один scrub або resilver — відновлення після заміни пристрою — одночасно, оскільки обидві операції інтенсивно використовують I/O. Якщо для пристрою виконується resilver, scrub очікує своєї черги.

Як читати статус zpool під час виконання scrub

Виконайте sudo zpool status tank і аналізуйте власні значення, а не порівнюйте їх зі значеннями з чужого прикладу. Під час scrub у рядку scan: відображаються кількість просканованих даних, кількість переданих на читання даних, загальний обсяг, кількість відновлених даних, відсоток виконання та приблизний час до завершення.

Scanned — це фаза роботи з метаданими: ZFS обходить дерево блоків і збирає адреси, які потрібно прочитати. Issued — це фаза роботи з даними: фактично надіслані пристрою операції читання, упорядковані за розташуванням на диску. Саме через впорядкований scrub існують два лічильники, а issued показує фактичний прогрес. На початку scanned значно випереджає issued, тому оцінка часу майже неінформативна. Оцінюйте її після перших десяти відсотків.

Repaired показує кількість байтів, перезаписаних із коректної копії. У пулі без надлишковості це значення залишається нульовим незалежно від результату scrub. Це числове підтвердження описаного раніше обмеження, за яким можна стежити.

Потім перегляньте стовпці для окремих пристроїв. READ і WRITE підраховують помилки введення-виведення, про які повідомив сам пристрій. CKSUM підраховує блоки, що не пройшли перевірку контрольної суми; саме для заповнення цього стовпця призначений scrub. Ненульове значення CKSUM на пристрої, який виглядає справним, є реальною проблемою: дані було отримано, але вони виявилися пошкодженими.

Останній рядок містить підсумковий результат. errors: No known data errors означає успішне завершення. Будь-який інший результат означає, що потрібно виконати sudo zpool status -v tank. Ця команда виводить повний список помилок даних від моменту останнього повного scrub, зокрема назви пошкоджених файлів. Відновіть ці файли з резервної копії, виконайте sudo zpool clear tank для скидання лічильників, а потім знову запустіть scrub. Кожен повний scrub створює цей список заново, тому ім’я файлу, відсутнє після повного scrub без помилок, справді більше не фігурує в результатах.

Яке періодичне завдання scrub налаштоване на вашому сервері?

Не припускайте, що воно є, і не припускайте, що воно лише одне. Механізм залежить від платформи та пакета. Формат пулу всюди однаковий, тому легко забути, що інструменти навколо нього відрізняються. У цьому випадку важливо, як ZFS постачається у FreeBSD порівняно з Linux.

У FreeBSD завдання працює через систему periodic. Укажіть такі параметри у /etc/periodic.conf:

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

daily_scrub_zfs_pools — це список імен пулів, розділених пробілами. Якщо залишити його порожнім, scrub виконуватиметься для кожного пулу. daily_scrub_zfs_default_threshold — кількість днів між операціями scrub, якщо для пулу не задано окремий поріг. У посібнику як значення за замовчуванням наведено 35. Щоденне завдання запускається щодня, але починає scrub лише після спливу заданого порога.

У Linux це залежить від пакета ZFS у вашому дистрибутиві. Деякі системи одночасно використовують обидва механізми. Для окремих пулів існують systemd timers zfs-scrub-monthly@tank.timer і zfs-scrub-weekly@tank.timer, які вмикаються для кожного пулу окремо. Debian і Ubuntu також постачають /etc/cron.d/zfsutils-linux. Він запускає скрипт, який виконує scrub для кожного пулу зі станом ONLINE у другу неділю місяця. Перед додаванням будь-яких налаштувань перевірте, що вже використовується:

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

zpool history дає точну відповідь, оскільки записує фактично запущені операції scrub для пулу разом із датами. Два scrub на місяць означають, що працюють обидва механізми, і один із них потрібно вимкнути. Щоб увімкнути timer:

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

Вільний простір важливіший за будь-який параметр

Тривалість scrub для невеликого pool визначається обсягом виділених даних і ступенем їх фрагментації. Заповнення pool погіршує обидва показники.

OpenZFS рекомендує залишати вільними понад 10% pool. Нижче цього порога metaslab — ділянки, з якими працює allocator, — починають переходити поріг вільного простору 4%, і allocator перемикається з first-fit на best-fit. Best-fit потребує значно більше CPU. Зростає затримка запису, посилюється фрагментація, а наступний scrub триває ще довше, оскільки той самий обсяг даних надходить у вигляді більшої кількості менших операцій читання.

Тому першим засобом є не параметр. Потрібно видаляти зайві дані. На системах із ZFS найчастіше причиною є старі snapshots, далі — Docker images і layers, які ніхто не видалив, а також пакети kernel, що залишилися після оновлень. Виконайте zfs list -o space, перш ніж змінювати будь-що інше, оскільки ця команда розділяє простір, зайнятий snapshots, і простір, зайнятий активними даними.

Тепер коротко про параметри. У Linux поточні значення можна переглянути так:

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

FreeBSD надає ті самі параметри через sysctl, тому знайдіть їх за допомогою sysctl -a | grep scrub. Збільшення цих значень скорочує час scrub, але сповільнює роботу застосунку. Зменшення дає протилежний результат. Для pool з одним або двома пристроями жодне налаштування не дасть обидва результати, оскільки для розподілу є лише одна черга. Параметр рідко виправляє недоліки проєктування. Якщо щомісячний scrub створює проблеми, це означає, що pool надто заповнений або пристрій надто повільний, а параметр лише переміщує проблему.

Час scrub — це прогноз тривалості resilver

Операція resilver виконує такий самий обхід, як і scrub: читає виділені блоки, перевіряє їх і записує відсутні блоки на пристрій-заміну. Тому тривалість scrub — це найточніший практичний прогноз того, скільки триватиме відновлення і як довго пул працюватиме зі зниженою надлишковістю.

ZFS планує операції resilver агресивніше, ніж операції scrub, тому відновлення зазвичай завершується швидше, ніж scrub такого самого пулу. Вважайте тривалість scrub консервативною верхньою межею. Якщо scrub триває дев’ять годин, плануйте вікно відновлення приблизно такої самої тривалості та враховуйте, що відмова другого пристрою протягом цього вікна призведе до втрати пулу. Саме тому на практиці варто використовувати дзеркальні пари замість однієї широкої групи raidz, оскільки raidz — схема парності, яку ZFS використовує замість RAID 5, — відновлюється читанням з усіх пристроїв, що залишилися.

У пулі з одним пристроєм resilver взагалі неможливий. Виходить з ладу пристрій — разом із ним втрачається і пул. Ваш час відновлення дорівнює часу відновлення з резервної копії, тому вимірюйте саме його. Відновлення, яке ви ніколи не виконували, не є планом аварійного відновлення.

Що змінюється, коли ви орендуєте диск

На VPS блоковий пристрій є віртуальним. Гіпервізор надає том, під яким можуть бути локальні NVMe-накопичувачі або реплікований мережевий том із власною схемою паритету. Для перевірки цілісності даних це має два наслідки.

По-перше, надлишковість платформи невидима для ZFS, і ZFS не може її використовувати. Якщо платформа виправляє помилку носія на нижчому рівні, ZFS ніколи її не бачить. Якщо платформа передає неправильний блок, ZFS виявляє помилку, але не може її виправити, оскільки правильна копія перебуває по інший бік цієї межі.

По-друге, зазвичай неможливо прочитати дані SMART (self-monitoring, analysis and reporting technology) для пристрою під віртуальним диском. Тому ранні попередження, на яких залежить моніторинг стану диска на VPS, можуть бути взагалі недоступними. Лічильник CKSUM під час перевірки цілісності стає основним сигналом, який ви можете контролювати.

Якщо ви хочете, щоб ZFS не лише повідомляла про помилки, а й виправляла їх, пул має містити більше одного пристрою в тому самому екземплярі. Це рішення щодо конфігурації, а не параметр оптимізації. Вибір VPS зі сховищем замість звичайного VPS дає потрібний обсяг, але наявність двох незалежних пристроїв залежить від тарифного плану. Виконайте lsblk і перевірте це, перш ніж створювати mirror на двох розділах одного тому. Ми орендуємо Linux- і FreeBSD-сервери, а не керований пристрій ZFS, тому розклад перевірок цілісності та резервне копіювання ви маєте налаштовувати й запускати самостійно. Такий компроміс означає повний контроль над пулом і повну відповідальність за його обслуговування.

FAQ

Як часто слід виконувати scrub пулу ZFS на VPS?

Щомісячного запуску достатньо для більшості невеликих пулів. Це відповідає налаштуванням пакетів за замовчуванням: cron-завдання у другу неділю місяця в Debian та Ubuntu і порогове значення 35 днів у periodic system FreeBSD. Щотижневий запуск має сенс лише після вимірювання тривалості scrub, якщо він швидко завершується на інакше незавантаженому сервері. На зайнятому пулі з одним або двома пристроями щотижневий scrub щотижня витрачає реальні ресурси I/O застосунків і дає лише на кілька тижнів раніше попередження про проблему.

Чи марно виконувати scrub пулу ZFS на одному диску?

Ні, якщо чітко розуміти, що саме він дає. За відсутності надлишковості scrub виявляє пошкодження, але не може їх виправити. Виняток становлять метадані, для яких ZFS за замовчуванням зберігає додаткову копію. Результатом буде іменований список пошкоджених файлів у zpool status -v. Ви отримаєте його достатньо рано, щоб відновити файли, поки десь ще існує справна копія. Правильна відповідь — покращити резервне копіювання, оскільки scrub точно показує, який файл потрібно відновити.

Чи можна призупинити scrub ZFS і завершити його пізніше?

Так. zpool scrub -p tank призупиняє scrub, а стан паузи та прогрес періодично записуються на диск. Тому scrub залишається призупиненим після export або перезавантаження. Щоб продовжити виконання з останньої контрольної точки, знову запустіть zpool scrub tank. Не використовуйте для цього zpool scrub -s tank: -s зупиняє scrub, а наступний запуск починається спочатку.

Чому scrub ZFS виконується так повільно і як його прискорити?

Тривалість scrub залежить від обсягу виділених даних і фрагментації, а не від ємності диска. Пул, заповнений більш ніж на 90%, працює повільно, оскільки metaslab із менш ніж 4% вільного простору перемикає allocator із first-fit на best-fit. Фрагментація, що виникає після цього, перетворює scrub на велику кількість дрібних операцій читання. Звільнення простору зазвичай допомагає більше, ніж зміна будь-якого tunable. Можна збільшити zfs_scrub_min_time_ms або zfs_vdev_scrub_max_active, щоб надати scrub більшу частку черги. Але в пулі з одним або двома пристроями ця частка безпосередньо забирається у застосунку.