SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor

Как часто запускать ZFS scrub на VPS с одним диском

ZFS scrub проверяет целостность данных через контрольные суммы. На VPS с одним диском восстановление невозможно, но регулярный запуск помогает выявить ошибки чтения.

Что на самом деле делает ZFS scrub

ZFS scrub считывает каждый выделенный блок в пуле, пересчитывает его контрольную сумму и сравнивает результат с контрольной суммой, хранящейся в указателе родительского блока. Если значения не совпадают, ZFS восстанавливает блок, используя избыточность, предусмотренную в пуле. Никакая другая функция ZFS не выполняет эту задачу. Обычные операции чтения проверяют только те блоки, к которым вы обращаетесь, поэтому файл, который вы не открывали два года, остается непроверенным, пока scrub не считает его.

Scrub — это не fsck, этап автономного восстановления, который требуется другим файловым системам. В ZFS нет фазы структурного восстановления, так как ZFS никогда не оставляет формат на диске в поврежденном состоянии: каждая запись производится в новое место, а uberblock, корневой указатель пула, обновляется в последнюю очередь. Scrub также не считывает устройство целиком. Он считывает только выделенные блоки, поэтому почти пустой пул проходит проверку за минуты, а тот же пул при заполнении на 80% — значительно дольше.

Scrub выполняется с самым низким приоритетом ввода-вывода в ZFS. В Linux параметр zfs_vdev_scrub_max_active по умолчанию равен 2, поэтому на каждое vdev (виртуальное устройство, группа дисков, которую ZFS рассматривает как единое целое) приходится не более двух одновременных операций чтения scrub. Параметр zfs_scrub_min_time_ms по умолчанию равен 750 — это минимальное время, которое поток синхронизации тратит на работу scrub между сбросами групп транзакций (периодическими фиксациями, в которые ZFS объединяет записи). На простаивающей машине scrub использует весь ресурс диска. При нагрузке он уступает место. В пуле с одним или двумя устройствами уступать некуда, поэтому планирование здесь важнее, чем в крупном шасси с шестьюдесятью дисками.

Зачем выполнять scrub пула, который не может восстановить себя самостоятельно?

Этот вопрос определяет всё остальное при работе с небольшим пулом. При отсутствии избыточности scrub обнаруживает повреждение, но не может его исправить. Один виртуальный диск в VPS — это пул без зеркалирования и без контроля четности. ZFS прочитает поврежденный блок, обнаружит несовпадение контрольной суммы, увеличит счетчик в столбце CKSUM, укажет имя файла и на этом остановится, так как нет второй копии для восстановления данных.

Стоит знать о двух частичных исключениях. По умолчанию ZFS хранит дополнительную копию метаданных (redundant_metadata=all), записывая её в другую область устройства, поэтому scrub может восстановить поврежденную запись каталога или указатель блока даже в пуле из одного устройства. А набор данных с параметром copies=2 хранит две копии блоков данных, что требует вдвое больше места. Ни один из этих способов не спасет, если устройство выйдет из строя полностью. Документация к свойству copies прямо предупреждает об этом: не создавайте страйп-пул, не устанавливайте copies=2 и не считайте, что у вас есть избыточность.

Таким образом, в пуле из одного устройства scrub дает одно преимущество: раннее и точное уведомление. Он превращает скрытое повреждение данных в конкретное имя файла в zpool status -v, пока в вашей резервной копии еще хранится исправная версия этого файла. Это аргумент в пользу резервного копирования, а не против выполнения scrub. Если вы еще не разобрались в разнице между снимком состояния (snapshot) и полноценной внешней копией, начните с почему VPS snapshot не является резервной копией, так как результат scrub полезен только в том случае, если где-то еще хранится неповрежденная копия данных.

Scrub, который ничего не обнаружил, — это тоже результат. Он подтверждает, что данные, на которые вы собираетесь положиться, находятся в целости. Именно это необходимо знать перед выполнением восстановления или миграции.

Как часто следует выполнять scrub для небольшого пула VPS?

Ежемесячное выполнение — оптимальный вариант по умолчанию, именно на него рассчитаны пакеты. В Debian и Ubuntu поставляется cron-задание, которое выполняет scrub исправных пулов во второе воскресенье каждого месяца. В FreeBSD система periodic работает на основе порогового значения в днях, и daily_scrub_zfs_default_threshold по умолчанию установлено на 35, что в руководстве описывается как пять недель.

Еженедельный scrub для небольшого загруженного пула обычно приносит больше затрат, чем пользы. При наличии одного или двух устройств scrub конкурирует за ту же очередь ввода-вывода, что и ваше приложение, и нет свободного устройства, чтобы компенсировать это. На VPS лимит I/O ограничен, поэтому операции чтения, затраченные на scrub, — это операции чтения, которые не получит ваша база данных. Учитывая эти затраты, еженедельный scrub дает вам максимум три недели форы в обнаружении неисправности, которую вы все равно не сможете устранить. Такой компромисс оправдан только тогда, когда scrub обходится дешево.

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

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

Что бы вы ни выбрали, запишите это рядом с другими регулярными задачами по обслуживанию сервера. Scrub относится к тому же списку, что и обновление пакетов или ротация логов: см. ежемесячный контрольный список обслуживания Linux-сервера.

Start, pause and stop a scrub

sudo zpool scrub tank
sudo zpool status tank

Pausing and stopping are different operations, and picking the wrong one can cost you hours of repeated work.

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

-p pauses. Pause state and progress are synced to disk periodically, so a paused scrub survives an export or a reboot: the pool comes back with the scrub still paused, waiting for you. Running zpool scrub again resumes from the last checkpoint written to disk. -s stops the scrub instead, and the next scrub you start begins from the beginning. Use -p when you need the disk back for an hour. Use -s when you want the scrub gone.

Two more flags are worth knowing. -w waits until the scrub finishes before returning, which is what you want inside a script so the next step does not start early. -e scrubs only the files with known data errors as reported by zpool status -v, which is the quick way to confirm that a file you restored from backup is now clean.

ZFS runs one scrub or resilver, the rebuild that follows replacing a device, at a time per pool, because both are I/O intensive. If a device is resilvering, your scrub waits its turn.

Как просматривать статус 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) настроена на вашем сервере?

Не предполагайте, что такая задача одна, или что она вообще существует. Механизм зависит от платформы и пакета. Формат пула везде одинаков, из-за чего легко забыть, что инструменты управления различаются, и разница в поставке 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-таймеры для каждого пула: 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 запускается дважды в месяц, значит, активны оба механизма, и один из них следует отключить. Чтобы включить таймер, выполните:

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

Свободное место важнее любых настроек

Длительность процесса scrub в небольшом пуле определяется объемом размещенных данных и степенью их фрагментации. Заполнение пула ухудшает оба этих показателя.

Рекомендация OpenZFS — поддерживать объем свободного места в пуле на уровне выше 10%. При падении ниже этого порога metaslabs (блоки, с которыми работает аллокатор) начинают пересекать границу 4% свободного пространства, и аллокатор переключается с алгоритма first-fit на best-fit. Алгоритм best-fit требует значительно больше ресурсов CPU. Задержки записи возрастают, за ними следует фрагментация, и следующий scrub проходит еще медленнее, так как тот же объем данных теперь считывается большим количеством мелких операций.

Поэтому первый рычаг управления — это не настройка, а удаление данных. Частая причина нехватки места на сервере ZFS — старые снимки (snapshots), за которыми следуют неочищенные образы и слои Docker и ядра, оставшиеся после обновлений. Запустите zfs list -o space, прежде чем предпринимать что-либо еще: эта команда позволяет разделить место, занятое снимками, и место, занятое актуальными данными.

Теперь кратко о параметрах настройки. В 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, но замедляет работу приложений. Уменьшение дает обратный эффект. В пуле с одним или двумя устройствами ни одна настройка не даст преимущества, так как очередь всего одна. Настройка редко исправляет ошибки проектирования. Если ежемесячный scrub вызывает проблемы, это означает, что пул переполнен или устройство работает слишком медленно, а изменение параметров лишь маскирует проблему.

Время выполнения scrub — это прогноз для resilver

Процесс resilver выполняет те же действия, что и scrub: он считывает выделенные блоки, проверяет их целостность и записывает недостающие данные на заменяющий накопитель. Поэтому время, затрачиваемое на scrub, является наиболее точным и честным прогнозом того, сколько времени займет восстановление и как долго пул будет работать с пониженной избыточностью.

ZFS планирует задачи resilver более агрессивно, чем задачи scrub, поэтому восстановление обычно завершается быстрее, чем scrub того же пула. Рассматривайте время выполнения scrub как консервативную верхнюю границу. Если scrub занимает 9 часов, планируйте окно восстановления соответствующей длительности и учитывайте, что выход из строя второго накопителя в этот период приведет к потере пула. Это практический аргумент в пользу зеркальных пар вместо одной широкой группы raidz, так как raidz — схема с контролем четности, которую ZFS использует вместо RAID 5 — выполняет восстановление путем чтения каждого исправного накопителя.

В пуле из одного накопителя процесс resilver отсутствует вовсе. Если накопитель выходит из строя, пул также перестает существовать. Ваше время восстановления в этом случае равно времени развертывания из резервной копии, поэтому измеряйте именно его. Восстановление, которое вы никогда не запускали, не является планом восстановления.

Что меняется при аренде диска

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

Во-первых, избыточность платформы невидима для ZFS, и ZFS не может ее использовать. Если платформа исправляет ошибку носителя на нижнем уровне, ZFS никогда не узнает о проблеме. Если платформа передает ошибочный блок, ZFS обнаруживает это, но не может исправить, так как корректная копия находится за пределами этой границы.

Во-вторых, вы обычно не можете прочитать данные SMART (self-monitoring, analysis and reporting technology) для устройства под виртуальным диском, поэтому ранние предупреждения, от которых зависит мониторинг состояния дисков на VPS, могут быть вовсе недоступны. Счетчик CKSUM после выполнения scrub становится вашим основным индикатором.

Если вы хотите, чтобы ZFS не только сообщала об ошибках, но и исправляла их, пул должен содержать более одного устройства в рамках одного экземпляра, и это решение принимается на этапе планирования, а не настройки. Выбор storage VPS вместо обычного VPS обеспечивает необходимый объем, однако наличие двух независимых устройств зависит от конкретного тарифного плана. Запустите lsblk и убедитесь в конфигурации перед созданием зеркала, которое может оказаться двумя разделами одного и того же тома. Мы предоставляем в аренду серверы с Linux и FreeBSD, а не управляемое решение ZFS, поэтому график выполнения scrub и создание резервных копий — это ваша зона ответственности. Таков компромисс: полный контроль над пулом и полная ответственность за его обслуживание.

FAQ

Как часто нужно выполнять scrub пула ZFS на VPS?

Ежемесячный запуск подходит для большинства небольших пулов и соответствует стандартным настройкам пакетов: во второе воскресенье месяца через cron в Debian и Ubuntu, или с порогом в 35 дней по умолчанию в системе periodic в FreeBSD. Еженедельный запуск оправдан, только если вы замерили время выполнения scrub и убедились, что он быстро завершается на простаивающей системе. На нагруженном пуле с одним или двумя дисками еженедельный scrub каждую неделю потребляет ресурсы ввода-вывода, необходимые приложениям, при этом лишь незначительно ускоряя обнаружение проблем.

Бессмысленно ли выполнять scrub для пула ZFS на одном диске?

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

Можно ли приостановить scrub в ZFS и завершить его позже?

Да. Команда zpool scrub -p tank приостанавливает процесс, а состояние паузы и прогресс периодически записываются на диск, поэтому scrub остается приостановленным даже после экспорта пула или перезагрузки системы. Выполните zpool scrub tank еще раз, чтобы возобновить работу с последней контрольной точки. Не используйте для этого zpool scrub -s tank: -s полностью останавливает scrub, и следующий запуск начнется с самого начала.

Почему scrub в ZFS работает так медленно и можно ли его ускорить?

Время выполнения scrub зависит от объема размещенных данных и фрагментации, а не от емкости дисков. Пул, заполненный более чем на 90%, работает медленно, так как при свободном месте в метаслэбах менее 4% алгоритм распределения переключается с first-fit на best-fit, а возникающая фрагментация превращает scrub в серию мелких операций чтения. Освобождение места обычно помогает эффективнее, чем любые настройки. Вы можете увеличить значения zfs_scrub_min_time_ms или zfs_vdev_scrub_max_active, чтобы выделить для scrub большую долю очереди, но в пуле с одним или двумя устройствами это напрямую отразится на производительности ваших приложений.