Пекло снапшотів не приходить під сирену. Воно проявляється питанням «чому пул знову заповнений на 94%?» і «чому видалення старих снапшотів нічого не звільняє?».
Потім вікно резервного копіювання розтягується, реплікація відстає, а рутинне відновлення перетворюється на форензичні розкопки.
Снапшоти ZFS — одна з найкращих ідей у сфері зберігання даних. Водночас вони — найпростіший шлях непомітно створити машину часу, яку ви не зможете утримувати.
Виправлення — не «робіть менше снапшотів» і не «купіть більше дисків». Потрібна політика збереження, яка ставиться до снапшотів як до продуктивних даних: з бюджетом, спостережуваністю та
регулярною збіркою сміття з підтвердженнями.
Що насправді таке «пекло снапшотів»
Пекло снапшотів — це не «занадто багато снапшотів». Це снапшоти без управління.
Ви можете мати десятки тисяч снапшотів і бути в порядку, якщо розумієте, як утримується простір, як працює реплікація і холди,
і видаляєте свідомо, а не на відчуття.
Ось як це виглядає в продакшені:
- Паніка через ємність: використання пулу зростає, хоча «ми видалили старі дані».
- Невпевненість при відновленні: ніхто не знає, який снапшот безпечний, консистентний чи релевантний.
- Затримки реплікації: інкрементальні відправлення ростуть, бо снапшоти не вирівняні або ви зберегли не ті.
- Операційний страх: «нічого не видаляйте, може знадобитися». Вітаю, ви тепер музей.
Ключова проблема в тому, що снапшоти зберігають старі блоки. Якщо ви інтенсивно змінюєте дані (VM, бази даних, кеші CI),
снапшоти тримають старі версії. Ваші «видалені» дані не видалені; вони в меморіалі.
Жарт №1: Снапшоти як чеки — корисні, доки ви не зберігаєте їх сім років і не виявите, що купили 300 однакових USB-кабелів.
Цікаві факти та історія, що стануть у пригоді
- ZFS створювали навколо copy-on-write (CoW), отже він ніколи не перезаписує живі блоки; снапшоти — природний наслідок, а не доповнення.
- Створити снапшот майже безкоштовно (працює метаданих), тому їх легко зловживати; витрати проявляються пізніше як утримані блоки.
- Снапшоти ZFS консистентні на рівні файлової системи; для консистентності додатків (бази даних) потрібна координація (freeze, flush або інструменти реплікації).
- Облік простору для снапшотів — не «розмір снапшота»; це «унікальні блоки, які посилаються лише цим снапшотом». Це плутає майже всіх хоча б раз.
- Клони — це записувані снапшоти — і вони створюють ланцюги залежностей, коли ви не можете видалити «стару річ», бо клон її використовує.
- Холди існують тому, що люди видаляють не те; ZFS зробив видалення снапшотів оборотним у дусі (запобіжним), але не фактично (все ще руйнівним).
- Інкрементальний send/receive спирається на родовід снапшотів; видалення «проміжних» снапшотів може зламати інкрементали, якщо ви не спланували це.
- Інструменти авто-снапшотингу стали популярними, бо ручне знімання провалюється непомітно: це працює доти, доки ви не забудете протягом тижня — прямо перед тим, як воно знадобиться.
Ментальна модель: снапшоти, блоки і чому видалення розчаровує
Снапшоти в ZFS — це покажчики на консистентний вигляд датасету в певний момент часу. Вони не «містять файли».
Вони містять посилання на блоки, які існували під час створення снапшота.
Коли дані змінюються після снапшота, ZFS записує нові блоки (CoW). Старі блоки залишаються, бо снапшот все ще на них посилається.
Тому вартість снапшота пропорційна скільки змінилося після його створення, а не номінальному розміру датасету.
Три поведінки, які доводять операторів до сказу
- Вільне місце повертається пізно: видалення файлу не звільнить блоки, якщо якийсь снапшот ще на них посилається.
- «Used» контекстуально: «used» снапшота — це унікальна власність блоків; воно може зростати, коли датасет інтенсивно змінюється.
- Залежності невидимі, поки не перевірите: клони й холди завадять видаленню і заплутають скрипти очищення.
Що повинна вирішувати політика збереження
Політика збереження — не просто розклад. Це угода між ризиком і витратами:
«Ми завжди зможемо відновити в межах вікна X і з гранулярністю Y, і ми ніколи не перевищимо Z% використання пулу через снапшоти».
Потрібно:
- Чіткі класи снапшотів (годинні/щоденні/тижневі/місячні).
- Схему іменування, що кодує наміри.
- Алгоритм обрізки, який зберігає репрезентативні точки часу.
- Запобіжні заходи: холди для спеціальних снапшотів і сповіщення, коли ретеншн порушує бюджет ємності.
- Покрокові інструкції для дня «пул заповнюється» — бо це станеться.
Одна перефразована ідея, яка сформувала культуру опсів:
Ви маєте будувати системи з очікуванням людських помилок і обмежувати площу ураження.
— James Hamilton (reliability engineering)
Політика збереження, яка реально працює
Політика нижче нудна. Саме тому вона виживає в контакті з продакшеном.
Вона побудована навколо трьох істин: більшість відновлень — нещодавні, комплаєнс хоче довготривалості, а ємність обмежена.
1) Визначте ціль відновлення, а потім купіть її снапшотами
Визначте своє RPO (скільки даних можна втратити) і RTO (як швидко треба відновити). Потім зіставте це з частотою снапшотів.
Якщо бізнес каже «ми можемо втратити 1 годину даних», не робіть тільки щоденні снапшоти і не надійтеся.
Практичний дефолт, що підходить багатьом командам:
- Щогодини: зберігати 48 (2 дні)
- Щодня: зберігати 35 (5 тижнів)
- Щотижня: зберігати 12 (3 місяці)
- Щомісяця: зберігати 18 (18 місяців)
Звучить багато. Насправді ні, якщо ви обрізаєте за графіком і розділяєте найінтенсивніше змінювані датасети (VM, кеші збірки, WAL бази даних).
2) Розділяйте датасети за рівнем churn і за цінністю
Ретеншн для снапшотів має бути на рівні класу датасету, а не «одне правило для пулу».
Помістіть високочурні дані в окремий датасет, щоб вони не отруювали економіку ретеншну для всього іншого.
- Бази даних: консистентні снапшоти в координації з БД; короткий локальний ретеншн, довший на репліці/резерві.
- Диски VM: короткі часті снапшоти; агресивна обрізка; розгляньте реплікацію для довших горизонтів.
- Домашні директорії: довший ретеншн, менший churn, хороший кандидат для довготривалого збереження.
- Scratch / CI: мінімальний ретеншн або відсутній; снапшоти тут — це як повільно підпалювати гроші.
3) Бюджетуйте снапшоти як відсоток ємності пулу
Виберіть жорстке обмеження, наприклад: «Снапшоти не повинні дозволяти пулу перевищувати 80% використання в нормальній роботі».
Ваш бюджет — це обмеження політики, а не пропозиція.
Коли межа порушена, обрізка стає більш агресивною автоматично (які шари скидати першими — місячні чи годинні?).
Моя думка: видаляйте високочастотні шари першими (годинні), бо вони коштують дорожче у churn-датасетах і приносять найменше для довготривалого відновлення.
4) Вимагавайте холдів для спеціальних снапшотів, але ніколи для рутинних
Холди призначені для виключних моментів: перед оновленням, юридичні холди, «ми зараз робимо руйнівну міграцію».
Рутинний ретеншн має бути повністю автоматизованим і повністю видаленим.
Якщо ви дозволите холдам проникати в набір стандартних снапшотів, ваша політика стане ввічливою вигадкою.
5) Узгодьте ретеншн з реплікацією
Якщо ви робите ZFS send/receive реплікацію, вирішіть, яка сторона відповідальна за довготривалий ретеншн.
Поширена виграшна схема:
- Джерело: короткий ретеншн, часті снапшоти для швидкого локального відновлення і малих інкременталів.
- Призначення: довший ретеншн, менше збережених снапшотів, плюс періодичні «якірні» (щотижня/щомісяця) для комплаєнсу.
Це уникне класичної помилки «ми зберегли все всюди». Диски дешевші за час — поки раптом ні.
Іменування та метадані: майбутній ви заслуговує кращого
Імена снапшотів — це частина вашої контрольної площини. Це не декор.
Якщо ви не закодуєте намір, у вас будуть імена типу auto-2025-thing і людина вгадуватиме, які з них важливі.
Схема іменування, що масштабується
Використовуйте: <dataset>@<class>-<utc timestamp> плюс опціональні суфікси для координації з додатком.
Приклади:
tank/vmstore@hourly-2026-02-04T00:00Ztank/home@daily-2026-02-04T00:00Ztank/db@hourly-2026-02-04T00:00Z-pgfreeze
Використовуйте властивості для тегування наміру
Користувацькі властивості ZFS можуть нести метадані політики. Наприклад:
com.example:retention=hourlycom.example:owner=paymentscom.example:tier=gold
Імена допомагають людям. Властивості допомагають інструментам.
Практичні завдання (команди, вивід, рішення)
Це не «іграшкові» команди. Це ті, які ви запускаєте, коли хтось питає, чому пул заповнений, а ваш календар ось-ось буде скасований фізикою.
Кожне завдання включає: команду, що означає її вивід, і рішення, яке з нього випливає.
Завдання 1: Перевірити тиск на ємність пулу та фрагментацію
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,health,frag
NAME SIZE ALLOC FREE CAP HEALTH FRAG
tank 10.9T 9.2T 1.7T 84% ONLINE 38%
Значення: CAP на 84% вже в зоні небезпеки для продуктивності й поведінки алокації; FRAG показує, наскільки розбитий вільний простір.
Фрагментація сама по собі не «погана», але високе CAP + зростаючий FRAG — місце, де латентність починає дратувати.
Рішення: Якщо CAP > 80%, припиніть створювати нові снапшоти з довгим ретеншном, пріоритизуйте обрізку та перевірте, хто тримає простір (снапшоти, клони чи самі дані).
Завдання 2: Визначити, які датасети фактично споживають місце
cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -S used
NAME USED AVAIL REFER MOUNTPOINT
tank/vmstore 4.3T 820G 1.1T /tank/vmstore
tank/home 2.7T 820G 2.2T /tank/home
tank/db 1.6T 820G 540G /tank/db
Значення: USED включає снапшоти і дочірні елементи; REFER — це те, на що посилається живий файловий простір.
Великі різниці між USED і REFER — це ваш податок снапшотів (або діти).
Рішення: Зосередьтеся на датасетах, де USED ≫ REFER. Вони — головні підозрювані у блоці снапшотів.
Завдання 3: Квантфікувати накладні витрати снапшотів по датасету
cr0x@server:~$ zfs get -H -o name,property,value used,usedbysnapshots,usedbydataset tank/vmstore
tank/vmstore used 4.30T
tank/vmstore usedbysnapshots 3.10T
tank/vmstore usedbydataset 1.10T
Значення: 3.10T утримується снапшотами. Це не «кількість снапшотів», це утримані блоки.
Рішення: Цей датасет потребує негайного перегляду ретеншну. Або зменшіть частоту/тривалість снапшотів, або розділіть інтенсивні підшляхи в окремі датасети.
Завдання 4: Перелік снапшотів за впливом на простір, відсортований
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -S used tank/vmstore | head
NAME USED REFER CREATION
tank/vmstore@hourly-2026-02-02T10:00Z 120G 1.05T Sun Feb 2 10:00 2026
tank/vmstore@hourly-2026-02-02T11:00Z 118G 1.06T Sun Feb 2 11:00 2026
tank/vmstore@daily-2026-01-28T00:00Z 90G 1.02T Tue Jan 28 00:00 2026
Значення: Колонка USED для снапшотів — це «унікальні дані, утримувані цим снапшотом». Великі значення — ваша точка для очищення.
Рішення: Почніть обрізку з великих годинних снапшотів — якщо вони не є частиною реплікаційного ланцюга, який вам потрібен.
Завдання 5: Перевірити, чи блокуються снапшоти холдами
cr0x@server:~$ zfs holds tank/vmstore@hourly-2026-02-02T10:00Z
NAME TAG TIMESTAMP
tank/vmstore@hourly-2026-02-02T10:00Z pre-upgrade Mon Feb 3 09:12 2026
Значення: Цей снапшот не можна знищити, поки холд не буде знято.
Рішення: Підтвердіть, що подія «pre-upgrade» завершена і затверджена. Потім зніміть холд; інакше залиште його і обріжте інші снапшоти.
Завдання 6: Безпечно зняти холд і видалити снапшот
cr0x@server:~$ zfs release pre-upgrade tank/vmstore@hourly-2026-02-02T10:00Z
cr0x@server:~$ zfs destroy tank/vmstore@hourly-2026-02-02T10:00Z
cr0x@server:~$ zfs list -t snapshot -o name,used -S used tank/vmstore | head -3
NAME USED
tank/vmstore@hourly-2026-02-02T11:00Z 118G
tank/vmstore@daily-2026-01-28T00:00Z 90G
Значення: Снапшот зник; порядок змінився. Простір може не показатися негайно як «вільний», якщо інші снапшоти все ще посилаються на ті блоки.
Рішення: Якщо вільне місце не зростає, продовжуйте видаляти далі по ланцюжку (або знайдіть клони/інші снапшоти, що тримають ті ж блоки).
Завдання 7: Виявити клони, що блокують видалення снапшота
cr0x@server:~$ zfs get -H -o name,property,value origin -r tank/vmstore
tank/vmstore origin -
tank/vmstore/clone-win11 origin tank/vmstore@daily-2026-01-28T00:00Z
Значення: tank/vmstore/clone-win11 залежить від того щоденного снапшота. Видалення снапшота зазнає невдачі, доки клон не буде видалено або не буде виконано промоцію.
Рішення: Або знищити клон (якщо він не потрібний), або zfs promote клон, щоб розірвати залежність перед обрізкою.
Завдання 8: Промотувати клон, щоб розблокувати ретеншн
cr0x@server:~$ zfs promote tank/vmstore/clone-win11
cr0x@server:~$ zfs get -H -o name,property,value origin tank/vmstore/clone-win11
tank/vmstore/clone-win11 origin -
Значення: Клон тепер незалежний; його origin очищено.
Рішення: Тепер можна видаляти старі снапшоти, які раніше були origin — після перевірки нової родовідної лінії клона і плану реплікації.
Завдання 9: Перевірити кількість снапшотів і їх розподіл за класами
cr0x@server:~$ zfs list -t snapshot -o name -r tank/home | awk -F@ '{print $2}' | cut -d- -f1 | sort | uniq -c
48 hourly
35 daily
12 weekly
18 monthly
Значення: Це відповідає політиці. Якщо кількості ростуть, це збій автоматизації або заблоковане видалення (холди/клони).
Рішення: Якщо кількості перевищують політику, спочатку перевірте холди й клони; потім — чи виконується ваша робота з обрізки і чи має вона права.
Завдання 10: Перевірити, що заважає інкрементальній реплікації
cr0x@server:~$ zfs list -t snapshot -o name,creation tank/db | tail -5
tank/db@hourly-2026-02-03T20:00Z Mon Feb 3 20:00 2026
tank/db@hourly-2026-02-03T21:00Z Mon Feb 3 21:00 2026
tank/db@hourly-2026-02-03T22:00Z Mon Feb 3 22:00 2026
tank/db@hourly-2026-02-03T23:00Z Mon Feb 3 23:00 2026
tank/db@hourly-2026-02-04T00:00Z Tue Feb 4 00:00 2026
Значення: Інкрементальні реплікації вимагають спільного снапшота на обох сторонах. Якщо на прийомі відсутні старі годинні снапшоти через обрізку, джерело не зможе виконати інкрементал від того пункту.
Рішення: Визначте, які снапшоти є «реплікаційними анкерами» (часто дейлі або вікі) і забезпечте їх збереження на обох сторонах достатньо довго.
Завдання 11: Оцінити розмір send перед виконанням
cr0x@server:~$ zfs send -nvP -I tank/db@hourly-2026-02-03T20:00Z tank/db@hourly-2026-02-04T00:00Z
send from @hourly-2026-02-03T20:00Z to tank/db@hourly-2026-02-04T00:00Z estimated size is 36.2G
total estimated size is 36.2G
Значення: Це те, що ваша реплікація відправить. Якщо це несподівано велике, у вас високий churn датасету або інтервал занадто довгий.
Рішення: Якщо оцінений розмір надто великий для вікна, збільште частоту снапшотів (менші дельти), зменшіть churn (відділіть WAL/temp), або змініть час реплікації.
Завдання 12: Підтвердити compression і recordsize, що впливають на churn снапшотів
cr0x@server:~$ zfs get -o name,property,value compression,recordsize,atime tank/vmstore
NAME PROPERTY VALUE
tank/vmstore compression zstd
tank/vmstore recordsize 128K
tank/vmstore atime off
Значення: Recordsize впливає на те, скільки даних змінюється при дрібному записі; atime=on може створювати непотрібний метадантичний churn (і тим самим ріст снапшотів).
Рішення: Для VM-образів і баз даних розгляньте recordsize і архітектуру датасету навмисно. Вимикайте atime, якщо немає реальної потреби.
Завдання 13: Знайти «місце, що не звільниться» через видалення під снапшотами
cr0x@server:~$ zfs list -o name,used,refer,usedbysnapshots -r tank/vmstore
NAME USED REFER USEDBYSNAPSHOTS
tank/vmstore 4.3T 1.1T 3.1T
tank/vmstore/images 3.9T 820G 3.0T
tank/vmstore/iso 120G 115G 2G
Значення: Churn сконцентрований під images. Саме там відбувалися видалення/перезаписи, поки існували снапшоти.
Рішення: Налаштуйте ретеншн конкретно для tank/vmstore/images або розділіть ще більше (по VM) щоб обмежити площу ураження.
Завдання 14: Dry-run руйнівного прибирання — перелік того, що буде видалено
cr0x@server:~$ zfs list -t snapshot -o name,creation -S creation tank/home | awk 'NR==1 || /@hourly-/' | head -5
NAME CREATION
tank/home@hourly-2026-02-04T00:00Z Tue Feb 4 00:00 2026
tank/home@hourly-2026-02-03T23:00Z Mon Feb 3 23:00 2026
tank/home@hourly-2026-02-03T22:00Z Mon Feb 3 22:00 2026
tank/home@hourly-2026-02-03T21:00Z Mon Feb 3 21:00 2026
Значення: Ви підтвердили шаблон іменування та час створення. Скрипти прибирання повинні працювати за цими шаблонами, а не «що виглядає старим».
Рішення: Якщо снапшоти не відповідають шаблонам, зупиніться і виправте іменування. Збирання сміття без послідовних імен — просто креативне видалення.
Завдання 15: Спостерігати I/O тиск, коли снапшотів багато
cr0x@server:~$ zpool iostat -v tank 2 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 9.2T 1.7T 420 1150 62.1M 210M
raidz2-0 9.2T 1.7T 420 1150 62.1M 210M
sda - - 52 140 7.8M 26.5M
sdb - - 50 138 7.5M 25.9M
sdc - - 54 145 8.0M 27.1M
Значення: Високі операції запису плюс високе використання пулу часто збігаються зі снапшот-важкими навантаженнями (більше метадантичного churn, більше фрагментації).
Рішення: Якщо ваше навантаження чутливе до латентності і CAP високе, обрізайте снапшоти і зменшуйте churn. Якщо у вас немає запасу, плануйте розширення — не торгуйте з ентропією.
Швидка діагностика: плейбук
Коли хтось каже «снапшоти нас вбивають», можливо, так і є — або вони звинувачують єдину видиму функцію.
Цей плейбук швидко знаходить вузьке місце у порядку, який зазвичай окупається.
Спочатку: чи ви справді обмежені ємністю?
-
Перевірте використання пулу та стан:
cr0x@server:~$ zpool list -o name,cap,health,frag NAME CAP HEALTH FRAG tank 84% ONLINE 38%Рішення: Якщо CAP > 80%, розглядайте це як інцидент. Ваші опції швидко скорочуються за цією межею.
-
Знайдіть внесок снапшотів:
cr0x@server:~$ zfs get -H -o name,value usedbysnapshots -r tank | sort -h -k2 | tail -5 tank/vmstore 3.10T tank/home 420G tank/db 310GРішення: Атакуйте головного контриб’ютора першим. Героїка в інших місцях — показуха.
По-друге: чи блокування видалення через залежності (холди/клони/реплікація)?
-
Перевірте холди на снапшотах, які мають бути видалені:
cr0x@server:~$ zfs holds -r tank/vmstore | head NAME TAG TIMESTAMP tank/vmstore@daily-2026-01-28T00:00Z legal Thu Jan 30 14:10 2026Рішення: Холди означають процес. Підтвердіть власника, потім зніміть або прийміть витрати ємності.
-
Перевірте клони та origin:
cr0x@server:~$ zfs get -H -o name,value origin -r tank/vmstore | grep -v '^-' tank/vmstore/clone-win11 tank/vmstore@daily-2026-01-28T00:00ZРішення: Якщо існують клони, промотуйте або знищуйте їх перед обрізкою origin-снапшотів.
По-третє: чи скарга стосується продуктивності, а не ємності?
-
Перевірте I/O і симптоми латентності:
cr0x@server:~$ zpool iostat -v tank 1 5 capacity operations bandwidth pool alloc free read write read write -------------------------- ----- ----- ----- ----- ----- ----- tank 9.2T 1.7T 380 1320 58.0M 225MРішення: Якщо записи високі і CAP високий, обрізка допомагає. Якщо CAP у нормі, дивіться на recordsize, sync-параметри та форму навантаження.
-
Перевірте властивості датасету, що створюють churn (atime, recordsize):
cr0x@server:~$ zfs get -o name,property,value atime,recordsize -r tank/vmstore NAME PROPERTY VALUE tank/vmstore atime off tank/vmstore recordsize 128K tank/vmstore/images atime off tank/vmstore/images recordsize 128KРішення: Настройте на рівні датасету. Не «оптимізуйте» весь пул через одне галасливе навантаження.
Три корпоративні міні-історії з передової
Міні-історія 1: Інцидент через неправильне припущення
Середня SaaS-компанія використовувала ZFS для зберігання VM та домашніх директорій. У них був нічний джоб, який «видаляв старі бекапи» в гостевій ОС.
Команда зберігання очікувала, що після кожного прибирання пул стане менш заповненим. Так не сталося.
Коли пул перейшов у високі 80-ті, латентність підскочила. Почалися тікети: «VM повільні», «бекап довше», «деплої застрягли».
on-call інженер зробив очевидне: видалив ще файлів. Пул став… ще заповненішим. Саме тоді паніка отримує почуття гумору.
Неправильне припущення було простим: «Видалення файлів звільняє простір». У ZFS із снапшотами це правда лише тоді, коли жоден снапшот не посилається на видалені блоки.
Їхній VM-датасет мав годинні снапшоти на 30 днів. Кожне нічне прибирання видаляло великі лог-файли й обертало образи VM. Снапшоти тримали всі старі блоки.
Виправлення не було містичним. Вони виміряли usedbysnapshots, виявили, що це більшість датасету, і скоротили годинний ретеншн з 30 днів до 2 днів.
Вони зберегли довші дейлі та вікі для точкових відновлень. Також розділили інтенсивні образи VM на пер-VM датасети, щоб один галасливий орендар не блокував простір для всіх.
Найкраще: відновлення покращилися. Замість перегортання місяця годинних снапшотів, у них з’явилося чітке недавнє вікно для швидкого відкату й довше вікно для аудиту.
Менше снапшотів. Кращі результати. Всесвіт іноді винагороджує базовий облік.
Міні-історія 2: Оптимізація, що обернулася проти
Фінансова організація захотіла «більше безпеки» і вирішила знімати снапшот кожні п’ять хвилин. Вони запустили це на завантаженому датасеті бази даних без координації з додатком.
Джоб снування був швидким. Реплікація — ні. Пул заповнився швидше, ніж їхній цикл закупівель, який є найповільнішим відомим рівнем зберігання.
Вони оптимізували далі: «Залишимо п’ятихвилинні снапшоти лише на 24 години і дейлі на рік».
На папері розумно. На практиці їхній скрипт обрізки видаляв «проміжні» снапшоти, необхідні для інкрементального ланцюга відправлень на DR-сайт,
змушуючи виконувати часті повні відправлення. Пропускна здатність зросла, відставання реплікації виросло, і DR почав втрачати ті точки відновлення, які всі вважали наявними.
Твіст полягав у тому, що вони оптимізували не ту метрику. Частота снапшотів не була проблемою; проблема була в вирівнюванні.
Джерело створювало снапшоти в :00, :05, :10. Прийом обрізав за своїм локальним часом та навантаженням, видаляючи анкери непередбачувано.
Виправлення: вони визначили явні реплікаційні анкери (годинні і дейлі) і зберігали їх на обох сторонах. П’ятихвилинні снапшоти залишилися локальними і короткоживучими.
DR знову став інкрементальним, передбачуваним і нудним — саме те, що потрібно від DR.
Жарт №2: Ніщо так не свідчить про «високу доступність», як усвідомлення, що ваш DR-план залежить від настрою cron-job.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Медична компанія мала суворий контроль змін. Перед великим оновленням вони робили ручний снапшот і застосовували холд з ID тікета в тегу.
Це було процедурно, трохи дратувало і над ними знущалися — поки не знадобилося.
Під час оновлення прошивки сховища неправильно налаштований multipath викликав періодичні I/O помилки на підмножині хостів.
Команда додатку відкотила код. Помилки залишилися. Проблема виявилася не в софті, а в шляхах доступу до зберігання.
Потрібно було відновити набір конфігураційних директорій і невелику базу даних, які були «очищені» під час троблшутингу.
Оскільки перед-оновленням снапшот був утриманий холдом, він пережив регулярний цикл обрізки. Відновлення було точковим: клонувати снапшот, витягти потрібні файли,
і продовжити роботу, поки multipath не виправили.
Це не вимагало геніальності. Це вимагало нудної дисципліни: снапшот + холд + документований власник. Холд запобіг «корисному прибиранню», яке могло знищити рятівний шлях.
Після закриття інциденту вони зняли холд, і система повернулась до нормальної політики без накопичення постійних наростів.
Типові помилки: симптом → корінь проблеми → виправлення
1) «Ми видалили старі дані, але простір не повернувся»
Симптом: REFER датасету зменшується, CAP пулу — ні.
Корінь проблеми: Снапшоти все ще посилаються на видалені блоки.
Виправлення: Виміряйте usedbysnapshots, потім обріжте снапшоти відповідно до політики. Якщо вам потрібні снапшоти, розділіть датасети, щоб ізолювати churn.
2) «Знищення снапшотів не вдається з помилкою ‘dataset is busy’ або подібною»
Симптом: zfs destroy відмовляє або скрипт пропускає снапшоти.
Корінь проблеми: Існують холди або клони; снапшот — origin.
Виправлення: Використовуйте zfs holds та zfs get origin. Знімайте холди, якщо авторизовано; знищуйте або промотуйте клони.
3) «Реплікація раптово стала величезною або повільною»
Симптом: Інкрементальні відправлення роздуваються; відставання реплікації зростає.
Корінь проблеми: Відсутні спільні снапшоти через невідповідність ретеншну або обрізку на одній стороні.
Виправлення: Встановіть реплікаційні анкери, що зберігаються на обох сторонах. Перевірте з zfs list -t snapshot на джерелі і прийомі.
4) «У нас тисячі снапшотів і ніхто не знає, що вони означають»
Симптом: Імена непослідовні, невідомий власник.
Корінь проблеми: Немає конвенції імен, метаданих; кілька інструментів створюють снапшоти.
Виправлення: Стандартизуйте імена за класом + UTC timestamp. Додайте користувацькі властивості для власника і класу ретеншну. Забороніть несанкціонованих творців снапшотів.
5) «Продуктивність погіршилася в міру додавання снапшотів»
Симптом: Латентність росте; пул відчувається «важким» під навантаженням.
Корінь проблеми: Високе використання пулу + фрагментація + churn від частих снапшотів підсилюють метадантичні та алокаційні витрати CoW.
Виправлення: Тримайте CAP під контролем (ціль < 80%). Зменшіть частоту для churn-датасетів. Розгляньте перерозподіл датасетів і розширення ємності.
6) «Обрізка запускається, але кількість снапшотів тільки зростає»
Симптом: Автоматизація повідомляє успіх, але старі снапшоти залишаються.
Корінь проблеми: Фільтри скрипта не збігаються з іменами; холди; права; або обрізка працює не в тому просторі датасетів.
Виправлення: Перевірте, перелікуючи снапшоти, які планується видалити, перед видаленням. Додайте моніторинг по кількості снапшотів на клас і по кількості холдів.
7) «Відновлення ненадійні або неконсистентні для баз даних»
Симптом: Відновлення стартує, але БД потребує довгого відновлення або логічно пошкоджена.
Корінь проблеми: Файлова системна консистентність ≠ консистентність додатку.
Виправлення: Використовуйте нативні механізми БД (freeze/flush, консистентні контрольні точки) під час створення снапшотів, або реплікуйте за допомогою інструментів БД і снапшотуйте репліки.
Чеклісти / покроковий план
Покроково: впровадити політику збереження, не створивши новий інцидент
-
Інвентаризуйте датасети і класифікуйте за churn/цінністю.
Групуйте: бази даних, образи VM, дані користувачів, логи, scratch. Якщо все в одному датасеті — ви вже знайшли проблему #1. -
Визначте RPO/RTO для класу.
Не дозволяйте «ми хочемо все назавжди» без платіжного наказу. - Оберіть рівні ретеншну (hourly/daily/weekly/monthly) і кількості для кожного класу.
- Прийміть схему іменування з UTC timestamp і префіксом класу.
- Впровадьте автоматизацію створення снапшотів з правильним охопленням і послідовним іменуванням.
-
Впровадьте автоматизацію обрізки, яка:
- зберігає найновіші N на клас
- ніколи не видаляє утримувані снапшоти
- усвідомлює клони (або принаймні звітує про них)
- логуватиме, що видалено і що не вдалося
- Встановіть обмеження ємності: сповіщення на 75% і 80% використання пулу; розглядайте 85% як критичне в залежності від навантаження.
-
Тестуйте відновлення щоквартально, не під час інцидентів.
Відновлення — це функція продукту. Якщо ви його не тестуєте — у вас його немає. - Узгодьте реплікацію з анкорами і відповідальністю за ретеншн (джерело vs прийом).
- Документуйте процедуру «спеціального снапшота»: зробити снапшот, додати холд з ID тікета, призначити термін/власника і вимагати видалення після завершення.
Операційний чекліст: день «пул заповнюється»
- Підтвердіть CAP і знайдіть топ-датасети за
usedbysnapshots. - Перелічіть найбільші снапшоти за USED і перевірте на холди/клони.
- Обріжте спочатку високочастотні снапшоти в churn-датасетах (hourlies), зберігши реплікаційні анкери.
- Якщо простір не звільняється, шукайте клони і довгоживучі холди.
- Якщо ви близькі до 90% CAP, плануйте екстрене розширення (переміщення даних, розширення пулу) під час обрізки — не ставте надії на одне лише.
Дизайн-чекліст: запобігти пеклу снапшотів структурно
- Відділяйте шляхи з високим churn в окремі датасети.
- Вимикайте atime там, де це не потрібно.
- Визначте, яка система — «довгострокове зберігання» (зазвичай реплікаційний прийом).
- Використовуйте холди лише з власником і датою закінчення.
- Моніторте кількість снапшотів і простір, утримуваний снапшотами, а не тільки CAP пулу.
- Тримайте іменування послідовним на всіх хостах для спрощення інструментів.
FAQ
Чи уповільнюють снапшоти ZFS?
Безпосередньо — ні. Вони уповільнюють опосередковано, збільшуючи утримані блоки, що підвищує використання пулу, ускладнює алокацію і може посилити фрагментацію.
Також більше метаданих і складніша шарінг-блоків можуть зробити деякі операції важчими.
Чому показник USED снапшота змінюється з часом?
Тому що USED — «унікальні блоки, які були б звільнені, якби цей снапшот було знищено». В міру зміни живого датасету снапшот стає останнім посиланням на старі блоки,
тож його унікальна власність може зростати.
Скільки снапшотів — це занадто багато?
Неправильне питання. Правильне: скільки простору утримують снапшоти і чи можете ви відновити те, що потрібно у вашому RPO/RTO?
Ви можете мати тисячі снапшотів при низькому churn і бути в порядку; або 200 снапшотів на високочурному датасеті VM можуть вибити вас з розуму.
Де краще тримати довгий ретеншн: на джерелі чи на прийомі реплікації?
Краще — на прийомі реплікації. Тримайте джерело компактним для продуктивності і малих інкременталів.
Зберігайте явні анкери на обох сторонах, щоб зберегти можливість інкрементальної реплікації.
Який найбезпечніший спосіб видаляти снапшоти?
Найбезпечніший означає: ви знаєте, навіщо існує снапшот, знаєте, що від нього залежить (холди/клони/реплікація), і видаляєте згідно з політикою.
Почніть з переліку снапшотів за USED, перевірте холди, перевірте origin/залежності клонів, потім видаляйте від найстарішого до найновішого всередині класу, який обрізаєте.
Чи можна робити снапшот бази даних без координації?
Файлова консистентність не рівна консистентності додатку. Деякі бази даних відновлюються чисто; інші — вимагають тривалого відновлення або дають логічні помилки.
Координуйте снапшоти з БД (flush/freeze), або робіть снапшоти репліки, призначеної для бекапів.
Чому обрізка не звільнила стільки простору, скільки очікували?
Бо видалені снапшоти не були унікальними власниками блоків, або інші снапшоти ще посилаються на ті ж блоки.
Також перевірте на наявність клонів: клон може утримувати блоки навіть після обрізки снапшотів.
Чи є холди хорошим механізмом довгострокового ретеншну?
Ні. Холди — запобіжник для виняткових снапшотів, а не рушій політики. Якщо ви використовуєте холди як механізм ретеншну, накопичите постійні снапшоти з невідомим власником,
і ваша система обрізки стане брехливою.
З якої політики ретеншну почати, якщо ви в паніці?
Почніть з: hourly 48, daily 35, weekly 12, monthly 18 — потім підлаштуйте за churn датасету. Помістіть образи VM і бази даних в окремі датасети і скорочуйте їх локальний ретеншн.
Зробіть реплікацію прийомом довготривалого зберігання.
Як заборонити інструментам створювати випадкові снапшоти?
Стандартизуйте автоматизацію створення снапшотів в одному місці, обмежте адміністративний доступ і моніторте швидкість створення снапшотів та відповідність імен.
Якщо з’являються снапшоти з невідомими префіксами, розглядайте це як дрейф конфігурації, а не як цікавинку.
Висновок: практичні наступні кроки
Пекло снапшотів — це провал політики в обгортці сховища. ZFS дав вам механізм; вам ще потрібне управління.
Якщо ви хочете перестати боятися zfs destroy, зробіть роботу один раз і тримайте її нудною.
- Виміряйте: збирайте
usedbysnapshotsпо датасетах і сповіщайте про тренди зростання. - Класифікуйте: розділіть датасети за churn і цінністю, щоб одне навантаження не розорило пул.
- Стандартизуйте: прийміть схему іменування і додайте користувацькі властивості для власності та класу ретеншну.
- Автоматизуйте: створюйте і обрізайте снапшоти по графіку, з обізнаністю про клони/холди і реальним логуванням.
- Узгодьте реплікацію: тримайте анкери на обох сторонах; переносьте довготривалий ретеншн на прийом.
- Практикуйте відновлення: тестуйте шлях, який важливий, перш ніж він знадобиться о 3 ранку.
Зробіть це — і снапшоти стануть тим, чим вони й мали бути: швидкою, надійною кнопкою відкату, а не археологічною ділянкою.