Вопрос или проблема
Пул подвергся постоянной потере данных в файле, который является частью снимка. Если бы данные файла были частью файловой системы (а не частью какого-либо снимка), я мог бы просто восстановить файл из подходящей резервной копии. Как я могу восстановить или отремонтировать (и устранить ошибки, сообщенные ZFS) файл в снимке из копии снимка или (частичной1) копии пула?
1 Где частичная копия содержит хотя бы затронутый снимок и предыдущий снимок тоже в затронутом пуле.
Пример
Вот простой для воспроизведения, но крайне искусственный пример:
Из (bash) командной строки:
cd
mkdir zfs-test
for i in {1..2}; do dd if=/dev/zero of=zfs-test/tank-file$i bs=1G count=1 &> /dev/null; done
sudo zpool create tank1 ~/zfs-test/tank-file1
sudo zpool create tank2 ~/zfs-test/tank-file2
sudo zfs snapshot tank1@snapshot1
sudo sh -c 'zfs send tank1@snapshot1 | zfs receive -F tank2'
Создайте текстовый файл /tank1/test-text-file с содержимым, которое вы легко сможете найти в шестнадцатеричном редакторе. Вот что я использовал:
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.
Снова из командной строки:
sudo zfs snapshot tank1@snapshot2
sudo sh -c 'zfs send -i tank1@snapshot1 tank1@snapshot2 | zfs receive -F tank2'
Теперь вам нужно испортить данные файла. Я использовал ht и искал “dui”, заменив его на “duh”.
Вы можете подтвердить, что данные повреждены:
sudo zpool scrub tank1; sudo zpool status -v tank1
pool: tank1
state: ONLINE
status: One or more devices has experienced an error resulting in data
corruption. Applications may be affected.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
see: http://zfsonlinux.org/msg/ZFS-8000-8A
scan: scrub repaired 0 in 0h0m with 1 errors on Sun Jan 11 20:16:30 2015
config:
NAME STATE READ WRITE CKSUM
tank1 ONLINE 0 0 1
/home/kenny/zfs-test/tank-file1 ONLINE 0 0 2
errors: Permanent errors have been detected in the following files:
tank1@snapshot2:/test-text-file
Всегда лучше использовать избыточные пула вместо не избыточных пулов (хотя это не всегда возможно). Приведенная выше проблема вряд ли возникнет в избыточном пуле. Кроме того, быстрее клонировать снимок (чтобы получить файл из него), чем воссоздавать его где-то (если, конечно, у вас нет претензий к неисправному оборудованию).
Вот мое немного обобщенное решение:
sudo cp /tank2/test-text-file /tank1/test-text-file
sudo zfs snapshot tank1@snapshot3
sudo sh -c 'zfs send -i tank1@snapshot2 tank1@snapshot3 | zfs receive -F tank2'
sudo zfs rollback -r tank1@snapshot1
sudo sh -c 'zfs send -i tank2@snapshot1 tank2@snapshot3 | zfs receive -F tank1'
sudo zpool scrub tank1; sudo zpool status -v tank1
И предполагая, что других ошибок не было:
sudo zpool clear tank1
Причина, по которой я создал snapshot3
, заключалась не в том, что он был необходим для моего (крайне искусственного) примера, а потому что это, вероятно, хорошая привычка, которую стоит развивать (и изначально я хотел проверить, что это сработает, как я и надеялся). Если бы на tank1
с момента snapshot2
были какие-либо другие изменения, я был бы рад не потерять их, восстанавливая test-text-file
.
Это теперь возможно с помощью корректирующего zfs receive см. https://github.com/openzfs/zfs/commit/e8cf3a4f7662f2d1c13684ce52b73ab0d9a12266
Я добавляю детали, чтобы поделиться, что это реальный сценарий, потому что это только что произошло со мной из-за ошибки контроллера / связи с пулом. У меня есть 4 ошибки данных, которые, похоже, затрагивают много файлов, однако, когда я внимательно изучаю это, на самом деле лишь 2 файла по ряду снимков. Удаление файлов, очевидно, не помогает, потому что они все равно останутся в снимках. Я мог бы удалить все снимки, но тогда я потерял бы свою защиту для хороших файлов. Единственное решение, которое я могу придумать в данный момент, это скопировать данные в новый пул, удалить исходный пул и воссоздать его, а затем скопировать данные обратно. Не очень элегантно.
Ответ или решение
Восстановление или ремонт поврежденного файла в снимке ZFS из резервной копии
Системы управления файловыми данными ZFS известны своей надежностью и эффективным управлением снимками. Однако, даже в самых устойчивых системах может возникнуть ситуация с повреждением данных. Это может произойти из-за различных проблем, таких как ошибочные записи, неисправные устройства или ошибки приложений. Таким образом, задача восстановить или исправить поврежденные файлы из снимка становится актуальной.
Шаги для восстановления поврежденного файла
В этой ситуации, когда файл находится в снимке и поврежден, есть возможность восстановления, используя копию базы данных или относительный снимок. Вот пошаговое руководство о том, как это сделать:
-
Идентификация проблемы:
После выполнения командыzpool scrub
вы можете увидеть сообщения об ошибках, указывающие на поврежденные данные. Важно задокументировать эти ошибки. -
Копирование файла из резервной копии:
Если у вас есть доступ к другому пулу ZFS (например,tank2
), содержащему неподвержденный снимок, можно скопировать файл для дальнейшей работы:sudo cp /tank2/test-text-file /tank1/test-text-file
-
Создание нового снимка:
Создайте новый снимок, чтобы сохранить текущее состояние, прежде чем вносить изменения:sudo zfs snapshot tank1@snapshot3
-
Обновление исходного пула:
Используйте командыzfs send
иzfs receive
, чтобы обновить пул с использованием последнего рабочей версии файла:sudo sh -c 'zfs send -i tank1@snapshot2 tank1@snapshot3 | zfs receive -F tank2'
-
Откат обратно в состояние без ошибок:
После успешного копирования файла можно откатить пул к состоянию, предшествующему повреждению:sudo zfs rollback -r tank1@snapshot1
-
Передача исправленного файла обратно:
После отката, передайте исправленный файл обратно в исходный пул:sudo sh -c 'zfs send -i tank2@snapshot1 tank2@snapshot3 | zfs receive -F tank1'
-
Проверка статуса пула:
Опять выполните командуzpool scrub
, чтобы убедиться, что нет больше ошибок:sudo zpool scrub tank1; sudo zpool status -v tank1
-
Очистка ошибок:
Если ошибок больше нет, вы можете очистить зарегистрированные ошибки с помощью:sudo zpool clear tank1
Рекомендации по предотвращению повреждений
- Используйте избыточные пулы: Использование пулов с резервированием, таких как RAID-Z, помогает значительно снизить риск повреждения данных.
- Регулярное создание резервных копий: Создавайте резервные копии данных регулярно, чтобы иметь возможность быстро восстановить их в случае сбоя.
- Систематическая проверка состояния пула: Настройте регулярные проверки состояния с помощью
zpool scrub
, чтобы своевременно выявлять ошибки.
Заключение
Восстановление поврежденного файла в снимке ZFS может оказаться сложной задачей, особенно если повреждение касается важных данных. Однако, соблюдая вышеуказанные шаги и используя возможности репликации ZFS, вы можете эффективно восстановить данные. Vажно помнить о просчитанных способах предотвращения подобных случаев, такие как использование избыточных пулов и регулярные резервные копии, чтобы минимизировать риски в будущем.