Видалення ZFS-снапшота: швидке звільнення місця (і як уникнути головної помилки «Я щойно знищив дані»)

Було корисно?

Це завжди відбувається в найгірший момент: пул доходить до 95% заповнення, запис уповільнюється майже до повного припинення, і хтось каже: «У нас є снапшоти. Просто видаліть кілька.» Так команди дізнаються, що облік місця в ZFS і чесний, і іноді контрінтуїтивний.

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

Що насправді відбувається при видаленні снапшота (і чого не відбувається)

Снапшот ZFS — це посилання на блоки в певний момент часу. Це не «копія» у традиційному сенсі. Коли ви робите снапшот, ZFS просто гарантує: «Ті блоки, як вони були в цей момент, залишаться доступними.» Коли дані змінюються пізніше, ZFS використовує copy-on-write, тож нові записи потрапляють у нові блоки, а старі блоки зберігаються, бо снапшот на них посилається.

Отже, коли ви руйнуєте снапшот, ZFS не «видаляє файли». Він прибирає набір посилань. Після цього ZFS може звільнити будь-які блоки, які більше ніким не посилаються — ні живою файловою системою, ні іншими снапшотами, ні клонами, ні через холди або спеціальні фічі.

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

Головна помилка «Я щойно знищив дані»

Руйнування датасету, коли мали на увазі руйнування снапшота. Або відкат, коли мали на увазі видалити. Команди короткі, наслідки тривалі, а продакшн байдуже, що це була чесна помилка.

Ось ментальна модель, яка запобігає аваріям:

  • zfs destroy pool/ds@snap видаляє снапшот. Це може звільнити місце (залежно від посилань).
  • zfs destroy pool/ds знищує датасет і все під ним (якщо не заборонено). Це означає «ми закінчили з цими даними».
  • zfs rollback pool/ds@snap повертає живий датасет до стану зі снапшота. Це означає «замінити поточні дані на старі».

Короткий жарт №1: ZFS схожа на шафу для документів, яка ніколи не забуває — доки ви не скажете їй, щоб забула, після чого вона стає надзвичайно доброю в забуванні.

Цікаві факти та історичний контекст (бо це змінює підхід)

  1. ZFS з’явився в Sun у середині 2000‑х з радикальною ідеєю, що файлову систему і менеджер томів варто поєднати, щоб снапшоти були першокласними і дешевими.
  2. Copy-on-write не був новим, але ZFS зробив його практичним для масштабних загальних файлових систем, через що снапшоти стали операційно нормою.
  3. Снапшоти ZFS дешеві у створенні (зазвичай метадані), що призвело до того, що команди створювали їх багато — і пізніше вчилися, що вартість зберігання наростає.
  4. Видимість «.zfs/snapshot» раніше вводила в оману: каталог .zfs/snapshot може показувати снапшоти для перегляду, що зручно, поки хтось не напише скрипт проти нього і не забуде, що це не звичайний каталог.
  5. Клони з’явилися рано і змінили історію видалення: якщо ви клонували снапшот, ви створили залежний файловий простір, який може зберігати блоки снапшота.
  6. Облік простору багаторівневий: USED, REFER, USEDDS, USEDSNAP існують тому, що «скільки місця займає цей об’єкт?» має кілька правильних відповідей в залежності від задачі.
  7. Холди в ZFS додали для безпеки, бо інструменти реплікації й бекапу потребували способу сказати «не видаляйте цей снапшот ще».
  8. Масивні видалення снапшотів раніше викликали спайки латентності на деяких навантаженнях через важку роботу з метаданими; сучасні реалізації покращили це, але видалення все ще може бути нетривіальним.

Одна ідея з надійності, варта нотатки: paraphrased ideaRichard Cook: «Успіх і невдача походять з однієї системи; люди адаптуються, щоб усе працювало.» У прибиранні снапшотів ZFS ваш «швидкий фікс» стає майбутнім інцидентом.

Швидкий план діагностики: знайти вузьке місце за кілька хвилин

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

Перше: чи справді пул повний, і чи фрагментація погіршує ситуацію?

  • Перевірте zpool list на предмет ємності й стану.
  • Перевірте zpool get fragmentation і zpool status на червоні прапори.
  • Якщо ви на 90%+ заповнення, очікуйте проблем з продуктивністю й повільнішого звільнення. ZFS любить вільний простір.

Друге: це «реально використане» місце чи «зарезервоване/утримане»?

  • Дослідіть використання на рівні датасету за допомогою zfs list -o space.
  • Шукайте refreservation, квоти та резервації, які роблять «доступне» меншим, ніж ви очікували.
  • Перевірте використання снапшотів і холди. Якщо після видалення місце не повертається, часто це означає, що інші снапшоти, клони або холди все ще посилаються на блоки.

Третє: які снапшоти великі з точки зору унікально посилань?

  • Сортуйте снапшоти за used (унікальне для того снапшота) і орієнтуйтесь на найбільших споживачів.
  • Підтвердьте, що на них немає залежних клонів (origin і шаблони zfs get clones).
  • Де можливо — робіть dry-run руйнівних команд; якщо не можна, змоделюйте вплив за допомогою вихідних метрик обліку.

Якщо все ще не вдається швидко звільнити місце

  • Шукайте датасет з величезним refreservation або runaway recordsize/compression mismatch, що призводить до несподіваного високого реального використання.
  • Розгляньте звільнення місця поза снапшотами (логи, дампи аварій, старі репліки).
  • Якщо пул дійсно повністю заповнений, може знадобитися екстрена тактика: видалити найважливіший некритичний датасет, додати vdev-ємність або підключити тимчасове сховище і мігрувати дані.

Облік простору, який вам справді потрібен: USED, REFER, AVAIL, USEDDS, USEDREFRESERV

ZFS показує кілька чисел, бо оператори ставлять різні запитання:

  • REFER: дані, доступні з поточної HEAD датасету (не враховуючи снапшоти). «Який розмір живої файлової системи?»
  • USED: загальний простір, спожитий датасетом і нащадками, включно зі снапшотами (іноді з урахуванням резервацій в певному вигляді). «Скільки простору пулу можна приписати цьому піддереву?»
  • AVAIL: скільки цей датасет ще може виділити, з урахуванням квот/резервацій. Це число, на яке першим наткнеться ваша програма.
  • USEDSNAP: скільки місця займають снапшоти під цим датасетом (не обов’язково унікально для кожного снапшота).
  • USEDDS: простір, який займає сам датасет (не снапшоти, не діти).
  • USEDREFRESERV: простір, зафіксований refreservation. Це «місце, яке ви пообіцяли зберегти», і воно перетворюється на «місце, яке ви не можете використати», коли ситуація критична.

Якщо запам’ятати одне: видалення снапшота звільняє лише ті блоки, на які більше ніким не посилаються. Тож вам треба знайти, хто ще на них посилається.

Практичні завдання (команди + що означає вивід + рішення)

Це ті завдання, які я справді виконую, коли хтось питає: «Пул ZFS майже повний, ви можете видалити снапшоти?» Кожне завдання містить команду, що означає її вивід і яке рішення з нього випливає.

Завдання 1: Підтвердьте ємність пулу і базовий стан

cr0x@server:~$ zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  7.25T  6.85T   410G        -         -    42%    94%  1.00x  ONLINE  -

Значення: CAP 94% — це небезпечна зона. FRAG 42% вказує, що алокації й вивільнення можуть бути дорожчими.

Рішення: Ставте це як інцидент, а не як рутинну роботу. Плануйте швидко звільнити місце, а потім створити підголовок (збільшити ємність або змінити політику зберігання).

Завдання 2: Перевірте, чи існує чекпоінт (рідко, але важливо)

cr0x@server:~$ zpool get checkpoint tank
NAME  PROPERTY    VALUE      SOURCE
tank  checkpoint  -          -

Значення: Чекпоінта немає. Якби чекпоінт був, поведінка простору може дивувати, бо відкат чекпоінта може змінити алокації.

Рішення: Продовжуйте; чекпоінт не враховується.

Завдання 3: Знайдіть, які датасети відповідають за використання

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -r tank | head
NAME                USED  AVAIL  REFER  MOUNTPOINT
tank               6.70T   320G   192K  /tank
tank/home           410G   320G   260G  /tank/home
tank/postgres       3.90T   320G  1.10T  /tank/postgres
tank/vm             2.20T   320G  1.80T  /tank/vm
tank/backups        190G   320G   175G  /tank/backups

Значення: USED показує атрибуцію включно зі снапшотами/дітьми; REFER показує живий розмір. tank/postgres використовує 3.90T, але живий об’єм лише 1.10T — ймовірно, снапшоти великі.

Рішення: Зосередьтеся на датасетах, де USED значно перевищує REFER.

Завдання 4: Розбити використання датасету на компоненти

cr0x@server:~$ zfs list -o name,used,usedds,usedsnap,usedrefreserv,usedchild -r tank/postgres
NAME                USED  USEDDS  USEDSNAP  USEDREFRESERV  USEDCHILD
tank/postgres       3.90T  1.10T    2.80T              0B        0B

Значення: USEDSNAP 2.80T — ось де справа. Утримання снапшотів займає більшу частину місця.

Рішення: Знайдіть, які снапшоти відповідають за унікальне використання і чи їх можна видалити (холди/клони/реплікація).

Завдання 5: Перелічити снапшоти й їх унікальне використання

cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s used -r tank/postgres | tail
tank/postgres@autosnap_2025-12-01_00:00:00   12.4G   1.05T  Mon Dec  1 00:00 2025
tank/postgres@autosnap_2025-12-08_00:00:00   28.1G   1.06T  Mon Dec  8 00:00 2025
tank/postgres@autosnap_2025-12-15_00:00:00   44.7G   1.08T  Mon Dec 15 00:00 2025
tank/postgres@autosnap_2025-12-22_00:00:00   71.2G   1.09T  Mon Dec 22 00:00 2025
tank/postgres@autosnap_2025-12-29_00:00:00  110.3G   1.10T  Mon Dec 29 00:00 2025

Значення: used для снапшота — це простір, унікальний для нього (сума, яку зазвичай звільняєте при видаленні, якщо немає інших посилань). Новіші снапшоти часто мають більший used, якщо є велика зміна даних.

Рішення: Орієнтуйтеся на найбільші за used снапшоти, але перевірте залежності.

Завдання 6: Перевірте холди на снапшоті (чому він не видаляється?)

cr0x@server:~$ zfs holds tank/postgres@autosnap_2025-12-29_00:00:00
NAME                                      TAG             TIMESTAMP
tank/postgres@autosnap_2025-12-29_00:00:00  zrepl_last_ok   Mon Dec 30 02:10 2025

Значення: Цей снапшот утримується тегом, імовірно встановленим інструментом реплікації/бекапу. Ви не зможете його зруйнувати, поки холд не знято (або поки не зміните поведінку з ризиком).

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

Завдання 7: Зняти холд (тільки коли ви знаєте його призначення)

cr0x@server:~$ sudo zfs release zrepl_last_ok tank/postgres@autosnap_2025-12-29_00:00:00

Значення: Холд знято. Тепер снапшот можна видалити стандартними засобами.

Рішення: Продовжуйте до руйнування, але підтвердіть відсутність клонів.

Завдання 8: Перевірте, чи має снапшот залежні клони

cr0x@server:~$ zfs get -H -o value clones tank/postgres@autosnap_2025-12-29_00:00:00
tank/devdb

Значення: Є клон tank/devdb, залежний від цього снапшота. Ви не можете зруйнувати оригінальний снапшот, поки не знищите або не змініте стан клона.

Рішення: Вирішіть, чи можна списати клон, чи його треба промотувати, чи зробити бекап і відтворити пізніше.

Завдання 9: Перегляньте origin клонa і вирішіть шлях промоції

cr0x@server:~$ zfs get -H -o value origin tank/devdb
tank/postgres@autosnap_2025-12-29_00:00:00

Значення: tank/devdb — клон із цього снапшота. Видалення снапшота порушить лінію залежностей, що ZFS забороняє.

Рішення: Якщо потрібно видалити снапшот, або знищуйте клон, або промотуйте його (що змінює залежності).

Завдання 10: Промотувати клон, щоб дозволити видалення снапшота (обережно)

cr0x@server:~$ sudo zfs promote tank/devdb

Значення: Клон стає «основним», і оригінальний датасет стає залежним (або принаймні граф залежностей змінюється). Це може неочікувано вплинути на інструменти, що розраховували на певну origin‑зв’язність.

Рішення: Промотуйте лише якщо розумієте, хто залежить від яких датасетів для реплікації/бекапу. Після промоції перевірте origin і clones на задіяних снапшотах.

Завдання 11: Безпечно знищити одиночний снапшот (попередньо перевіривши)

cr0x@server:~$ zfs list -t snapshot tank/postgres@autosnap_2025-12-22_00:00:00
NAME                                      USED  AVAIL  REFER  MOUNTPOINT
tank/postgres@autosnap_2025-12-22_00:00:00  71.2G      -  1.09T  -

Значення: Ви дивитеся на об’єкт, який плануєте видалити. Це крок людського контролю, що запобігає помилкам при наборі.

Рішення: Якщо це правильний снапшот — зруйнуйте його.

cr0x@server:~$ sudo zfs destroy tank/postgres@autosnap_2025-12-22_00:00:00

Значення: Снапшот видалено. Місце може не відобразитися миттєво, якщо інші снапшоти все ще посилаються на ті самі блоки або якщо системі потрібен час для обробки вивільнення.

Рішення: Повторно перевірте метрики простору; якщо змін немає, досліджуйте залежності замість того, щоб бездумно продовжувати видаляти.

Завдання 12: Видалити діапазон снапшотів (цільове прибирання)

cr0x@server:~$ zfs list -t snapshot -o name,creation -r tank/postgres | grep autosnap_2025-12 | head
tank/postgres@autosnap_2025-12-01_00:00:00  Mon Dec  1 00:00 2025
tank/postgres@autosnap_2025-12-08_00:00:00  Mon Dec  8 00:00 2025
tank/postgres@autosnap_2025-12-15_00:00:00  Mon Dec 15 00:00 2025

Значення: Ви підтвердили схему іменування та які снапшоти відповідають вашому місяцю/префіксу.

Рішення: Використовуйте -d для відкладеного видалення, якщо потрібно, і уникайте шаблонів, що можуть збігатися ширше, ніж ви думаєте.

cr0x@server:~$ sudo zfs destroy -d tank/postgres@autosnap_2025-12-01_00:00:00%autosnap_2025-12-15_00:00:00

Значення: Руйнує снапшоти в інклюзивному діапазоні. Відкладене руйнування позначає їх для подальшого очищення, що може зменшити негайний вплив, але затримує звільнення місця в деяких випадках.

Рішення: Використовуйте видалення діапазону, коли у вас послідовне найменування і ви підтвердили межі. Якщо потрібно місце терміново, уникайте відкладення, хіба що жертвуєте миттєвим звільненням заради зниження латентності.

Завдання 13: Слідкуйте, чи дійсно збільшився вільний простір

cr0x@server:~$ zpool list tank
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  7.25T  6.72T   530G        -         -    41%    92%  1.00x  ONLINE  -

Значення: Вільне місце зросло з ~410G до ~530G. Це реальне відновлення.

Рішення: Продовжуйте, поки не отримаєте операційний запас (зазвичай 15–20% вільного для комфортної роботи зайнятих пулів), потім припиніть видалення і виправте політику збереження, щоб не повертатися до цього наступного тижня.

Завдання 14: Виявити несподіванки з refreservation/квотами

cr0x@server:~$ zfs get -o name,property,value -s local -r tank | egrep 'refreservation|reservation|quota'
tank/vm  refreservation  500G
tank/backups  quota  250G

Значення: tank/vm фіксує 500G через refreservation. Навіть якщо ви видалите снапшоти в інших місцях, ви можете не повернути AVAIL там, де потрібно, бо місце зарезервоване.

Рішення: У екстреному режимі розгляньте тимчасове зменшення refreservation (після узгодження зі стейкхолдерами). Квоти також можуть викликати помилки «немає місця», навіть коли пул має вільні блоки.

Завдання 15: Перевірте, чи дочірній датасет є основним «колектором» снапшотів

cr0x@server:~$ zfs list -o name,used,usedsnap,refer -r tank/vm
NAME          USED  USEDSNAP  REFER
tank/vm       2.20T   320G    1.80T
tank/vm/win1   900G   250G     640G
tank/vm/linux1  640G    40G     600G

Значення: Використання снапшотів концентрується в tank/vm/win1. Саме там ви отримаєте відчутний ефект.

Рішення: Не видаляйте хаотично на батьківському рівні. Йдіть туди, де є велика частина змін.

Завдання 16: Переконайтеся, що ви не збираєтеся випадково знищити датасет

cr0x@server:~$ zfs list tank/postgres
NAME           USED  AVAIL  REFER  MOUNTPOINT
tank/postgres  3.55T   420G  1.10T  /tank/postgres

Значення: Це датасет. Немає суфікса @snap. Якщо ви зруйнуєте це, ви не «чистите снапшоти».

Рішення: Якщо у вашій команді немає @, зупиніться і наберіть заново.

Безпечне видалення снапшотів: шаблони, що не підведуть

Шаблон 1: Видаляйте «по найбільшому унікальному used», а не за віком

Видалення за віком задовольняє емоційно і зручне операційно. Це може працювати, але це не швидкий шлях, коли ви на 94% ємності. Коли потрібно місце терміново, видаляйте снапшоти, які зараз унікально дорогі.

У датасетах з високою зміною блоків (бази даних, образи ВМ, кеші збірок) нові снапшоти часто тримають найбільш унікальні дані. Видалення «найстарішого» може майже нічого не звільнити, бо старі снапшоти ділять більшість блоків з іншими снапшотами і живим датасетом.

Шаблон 2: Ставте холди й клони в один рівень важливості

Якщо снапшот не видаляється, система не вперта. Вона права. Холди означають, що якийсь процес оголосив: «Цей снапшот потрібен.» Клони означають: «На цьому снапшоті створено файлову систему.» Обидва — причини зупинитись, а не просто додавати -f і сподіватися.

Шаблон 3: Використовуйте відкладене видалення, коли латентність важливіша за негайне звільнення

Видалення снапшотів може бути важким. Якщо у вас навантаження чутливе до латентності і ви ще не повністю вичерпали простір, відкладене видалення може стати компромісом. Але якщо місця немає, відкладення — це як відкласти гасіння пожежі до обіду.

Шаблон 4: Віддавайте перевагу політиці збереження перед хаотичними чистками

Ручні чистки снапшотів — це запах проблем. Справжнє рішення — політика збереження, що відповідає бізнес-вимогам і потребам реплікації, плюс оповіщення на розумних порогах (не «99%»).

Короткий жарт №2: Утримання снапшотів без моніторингу — це як зберігати чеки назавжди, бо можливо колись доведеться повернути весь будинок.

Чому місце не повертається після видалення снапшотів

Це та частина, яка змушує людей не довіряти ZFS. Вони видаляють снапшоти, дивляться df -h і бачать… майже нічого. Система не брешe; ви просто дивитеся не на той рівень або пропустили залежність.

1) Інший снапшот все ще посилається на блоки

Якщо видалити снапшот A, але снапшот B (або живий датасет) все ще посилається на ті ж блоки, нічого не звільниться. Стовпчик used для снапшотів — ваш друг, бо він наближає, що унікально приписано.

2) Клон залежить від снапшота

Клони — тиха причина «чому я не можу видалити це?» у корпоративних середовищах, бо хтось підняв дев-копію з снапшота «на тиждень», а вона стала напівпродуктовою службою з каналом у Slack і почуттями.

3) Холд перешкоджає видаленню

Інструменти бекапу/реплікації часто ставлять холди, щоб запобігти руйнуванню ланцюжків реплікації. Якщо знімати холди без розуміння, можете сьогодні повернути місце й втратити точку відновлення завтра.

4) Ви звільнили блоки, але датасет, який вам потрібен, має квоту/rezervation

Вільний простір пулу й доступний простір датасету — різні речі. Якщо ваша програма пише в датасет з квотою, вона може отримати помилку навіть коли пул має вільні блоки. Навпаки, refreservation може робити пул «повним», хоча файлова система не така велика.

5) Ви дивитесь на неправильну метрику (df проти ZFS)

df -h показує погляд файлової системи на точки монтування. Для ZFS авторитетні zfs list і zpool list. Використовуйте df для перевірки сумісності додатків, а не для прийняття рішень під час інциденту.

Поширені помилки: симптом → причина → виправлення

Помилка 1: «Я видалив снапшоти і нічого не звільнилося»

Симптоми: zpool list все ще показує високий ALLOC; USEDSNAP датасету зменшився трохи або взагалі не змінився; тиск залишається.

Причина: Ви видаляли снапшоти з низьким унікальним used, або блоки все ще посилаються інші снапшоти/клони.

Виправлення: Сортуйте снапшоти за used і цільте найбільші. Перевірте zfs get clones і zfs holds на блокатори.

Помилка 2: «Destroy снапшота каже, що датасет зайнятий / не можна знищити»

Симптоми: Destroy не вдається або скаржиться на залежності.

Причина: Існує клон, або є холди, або ви намагаєтесь знищити снапшот, що є origin для іншого об’єкта.

Виправлення: Знайдіть залежних з zfs get clones на снапшоті. Вирішіть: знищити клон, промотувати клон або зберегти снапшот.

Помилка 3: «Ми звільнили місце в пулі, але додаток все ще отримує ‘no space left’»

Симптоми: zpool list показує вільне місце, але записи додатку не вдаються; zfs list показує низьке AVAIL для датасету.

Причина: Квота, резервація або refreservation обмежують AVAIL.

Виправлення: Перевірте zfs get quota,reservation,refreservation. Згодом корегуйте з процедурою змін; не видаляйте квоти тимчасово без плану.

Помилка 4: «Хтось відкотився до снапшота, щоб «звільнити місце»»

Симптоми: Дані здаються поверненими; останні зміни зникли; інциденти позначені як «корупція», хоча це просто подорож у часі.

Причина: Плутанина між rollback і destroy; віра, що rollback видаляє дані снапшота.

Виправлення: Використовуйте rollback лише як відновлювальний крок з явною згодою і попереднім створенням снапшота перед відкатом. Для звільнення місця видаляйте снапшоти; не робіть rollback.

Помилка 5: «Ми видалили датасет замість снапшота»

Симптоми: Вся файлова система зникає; точки монтування пропадають; сервіси відмовляють; раптом усі знають ваше ім’я.

Причина: Невірно введена команда zfs destroy pool/ds замість zfs destroy pool/ds@snap; відсутні запобіжники; немає рев’ю для руйнівних команд.

Виправлення: Вимагайте списку датасетів безпосередньо перед destroy. Використовуйте принцип найменших привілеїв. Віддавайте перевагу інтерактивним обгорткам для операцій, що виконує людина.

Помилка 6: «Видалення снапшота спричинило спайк латентності»

Симптоми: Зростає латентність I/O під час видалення; хвостова латентність додатка погіршується; моніторинг показує завантаження дисків.

Причина: Видалення великої кількості снапшотів змушує метадані активно оновлюватися й звільняти блоки; пул уже повний/фрагментований; обладнання насичене.

Виправлення: Видаляйте меншими партіями в непіковий час, розгляньте відкладене руйнування і тримайте пул нижче болісних порогів заповнення. Довгостроково: скоригуйте частоту й збереження снапшотів.

Помилка 7: «Реплікація зламалася після прибирання»

Симптоми: Incremental send не вдається; інструмент реплікації скаржиться на відсутній базовий снапшот.

Причина: Видалено снапшоти, що служили як опори реплікації; холди були обхідні або відсутні.

Виправлення: Узгодьте політику збереження між джерелом і ціллю. Використовуйте холди для «не видаляти» до підтвердження реплікації. Погодьте зміни з власником реплікації перед очищенням.

Три корпоративні міні-історії (реалістично, болісно, корисно)

Міні-історія 1: Інцидент через неправильне припущення

У них був змішаний пул: образи ВМ, PostgreSQL і купа CI-артефактів, за які ніхто не хотів відповідати. Після запуску продукту пул почав заповнюватися швидше, і on-call зробив те, що робить on-call: видалив старі снапшоти. Багато їх.

Місце не рухнулося. Зовсім. Припущення було таке: «старі снапшоти великі», бо більшість людей думає про бекапи так: старе = важке. Але розмір снапшота в ZFS — це не вік; це унікальні блоки. Найстаріші снапшоти мали мізерне унікальне used, бо основні зміни були нещодавні.

Вони продовжували видаляти. І нічого. Паніка зростала. Хтось запропонував «можливо ZFS завис», що зазвичай означає «ми не ідентифікували залежність». Реальна проблема: найновіший снапшот мав холд, встановлений задачею реплікації. Він був анкором для інкременталів і також містив найбільший унікальний приріст після міграції схеми.

Коли вони перевірили холди й націлилися на снапшоти за унікальним used, їм вдалося звільнити достатньо місця, щоб стабілізувати систему. Урок не в тому, що холди дратують. Урок у тому, що якщо ви не розумієте граф снапшотів, ви не керуєте сховищем — ви просто тягнете важелі й сподіваєтесь.

Міні-історія 2: Оптимізація, що обернулась проти

Інша компанія хотіла «агресивні точки відновлення» для сервісу клієнта. Вони налаштували autosnap кожні 5 хвилин і зберігали їх два тижні. На папері все виглядало добре, бо датасет «тільки трохи виростав щодня».

Насправді це було навантаження з ВМ і високим блоковим чаржом. Кожен 5‑хвилинний снапшот захоплював унікальні дельти, які окремо були малими, але в сумі вбивчими. Пул не впав відразу. Він впав у найгірший можливий момент: під час інциденту, коли сервіс вже деградував і логи ринулися.

Вони намагалися видалити снапшоти швидко, щоб виграти місце. Видалення десятків тисяч снапшотів одним махом створило додаткове навантаження, перетворивши деградований сервіс на недоступний. Не тому, що ZFS «не витримав», а тому, що вони попросили систему виконати важку метаоперацію з метаданими під час пікового навантаження на майже повний пул.

Виправлення було нудне: зменшити частоту снапшотів для цього датасету, впровадити багаторівневе збереження (часті короткострокові, рідкісні довгострокові) і підтримувати запас вільного місця. «Більше снапшотів» — не є надійністю; це просто більше роботи, збереженої у вигляді метаданих і блоків.

Міні-історія 3: Сумна, але правильна практика, яка врятувала ситуацію

Фінансова команда вела ZFS для набору внутрішніх сервісів. Нічого героїчного. Їхні системи — ті, про які забуваєш, поки вони не впадуть. У них був письмовий ранубук для прибирання снапшотів, який зобов’язував три речі: перелічити цільовий об’єкт, зробити dry-run для набору збігів і підтвердити залежності (холди/клони) перед видаленням.

Одного вікенду розробник просив терміновий клон продакшн‑даних для дебагу. Його створили зі снапшота й залишили працювати. Через тижні тиск на сховище почав збільшуватись. On‑call побачив кілька снапшотів з нетипово великим унікальним простором.

Ранубук змусив перевірити залежності. Вони знайшли клон, прив’язаний до саме тих снапшотів, які хотіли видалити. Замість того, щоб ламати систему, вони погодилися: дев‑клон був замінений оновленою копією на іншому пулі, старий клон знищили. Потім снапшоти могли бути видалені безпечно, і місце повернулося миттєво.

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

Чеклісти / покроковий план

Чекліст A: Екстрене прибирання снапшотів при «пул майже повний»

  1. Підтвердьте стан пулу та ємність. Якщо CAP 95%+, ставте як інцидент.
  2. Визначте топові датасети за USED vs REFER. Велика різниця вказує на нагромадження снапшотів.
  3. Розбийте USEDSNAP для найгіршого датасету. Не вгадуйте.
  4. Перелічіть снапшоти, відсортовані за унікальним used. Цільте на високоповертаючі кандидати.
  5. Для кожного кандидата: перевірте холди й клони.
  6. Видаляйте партіями. Повторно перевіряйте вільне місце пулу після кожної партії.
  7. Зупиніться, щойно отримаєте запас. Потім виправте політику й планування ємності, щоб не повторювати це під стресом.

Чекліст B: Безпечні щоденні операції (план «ніколи не дзвоніть мені через це знову»)

  1. Визначте політику збереження за класом датасету (БД, ВМ, домашні директорії, бекапи).
  2. Узгодьте політику збереження з вимогами реплікації; не видаляйте останній спільний снапшот.
  3. Налаштуйте оповіщення на розумних рівнях (наприклад, 75/85/90%), а не 98%.
  4. Переглядайте refreservation і квоти щоквартально; документуйте причини їх існування.
  5. Документуйте життєвий цикл клонів: хто може їх створювати, де вони живуть і коли спливають.
  6. Періодично практикуйте відновлення зі снапшотів. Ви виявите операційну тертя під час тренування, а не в реальному інциденті.

Чекліст C: Перед будь‑якою руйнівною ZFS-командою вручну

  1. Запустіть zfs list для точного імені цілі, яку збираєтесь знищити.
  2. Підтвердьте наявність @ для снапшотів.
  3. Перевірте zfs holds і zfs get clones для снапшотів.
  4. Підтвердьте точки монтування і імена датасетів; остерігайтеся схожих імен (tank/prod vs tank/prod-db).
  5. Вставте команду у текстовий редактор перед виконанням, якщо ви втомлені. Люди ненадійні о 03:00.

FAQ

1) Чи видаляє видалення ZFS‑снапшота мої файли?

Ні. Видаляється посилання на снапшот. Живі файли залишаються. Але якщо ви покладалися на цей снапшот для відновлення видалених файлів, ця точка відновлення зникла.

2) Чому zfs list -t snapshot показує снапшот з великим REFER?

REFER на снапшоті відображає розмір датасету на момент створення снапшота. Це не «унікальне» значення. Стовпчик USED більш релевантний для питання «скільки місця я, ймовірно, отримаю, видаливши це?»

3) Я знищив снапшоти, але df -h не змінився. Це поламано?

Ймовірно, ні. Використовуйте zpool list і zfs list, щоб підтвердити алокації пулу і датасету. df може не відповідати очікуванням, бо не враховує всі нюанси обліку ZFS.

4) У чому різниця між видаленням снапшота та відкатом?

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

5) Що таке холди ZFS і хто їх ставить?

Холди — це теги, які запобігають видаленню снапшотів. Інструменти реплікації/бекапу часто ставлять їх, щоб гарантувати, що потрібні снапшоти зберігаються до підтвердження реплікації.

6) Чому я не можу видалити снапшот навіть після зняття холда?

Бо на ньому може залежати клон або існує інша залежність. Перевірте zfs get clones snapshot. Якщо є клони, вам потрібно їх знищити або промотувати перед видаленням оригіну.

7) Чи безпечно видаляти снапшоти в навантаженому продакшні?

Зазвичай так — але це може бути дорогим. Великі або численні видалення можуть підвищити латентність, особливо на повних або фрагментованих пулах. Розбивайте видалення на партії і виконуйте їх у непік.

8) Скільки вільного місця слід тримати в ZFS‑пулі?

Правила залежать від навантаження, але добре триматися значно нижче 90% як за замовчуванням. Високе заповнення збільшує тиск фрагментації й може підсилити латентність під час важких записів і звільнень.

9) Чи покращиться продуктивність після видалення снапшотів?

Іноді. Якщо пул дуже повний, відновлення простору може знизити тиск алокатора і покращити поведінку записів. Але сам процес видалення може тимчасово додати навантаження.

10) Чи варто використовувати deferred destroy (-d)?

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

Висновок: що робити далі на робочій системі

Якщо ви дивитесь на майже повний пул, не робіть «почистити старі снапшоти» просто за відчуттями. Робіть це як контрольовану операцію:

  1. Квантифікуйте проблему: zpool list, потім zfs list -o space для топових порушників.
  2. Цільте правильні снапшоти: сортуйте за унікальним used, а не за віком.
  3. Безпечно знімайте блокатори: перевіряйте холди і клони перед кожним destroy.
  4. Перевіряйте після кожної партії: зупиніться, щойно відновите запас.
  5. Виправте корінь проблеми: політика збереження, вирівнювання реплікації, квоти/резервації та планування ємності.

Справжній виграш — це не звільнити 200GB о 03:00. Справжній виграш — ніколи не потрапляти в цю ситуацію з натиском «записи відмовляються» і «хто виконав ту команду?»

← Попередня
DNSSEC: Помилка ротації, що одночасно виводить з ладу пошту й веб
Наступна →
Продуктивність Docker: чому контейнери гальмують під навантаженням (і це не CPU)

Залишити коментар