Деякі інциденти не починаються з відмови диска чи kernel panic. Вони починаються з абсолютно здорової системи та однієї правильної за намірами команди: правка конфігурації, оновлення пакета, «прибирання», яке видаляє не ту директорію. Раптом ваш додаток не працює, дані дивні, а зацікавлені сторони видають ті звуки, які люди видають, коли дізнаються, що їхні плани на вихідні скасовано.
Відкат ZFS — один із небагатьох інструментів у продакшні, що вміє повернути час назад з хірургічною точністю. Але це також один з найпростіших способів випарувати потрібні знімки, зламати ланцюги реплікації або відкотити датасет, залишивши залежні системи в тонко корумпованому стані. Ось безпечний підхід: мінімізуйте радіус ураження, збережіть докази і збережіть своє майбутнє від сеансів терапії.
Що насправді робить відкат (і що він знищує)
zfs rollback переміщує «живий» датасет назад до точних вмістів знімка. Він не «зливає» чи «м’яко відміняє» зміни. Він перемотує вказівник голови датасету, що неявно відкидає зміни, зроблені після того знімка.
Ось що підступно: за замовчуванням ZFS не дозволить вам відкотитися через знімки, після яких існують новіші знімки, якщо ви явно не вкажете. Якщо ви використовуєте -r (рекурсивно) або -R (ще більш руйнівно рекурсивно), ви явно просите ZFS зруйнувати знімки та залежні клони, які “новіші” за цільовий знімок. Це може бути правильним рішенням. Але це також може бути саме тим моментом, коли ви переріжете історію реплікації й команда резервного копіювання перестане відповідати на дзвінки.
Операційно відкат краще сприймати як контрольовану руйнацію: ви можете зробити це безпечно, але лише якщо ви вже перевірили, що приєднано до того, що ви збираєтеся рухати.
Сімейне дерево знімків має значення
Знімки утворюють часову лінію. Відкат перемотує назад. Якщо після цієї точки є знімки, ті знімки посилаються на блоки, що представляють історію після цілі. Коли ви відкатуєте з руйнівними прапорами, ZFS очищує майбутнє, яке ви більше не хочете. Це не «небезпечно» — це просто остаточно.
Відкат — це не відновлення файлу
Якщо вам треба лише кілька файлів або директорію, монтувати або переглядати знімок безпечніше, ніж відкотити весь датасет. Відкат призначений для «датасет зараз неправильний, і ми хочемо повернути його точно таким, яким він був». Відновлення на рівні файлів — для «я пошкодував про одну команду, а не про всю свою особистість».
Одна цитата над терміналом
Парафразована ідея (Gene Kim, автор з надійності/DevOps): «Покращення приходить від зроблення роботи видимою і зниження вартості відновлення». Відкат знижує вартість відновлення — якщо ви тримаєте його видимим і під контролем.
Цікаві факти й історичний контекст
- ZFS поставлявся зі знімками з самого початку (початок 2000-х розробка Solaris), коли багато файлових систем все ще вважали «бекап» чужою проблемою.
- Знімки по суті безкоштовні для створення (лише метадані при створенні). Вони стають «дорогими» пізніше тільки тоді, коли різні блоки утримуються довше.
- Відкат миттєвий для метаданих, але операційний вплив не миттєвий: сервіси бачать раптову зміну стану, кеші стають неправдою, і додаткам можуть знадобитися кроки відновлення.
- Клони існують тому, що відкат занадто грубий: клон — це записувана гілка знімка, створена для безпечного тестування й вибіркового відновлення.
- Реплікація ZFS (send/receive) базується на знімках, отже рішення щодо відкату можуть зламати інкрементальні ланцюги, якщо ви видаляєте знімки, які очікує приймач.
- «USED by snapshots» спочатку плутає майже всіх: це не «розмір знімка», а «скільки було б звільнено, якби цей знімок зник».
- Holds у ZFS були введені, щоб запобігати випадковому видаленню критичних знімків, особливо в автоматизованих середовищах, де «скрипти прибирання» гуляють.
- Bookmarks існують для гігієни реплікації: вони фіксують точку для send без потреби фіксувати всі блоки як повний знімок.
- Відкат root-пулу став операційною практикою з boot environments (помітно на illumos і деяких Linux-настройках), роблячи «оновити потім відкотити» менш страшним.
Ментальна модель, яка запобігає паніці
Коли ви в середині інциденту, вам не потрібна поезія. Вам потрібна модель, яку можна виконати.
Думайте про три шари:
- Шар даних (ZFS): датасети, знімки, клони, утримання, bookmarks.
- Шар узгодженості (додатки): бази даних, черги повідомлень, файли, що мають один одного відповідати, WAL/redo логи, семантика відновлення після збоїв.
- Шар залежностей (опс): реплікація, бекапи, очікування моніторингу, споживачі змонтованих шляхів.
Відкат належить тільки шару 1. Інцидент зазвичай викликаний шарами 2 або 3. Ось чому «відкат виправив файли» інколи все одно залишає систему зламаною: світ додатка включає кеші, зовнішній стан і транзакційні інваріанти.
Правило: якщо додаток не витримує відключення живлення у будь-який момент, він не витримає відкат без явної координації. ZFS із задоволенням перемотить; ваша база даних з задоволенням пояснить, чому вона незадоволена.
Безпечні налаштування за замовчуванням: спочатку клон, потім відкат
Якщо ви нічого не запам’ятаєте: не відкатуйте в першу чергу, якщо ви не на 100% упевнені. Клонуйте знімок, змонтуйте його в безпечному місці, порівняйте, витягніть і лише потім думайте про відкат.
Відкат корисний для:
- Відкату невдалого оновлення пакета або конфігурації на виділеному датасеті чи boot environment.
- Скасування руйнівних файлових операцій, коли поточний стан датасету не вартий збереження.
- Відновлення відомого робочого образу сервісу, коли додаток безстанний або має власне журналювання для відновлення.
Відкат ризикований для:
- Баз даних із зовнішніми залежностями (репліки, PITR, binlog/WAL доставка).
- Датасетів, які використовують кілька сервісів, коли лише один «зламався».
- Систем з щільними ланцюгами реплікації, де видалення знімка ламає інкременти.
Жарт №1: Відкат як машини часу: працює чудово, поки ви не зрозумієте, що також видалили хроніку, де записали, що саме змінили.
Практичні завдання з командами, виводом і рішеннями
Це реальні операційні кроки, які можна виконати під тиском. Кожне завдання включає: команду, що означає вивід, і рішення, яке з цього випливає.
Завдання 1: Перевірте здоров’я пулу перед тим, як щось чіпати
cr0x@server:~$ zpool status -x
all pools are healthy
Значення: немає відомих помилок пристроїв або деградованих vdev. Якщо ви бачите “DEGRADED” або помилки контрольних сум, ваша проблема може бути апаратною або корупцією, а не «ой, ми змінили файл».
Рішення: Якщо пул не в нормі — зупиніться і стабілізуйте: scrub, замініть диски або принаймні зафіксуйте статус у нотатках інциденту перед будь-яким відкатом.
Завдання 2: Визначте точний датасет, який відповідає за mountpoint
cr0x@server:~$ zfs list -o name,mountpoint -S mountpoint
NAME MOUNTPOINT
tank /tank
tank/app /srv/app
tank/app/logs /srv/app/logs
tank/db /var/lib/postgresql
Значення: Тепер ви знаєте, якому датасету відповідає шлях. Люди відкочують «tank», коли мали на увазі «tank/app». Так виникають нові інциденти.
Рішення: Цілюйте найменший датасет, що містить зламаний стан.
Завдання 3: Перелікуйте знімки датасету й знайдіть кандидат
cr0x@server:~$ zfs list -t snapshot -o name,creation,used -s creation tank/app
NAME CREATION USED
tank/app@autosnap_2025-12-26 Fri Dec 26 01:00 2025 120M
tank/app@autosnap_2025-12-26_02-00 Fri Dec 26 02:00 2025 8M
tank/app@pre_upgrade Fri Dec 26 02:12 2025 0B
tank/app@post_upgrade Fri Dec 26 02:20 2025 35M
Значення: Імена знімків і час створення. USED — це скільки унікального простору було б звільнено, якби знімок видалили (не «розмір вмісту знімка»).
Рішення: Оберіть знімок, що відповідає вашій «останній відомо робочій» точці. Віддавайте перевагу явним знімкам на кшталт @pre_upgrade замість періодичних, коли вони доступні.
Завдання 4: Перевірте залежні клони (відкат може бути заблокований або руйнівний)
cr0x@server:~$ zfs list -t snapshot -o name,clones tank/app@pre_upgrade
NAME CLONES
tank/app@pre_upgrade tank/app-test
Значення: Існує клон tank/app-test на основі цього знімка. Деякі операції відкату, що руйнують знімки, можуть вимагати знищення залежних клонів.
Рішення: Якщо існують клони — віддайте перевагу «клонувати й відновлювати файли» замість відкату, або заздалегідь плануйте долю клону.
Завдання 5: Перевірте, чи існують новіші знімки, які будуть знищені
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 5
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00
Значення: Якщо ви відкотитесь до @pre_upgrade з рекурсивним прапором для знищення, все, що після нього — під ніж.
Рішення: Якщо пізніші знімки потрібні для реплікації або аудиту — не знищуйте їх; клон замість цього.
Завдання 6: Створіть зараз безпечний знімок (так, навіть якщо все зламано)
cr0x@server:~$ zfs snapshot tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs list -t snapshot -o name,creation | grep before_rollback
tank/app@before_rollback_2025-12-26T0235 Fri Dec 26 02:35 2025
Значення: Ви зберегли поточний зламаний стан. Це ваша криміналістика і «відкат відкату».
Рішення: Якщо відкат піде не за планом, ви зможете повернутися до цієї точки або витягти докази.
Завдання 7: Поставте hold на критичні знімки, щоб автоматизація не змогла їх видалити під час інциденту
cr0x@server:~$ zfs hold incident tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs holds tank/app@before_rollback_2025-12-26T0235
NAME TAG TIMESTAMP
tank/app@before_rollback_2025-12-26T0235 incident Fri Dec 26 02:36 2025
Значення: Знімок не можна буде знищити, поки hold не знято.
Рішення: Використовуйте holds коли існують скрипти прибирання або коли кілька людей «допомагають». Це дешевше за суперечки.
Завдання 8: Клонуйте знімок, щоб інспектувати й відновлювати без зміни продакшн
cr0x@server:~$ zfs clone tank/app@pre_upgrade tank/app_recover
cr0x@server:~$ zfs set mountpoint=/mnt/app_recover tank/app_recover
cr0x@server:~$ zfs mount tank/app_recover
cr0x@server:~$ zfs list -o name,mountpoint,mounted tank/app_recover
NAME MOUNTPOINT MOUNTED
tank/app_recover /mnt/app_recover yes
Значення: Тепер у вас є записувана гілка зі старим вмістом. Ви можете робити diff, копіювати або запускати перевірки без ризику для живого датасету.
Рішення: Якщо ви можете виправити продакшн, скопіювавши кілька файлів з клона — зробіть це і уникайте відкату взагалі.
Завдання 9: Порівняйте властивості датасету, що можуть вплинути після відкату
cr0x@server:~$ zfs get -H -o property,value compression,recordsize,atime,xattr,acltype tank/app
compression lz4
recordsize 128K
atime off
xattr sa
acltype posixacl
Значення: Властивості впливають на продуктивність і семантику. Відкат не змінює властивості (вони не прив’язані до знімків), але якщо хтось «пофіксив» щось зміною властивості після знімка, відкат цього не відкотить.
Рішення: Якщо інцидент спричинений зміною властивості — виправте властивість замість відкату даних. Або зберігайте властивості в конфігураційному менеджменті як окрему політику.
Завдання 10: Перевірте тиск на простір (знімки можуть блокувати звільнення; відкат може це посилити)
cr0x@server:~$ zfs list -o name,used,avail,refer,mounted tank
NAME USED AVAIL REFER MOUNTED
tank 8.21T 640G 96K yes
Значення: Лише 640G вільно. Якщо ви створюєте клони, отримуєте стріми або тримаєте багато знімків, ви можете вдаритися в 100% і спричинити падіння продуктивності або помилки при розподілі.
Рішення: Якщо вільного місця мало — уникайте операцій, що збільшують referenced space (великі клони, великі receive). Розгляньте видалення неважливих знімків (ретельно) або додавання ємності перед «хитрим» відновленням.
Завдання 11: Дізнайтеся, що фіксує простір через знімки
cr0x@server:~$ zfs list -t snapshot -o name,used,refer -S used tank/app | head
NAME USED REFER
tank/app@autosnap_2025-12-25_23-00 88G 612G
tank/app@autosnap_2025-12-26_00-00 74G 618G
tank/app@autosnap_2025-12-26_01-00 120M 620G
tank/app@before_rollback_2025-12-26T0235 0B 621G
Значення: Старі знімки з великим USED утримують багато блоків. Це зазвичай «очікувано», але саме так ви отримуєте «df каже вільно, ZFS каже ні».
Рішення: Якщо ємність є вузьким місцем — видаліть або відправте ті знімки, що утримують найбільше простору — після перевірки, що вони не потрібні для реплікації або відповідності вимогам.
Завдання 12: Пробний прогін впливу відкату, перелічивши, що буде знищено
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | awk '/@pre_upgrade/{flag=1}flag{print}'
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00
tank/app@before_rollback_2025-12-26T0235
Значення: Це «майбутнє» відносно @pre_upgrade. Якщо ви відкатитесь з руйнівними прапорами, ці знімки під прицілом.
Рішення: Якщо будь-який зі списку потрібен (реплікаційна точка, аудиторська точка, «before_rollback») — не знищуйте. Використайте клон або більш хірургічний підхід.
Завдання 13: Виконайте відкат (окремий датасет), тільки після того, як усе зроблено нудним
cr0x@server:~$ sudo systemctl stop app.service
cr0x@server:~$ zfs rollback tank/app@pre_upgrade
cr0x@server:~$ sudo systemctl start app.service
cr0x@server:~$ systemctl status --no-pager app.service
● app.service - Example App
Loaded: loaded (/etc/systemd/system/app.service; enabled)
Active: active (running)
Значення: Сервіс зупинено, щоб уникнути записів під час відкату. Відкат успішний і сервіс повернувся.
Рішення: Якщо сервіс все одно падає, ви тепер в зоні узгодженості додатка (міграції, кеші, дрейф схем). Перейдіть до відновлення на шарі додатка, а не знову «трусіть» ZFS.
Завдання 14: Якщо потрібно знищити новіші знімки під час відкату — зробіть це явно й розумійте радіус ураження
cr0x@server:~$ zfs rollback -r tank/app@pre_upgrade
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 3
tank/app@autosnap_2025-12-26_01-00
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade
Значення: Новіші знімки пропали. Це може включати анкори реплікації. Ось чому ви перевіряєте заздалегідь.
Рішення: Приймайте це тільки якщо підтверджено, що ви зможете повторно посіяти реплікацію, і у вас є збережений знімок before_rollback (можливо на іншій системі) на випадок потреби пізніше.
Завдання 15: Оцініть наслідки для реплікації, перевіривши bookmarks (якщо використовуються)
cr0x@server:~$ zfs list -t bookmark -o name,creation tank/app
NAME CREATION
tank/app#replica_base_01 Fri Dec 20 03:00 2025
tank/app#replica_base_02 Wed Dec 25 03:00 2025
Значення: Bookmarks можуть зберегти точки для send навіть якщо знімки видалено. Якщо ваша стратегія реплікації покладається на bookmarks, у вас більше гнучкості.
Рішення: Якщо є підходящий bookmark, ви зможете зберегти інкременти. Якщо ні — плануйте повне повторне насіння після руйнівного відкату.
Завдання 16: Перевірте обмеження, пов’язані з шифруванням, перед клонуванням або відправкою
cr0x@server:~$ zfs get -H -o property,value encryption,keylocation,keystatus tank/app
encryption aes-256-gcm
keylocation file:///etc/zfs/keys/tank_app.key
keystatus available
Значення: Шифровані датасети потребують завантажених ключів для монтування/receive-операцій залежно від дизайну. Сам відкат не «потребує» ключів в тому ж сенсі, але монтування клонів потребує.
Рішення: Переконайтеся, що матеріали ключа доступні перед клонуванням/монтуванням для відновлення. Якщо ключі відсутні — виправте керування ключами перш ніж сліпо відкатувати; відкат не поверне ключі.
Шпаргалка швидкої діагностики
Коли відкат розглядається, зазвичай ви ставите одне з двох питань: «Чи можу я безпечно перемотати?» і «Якщо я перемотую, чи це насправді виправить систему?» Ця шпаргалка оптимізована для швидкості й мінімального радіусу ураження.
Спочатку: підтвердьте, що ви ремонтуєте правильний шар
- Чи є стан відмови виключно на диску? Відсутні файли, неправильна конфігурація, пошкоджений артефакт деплою. Якщо так — ZFS може допомогти прямо.
- Чи є стан відмови у зовнішньому світі додатка? Несумісність схеми бази даних, кешовані секрети, несумісність downstream API, накопичені повідомлення. Якщо так — відкат може бути неактуальним або шкідливим.
- Чи це апаратна проблема або стан пулу? Якщо читання падають або затримки величезні — відкат нічого не змінить у фізиці.
По-друге: визначте найменший безпечний одиниці відкату
- Відобразьте mountpoints на датасети (
zfs list -o name,mountpoint). - Оберіть найбільш специфічний датасет, що містить проблему.
- Перевірте, чи існують дочірні датасети; не відкатуйте випадково дітей, які не повинні змінюватися.
По-третє: перевірте обмеження «не ламайте майбутнє»
- Реплікаційний ланцюг: Чи видалення новіших знімків зламає інкрементальні send?
- Клони: Чи існують залежні клони, які блокуватимуть або будуть знищені?
- Простір: Чи ви в межах безпечного запасу вільного місця для клонування/міграції, якщо потрібно?
- Координація: Чи можна зупинити записувачів чисто? Якщо ні — ви відкатуєтесь в рухому ціль.
Швидка перевірка вузьких місць, якщо все повільно (поширено під час інцидентів зі знімками)
cr0x@server:~$ zpool iostat -v 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 8.21T 640G 120 980 32.1M 210M
raidz2-0 8.21T 640G 120 980 32.1M 210M
sda - - 15 130 4.0M 28.0M
sdb - - 14 126 3.9M 27.5M
sdc - - 46 340 12.2M 72.1M
sdd - - 45 340 12.0M 72.0M
-------------------------- ----- ----- ----- ----- ----- -----
Значення: Нерівномірне навантаження по дисках може вказувати на збій диска, гарячий vdev або патологічні IO-шаблони. Часта генерація знімків за низького вільного місця також може перетворити записи на пекло.
Рішення: Якщо IO — вузьке місце, стабілізуйте продуктивність (запас місця, призупиніть важкі завдання, рознесіть scrub) перед великими операціями зі знімками.
Три корпоративні міні-історії з практики
Міні-історія 1: Інцидент через хибне припущення
Середня компанія запускала флот серверів зі ZFS для локального стану: конфіги, невеликі файли даних і деякі «тимчасові» артефакти, що ніколи не були тимчасовими. Вони звичали щогодини робити знімок усього пулу tank, бо це було просто. І, чесно, це працювало місяцями.
Потім інженер намагався відкотити невдалий деплой. Він побачив tank@pre_deploy і припустив, що відкат tank акуратно відмінить зміну. Він дійсно відміняв зміну. Але також відкатнув несуміжні датасети: директорію spool черги повідомлень і стан агента моніторингу. Spool тепер містив повідомлення, які вже оброблено. Агент моніторингу «забув», що бачив. Система не впала. Вона брехала.
Найдорожче було відставання: інцидент не оголосився гуркотом. Він виявився як дубльована робота, неконсистентні метрики і питання «чому черга повторює?» через три години. Всім довелося відтворювати події з логів — логів, що теж були на ZFS і теж відкотилися.
Виправлення не було магічним. Вони розділили датасети так, щоб одиниця відкату відповідала зоні відповідальності: tank/app, tank/queue, tank/monitoring. Також припинили вважати відкат пулу нормальним інструментом. Тепер «відкат» вимагає явного вказання датасету в плані змін.
Міні-історія 2: Оптимізація, що повернулася бумерангом
Інша організація хотіла швидших відновлень. Їхня ідея: частіші знімки, довша їхня утримка і опора на відкат для більшості «ой» моментів. Вони налаштували autosnap так, щоб тримати багато знімків на добу. Це тішило менеджерів, бо звучало як підвищена стійкість.
Що вони не змоделювали — це ампліфікацію записів під тиском простору. Знімки утримують старі блоки; видалення не звільняє простір, поки знімки не впадуть; вільний простір пулу зменшився; виділення стало фрагментованим; продуктивність погіршилась. Платформна команда помітила зростання затримок під час пік-операцій, але виглядало це як проблема додатка, бо пул був «healthy».
Потім стався реальний інцидент: погана міграція схеми. Вони хотіли відкатити датасет бази даних. Але не могли легко, бо приймач реплікації чекав ланцюга знімків, що простягався крізь довгу історію, а пул був занадто щільний, щоб клонувати для розслідування. Їхній «швидший recovery» змусив їх провести найповільніше відновлення: повне повторне насіння плюс вирівнювання на рівні додатка.
Після цього вони лишили часті знімки, але скоротили утримання для найгарячіших датасетів, ввели holds лише для pre-change знімків і впровадили політику мінімального вільного простору. Їхня найкраща оптимізація виявилась нудним алертом: «pool < 20% free».
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Сервіс, пов’язаний з платежами (без імен), працював на ZFS із суворим контролем змін. Перед кожним деплоєм їхній pipeline робив знімок з ім’ям @pre_change_$ticket. Знімок утримувався тегом і автоматично реплікувався на вторинну систему. Нічого фантастичного. Просто послідовно.
Одного вечора оновлення залежності прийшло із тонкою зміною дефолтного конфігу. Сервіс почав відмовляти валідним запитам. SRE отримали pager, і за кілька хвилин у них було чисте рішення: проблема почалась при деплої, їхній pre-change знімок існував, був утриманий і вже знаходився поза хостом.
Вони навіть не відкатували відразу. Вони клонували @pre_change, порівняли конфіги і знайшли зміну дефолту. Вони зробили хотфікс конфігу на місці. Відкат не знадобився, ланцюг реплікації не зламався, і звіт по інциденту мав чітку часову лінію, бо знімок «зламаного стану» теж існував.
Це не було гламурно. Це було еквівалент чищення зубів у системному адмініструванні. І це спрацювало.
Поширені помилки: симптом → корінь → виправлення
1) «Відкат не вдався: датасет має залежні клони»
Симптоми: Помилки команди відкату з посиланням на клони або «dataset is busy» чи залежності клонів.
Корінь: Знімок, через який ви намагаєтесь відкотитись, є джерелом клону, або датасет змонтовано й він активний у використанні.
Виправлення: Перелічіть клони знімка, вирішіть, чи зберігати їх, і перейдіть на відновлення через клон, якщо не можете їх видалити. Зупиніть сервіси й відмонтуйте, якщо це просто «busy». Використовуйте zfs list -t snapshot -o name,clones і lsof/fuser на mountpoint за потреби.
2) «Ми відкотили, а додаток все ще зламаний»
Симптоми: Файли виглядають правильно, але помилки додатка лишаються; база даних скаржиться; кеші не співпадають.
Корінь: Стан додатка поза датасетом: зміни схеми, зовнішні черги, віддалені залежності або очікування журналювання.
Виправлення: Розглядайте відкат лише як перший крок. Координуйте відновлення додатка: відновлення бази даних після крашу, логи undo/redo, перевірки версії схеми, очищення кешів або відкат тільки артефактного датасету, а не бази даних.
3) «Відкат знищив знімки і реплікація тепер застрягла»
Симптоми: Інкрементальний zfs send падає; приймач скаржиться на відсутні знімки; помилки інструментів реплікації після відкату.
Корінь: Руйнувальний відкат (-r/-R) видалив знімки, що слугували основою для інкрементів.
Виправлення: Повторно насійте реплікацію повним send або використайте bookmarks, якщо ваша стратегія їх підтримує. На майбутнє: ніколи не видаляйте знімки, які використовуються як якорі реплікації; утримуйте їх, поки приймач не підтвердить.
4) «Після видалення даних простір не повернувся»
Симптоми: Ви видаляєте гігабайти, але zfs list показує мало змін; пул залишається заповненим; записи гальмують.
Корінь: Знімки утримують видалені блоки.
Виправлення: Визначте знімки з великим USED і очистіть їх згідно з політикою збереження/реплікації. Розгляньте розділення датасетів, щоб каталоги з великим обігом не фіксували простір по всьому сервісу.
5) «Ми відкотили невірний датасет»
Симптоми: Несуміжні сервіси відкотились; логи зникли; моніторинг показує подорож у часі; приходить кілька команд.
Корінь: Відображення mountpoint→датасет було припущенням, а не перевірено. Або відкат виконано на рівні пулу.
Виправлення: Завжди відображайте mountpoint на датасет і відкатуйте тільки цей датасет. Використовуйте явні імена датасетів у runbook. Якщо потрібно відкотити кілька датасетів — знімкуйте їх разом (див. чеклісти) і відкатуйте скоординовано.
6) «Відкат завершено, але поведінка прав/ACL дивна»
Симптоми: Помилки доступу або зміни оцінки ACL після відкату; файли «виглядають» правильно, але поводяться інакше.
Корінь: Властивості датасету (ACL type, xattr mode) або обробка ACL на рівні ОС змінились. Знімки не повертають властивості датасету.
Виправлення: Порівняйте вивід zfs get з базовою конфігурацією; відновіть властивості через конфігураційний менеджмент. Трактуйте властивості як код.
7) «Відкат на зашифрованому датасеті не змонтував клон»
Симптоми: Клон існує, але не монтується; статус ключа недоступний; помилки інструментів навколо ключів.
Корінь: Ключі не завантажені, неправильний keylocation або операційний потік припускає, що ключі є на хості відновлення.
Виправлення: Переконайтеся, що ключі завантажені й доступні на хості, де ви клонуюєте/монтуєте. Перевірте через zfs get keystatus. Якщо ви реплікуєте зашифровані датасети — майте план управління ключами для інцидентів.
8) «Ми використали відкат для відновлення файлу і все погіршили»
Симптоми: Один відсутній файл перетворився на повний сервісний відкат, втративши легітимні записи з часу знімка.
Корінь: Використання відкату датасету коли потрібно було відновлення на рівні файлу.
Виправлення: Монтуйте/переглядайте знімок або клон і копіюйте назад конкретні шляхи. Відкат — крайній засіб для широких реверсій, а не типовий спосіб відновлення видалених файлів.
Жарт №2: Якщо ваш план відкату — «ми просто відкотимо», вітаю — ви винайшли стратегію бекапу з впевненістю печива фортун.
Чеклісти / покроковий план
Чекліст A: План «потрібно відновити кілька файлів» (без відкату)
- Визначте датасет для шляху (
zfs list -o name,mountpoint). - Перелікуйте знімки навколо часу інциденту.
- Створіть інцидентний знімок поточного стану і поставте на нього hold.
- Клонуйте цільовий знімок у recovery-датасет.
- Скопіюйте файли з клона в живий датасет (зберігаючи власника/ACL).
- Перевірте поведінку додатка. Тримайте клон, поки не впевнені.
Чекліст B: План «Безпечний відкат цього датасету»
- Зупиніть записувачів. Зупинка systemd-сервісу, режим обслуговування додатка або щонайменше блокування записів.
- Підтвердіть здоров’я пулу. Якщо degraded — не додавайте хаосу.
- Підтвердіть межі датасету. Не відкатуйте пул, якщо не готові взяти на себе проблеми всіх команд.
- Знімкуйте поточний стан. Назвіть зрозуміло і поставте hold.
- Перевірте клони. Якщо існують залежні клони — вирішіть, чи відкат можливий.
- Перевірте наслідки «новіших знімків». Визначте, чи можна їх зберегти або доведеться знищити.
- Розгляньте репетицію через клон. Якщо не впевнені — клон і протестуйте запуск додатка на ньому.
- Відкат. Використайте найменш руйнівну форму, що працює. Уникайте
-R, якщо не потрібно. - Запустіть сервіси і валідуйте. Перевірте не лише «сервіс працює», а й коректність і цілісність даних.
- Приберіть акуратно. Зніміть holds коли безпечно, видаліть тимчасові клони і задокументуйте використаний знімок.
Чекліст C: Координований відкат кількох датасетів
Саме тут команди отримують опіки. Багатодатасетний стан (додаток + БД + черга) потребує координованих знімків і координованого відкату, інакше ви отримаєте «внутрішньо консистентно, але взаємно неконсистентно».
- Зупиніть весь стек або переведіть його в quiesced режим.
- Створіть знімок на кожному датасеті з тим самим токеном імені (наприклад:
@pre_change_TICKET). - Утримуйте ці знімки під тегом «incident» або «change».
- При відкаті відкотіть набір у визначеному порядку (зазвичай черга/споживачі першими, потім БД, потім додаток) і перевіряйте кожний шар.
FAQ
1) Чи видаляє ZFS rollback дані назавжди?
Відкат відкидає зміни живого датасету після знімка. Якщо ви також видаляєте новіші знімки (через -r/-R), то так — та історія втрачена, якщо вона не реплікована десь ще.
2) У чому різниця між відкатом і клонуванням знімка?
Відкат перемотує існуючий датасет на місці. Клон створює новий записуваний датасет на основі знімка. Клони безпечніші, коли ви не впевнені, потрібне відновлення файлів або хочете протестувати без дотиків до продакшну.
3) Можу я відкотити лише одну директорію?
Ні. Відкат застосовується до датасету. Якщо хочете «лише одну директорію» — використайте перегляд знімка (наприклад .zfs/snapshot де доступно) або клон і скопіюйте директорію назад.
4) Чому відкат блокується через «існують новіші знімки»?
ZFS запобігає випадковому знищенню хроніки знімків. Ви можете примусити його, але ZFS хоче, щоб ви явно визнали, що видаляєте майбутнє.
5) Чи відкат відновить властивості датасету, як compression або recordsize?
Ні. Властивості не належать до стану знімка, як вміст файлів. Якщо зміна властивості спричинила проблему — виправте властивість напряму і зафіксуйте політику змін у конфіг-мегменті.
6) Як відкат взаємодіє з реплікацією?
Реплікація залежить від неперервності знімків. Якщо ви видаляєте знімки, які вже відправлено (або які очікувалися як інкрементальна база), ви можете зламати інкременти і потребуватимете повного повторного насіння. Використовуйте holds для анкоров реплікації і плануйте відкат так, щоб не видаляти їх casual.
7) Чи безпечний відкат для баз даних?
Іноді. Це залежить від того, чи може база даних відновитись із crash-consistent образу і чи ви координували з репліками, PITR-інструментами та міграціями схем. Якщо ви не можете чітко описати ці залежності — краще клон і перевірка або штатні шляхи відновлення бази даних.
8) Який найбезпечніший «undo», якщо я не знаю, що змінилося?
Зробіть знімок поточного стану (і поставте hold), потім клон одного з відомо робочих знімків і порівняйте. Якщо diff показує невелику кількість файлів — відновіть їх. Відкат для тоді, коли ви впевнені, що весь датасет треба перемотати.
9) Коли використовувати holds?
Використовуйте holds для будь-якого знімка, який не повинен зникнути: pre-change знімки, знімки як доказ інциденту, анкори реплікації та знімки для відповідності. Знімайте holds свідомо, коли вікно ризику минуло.
10) Чи потребує відкат відмонтування датасету?
Не завжди, але зупинка записувачів — справжня вимога. На практиці зупиніть сервіс і переконайтесь, що нічого не пише. Якщо датасет зайнятий — відмонтуйте або знайдіть процес, що утримує його.
Висновок: наступні кроки, які ви реально можете зробити
Відкат — гострий інструмент. Він може врятувати ніч, квартал або вашу репутацію. Але безпечний шлях не в «швидшому наборі rollback». Безпечний шлях — зменшувати невизначеність і звужувати радіус ураження.
Зробіть наступне:
- Розділіть датасети за власністю і доменом відкату. Якщо два сервіси ділять датасет — ваш ризик відкату вже враховано.
- Стандартизуйтесь на pre-change знімках з утриманнями. Зробіть їх автоматичними й нудними, і реплікуйте, якщо можете.
- Тренуйте підхід «спочатку клон, потім відновлення». Зробіть «клон, diff, copy back» типовою м’язовою пам’яттю.
- Запишіть політику руйнівних прапорів. Коли
-rдозволено? Коли заборонено? Хто підписується? - Проведіть game day: зламаєте конфіг, відновіть зі знімків, потім повторіть при «мало вільного місця». Ось справжній тест.
Якщо ваша відповідь на інциденти покладається на героїзм — у вас немає плану реагування. У вас є регулярний запис у календарі з хаосом. Відкат ZFS, виконаний безпечно, — це спосіб скасувати той запис.