Є два типи інженерів зі зберігання даних: ті, кому колись знадобився аварійний зворотний хід, і ті, кому він ще не знадобився. ZFS zpool checkpoint — це той самий зворотний хід: точка “відмінити” для всього пулу, яка може повернути на-дисковий стан пулу до моменту створення контрольної точки. Це не резервна копія. Це не snapshot. І це не особливо поблажливо. Але в потрібному вікні часу воно може перетворити фатальну помилку в не дуже приємний, але керований інцидент.
Якщо ставитися до чекпойнтів як до «безкоштовної подушки безпеки», ви рано чи пізно відкриєте їхню улюблену фішку: робити простір невидимим саме тоді, коли він найбільше потрібен. Це операційний інструмент, а не ковдра від тривог. Поговорімо про те, як він працює, для чого підходить, чому небезпечний і як використовувати його в продакшені, не ставши анекдотом.
Що таке zpool checkpoint (і що ним не є)
Чекпойнт пулу ZFS — це спеціальний маркер у метаданих пулу, який дозволяє відкотити весь пул до точної на-дискової версії стану на момент створення чекпойнта. Не «відновити деякі файли». Не «повернути один dataset». Увесь пул: datasets, snapshots, блок-покажчики, алокації — усе.
Чекпойнти краще розуміти як «кнопку перемотки назад для всього пулу», що ґрунтується на природі ZFS з copy-on-write (CoW). Після створення чекпойнта ZFS мусить зберегти старий стан, щоб його можна було відтворити. Це означає, що блоки, які раніше були вільними, більше не можна повторно використовувати, якщо їх потрібно зберегти для консистентності чекпойнта. Практичний наслідок жорсткий: чекпойнт може заблокувати простір. На завантаженому пулі такий заблокований простір може швидко рости, і робить це в найгірший спосіб: тихо, поки вже не зовсім тихо.
Що це
- Точка відкотування на рівні пулу для усіх метаданих і даних пулу.
- Один чекпойнт одночасно (на пул), а не необмежений стек.
- Тактичний інструмент для ризикованих операцій: оновлення пулу, послідовні заміни пристроїв, зміни on-disk фіч, великі рефактори.
Чим це не є
- Не резервна копія. Якщо пул загинув, чекпойнт теж загинув.
- Не dataset snapshot. Snapshots створюються на рівні dataset і їх можна пересилати/відновлювати; чекпойнти — ні.
- Не вибірковий механізм. Ви не можете відкотити один dataset і лишити інші «сьогоднішніми».
Перша жартівлива ремарка (як обіцяно, коротка): чекпойнт — як “undo” в текстовому редакторі — тільки він ще відкочує зміни колеги, зміни CI-пайплайна і ваші останні дві години здорового глузду.
Чому існують чекпойнти: коротка історія та факти
Чекпойнти здаються сучасним зручністю, але вони коріняться в давніх принципах ZFS: метадані — святі, а CoW — і суперсила, і відповідальність. Ось кілька фактів і контексту, що пояснюють, чому чекпойнти з’явилися й чому вони такими і є.
- Початкова обіцянка ZFS (середина 2000-х): «цілісність даних наскрізь», і CoW — базовий механізм: нові записи не перезаписують старі блоки; вони виділяють нові блоки і атомарно переключають покажчики.
- Флаги фіч пулу еволюціонували, коли ZFS вийшов за межі оригінального вендора і розповсюдився в різні реалізації. Деякі фічі «активуються» тільки при використанні; інші змінюють поведінку on-disk структур. Відкат після активації фіч може бути складним.
- Раніше zpool upgrade був страшнішим, коли активація фіч була менш прозорою для операторів. Чекпойнти з’явилися як страховка для моментів «я оновив і жалкую».
- Snapshots дешеві, поки не стануть дорогими: коли snapshots розмножуються, оператори вчаться, що «дешево» стосується метаданих, а не вічно заблокованих блоків на датасеті із високою зміною. Чекпойнти несуть ту саму фізику — але в масштабі пулу.
- Рахунок простору в ZFS тонкий. «df каже багато вільного» — не те ж саме, що «ZFS може алокувати». Чекпойнти дають ще одну причину, чому ці числа можуть розходитися.
- Висока фрагментація переживана, але висока фрагментація поруч із майже повним накопичувачем — це те місце, де пул стає нестабільним у людських термінах (повільний, схильний до помилок в операціях). Чекпойнти можуть підштовхнути вас ближче до цього краю.
- Обмеження в один чекпойнт навмисне: пул уже має зберігати попередній стан; складання кількох пул-широких історичних станів лише збільшило б заблокований простір і складність.
- Операційні інструменти виросли навколо реальності, що продакшн-зміни — брудні: заміни пристроїв, ashift-невідповідності, флаги фіч, випадкові руйнівні команди. Чекпойнти існують, бо існують люди.
Як чекпойнти працюють “під капотом”
Ви можете оперувати чекпойнтами без читання вихідників ZFS, але вам потрібна ментальна модель. Ось модель, що відповідатиме реальним симптомам.
Чекпойнт — це «збережений корінь пулу»
У ZFS є концепція стану пулу, кореневого в метаданих (уявіть «uberblock» як одну з точок входу в те, “що таке пул зараз”). Чекпойнт фактично зберігає попередній корінь, щоб ZFS міг пройти старе дерево блок-покажчиків і відтворити попередній вигляд.
Чому простір зникає: блоки стають невикористовуваними
Через CoW чекпойнт не потребує копіювання всього пулу. Потрібно лише, щоб старі блоки залишалися досяжними. Але якщо ви змінюєте дані після чекпойнта, ZFS пише нові блоки. Старі блоки залишаються посиланими чекпойнтом і тому не можна їх звільнити. Якщо ви видалите дані після чекпойнта, відчуття може бути таким: «Я видалив 20 ТБ, чому не стало більше вільного?» Тому що з позиції чекпойнта ці дані все ще існують і мають залишатися відновлюваними.
Відкат — не магія, а контрольований вибух
Відкат до чекпойнта викидає усе, що сталося після нього: усі записи, всі видалення, усі зміни dataset і будь-який операційний прогрес, котрий торкався on-disk стану. Це також може взаємодіяти з фічами та операціями над пристроями так, що потрібне планування. Пул повертається до тієї топології, яка була зафіксована в час створення чекпойнта, а не до того, якою ви хочете її бачити.
Гострі краї
- Пули, що майже повні: чекпойнт може швидко підштовхнути вас у стан «немає місця», раніше ніж ви зреагуєте.
- Завантажені пули: інтенсивна зміна даних швидко блокує блоки; «вартість» чекпойнта може роздутися за кілька годин.
- Координація людей: період із чекпойнтом треба трактувати як вікно заморозки змін для певних дій, інакше ви створите міни відкату.
Друга коротка жартівлива ремарка: використовувати чекпойнт без моніторингу — як взяти запасний парашут, але не перевірити ремені: технічно ви безпечні, аж поки фізика не висловить думку.
Коли використовувати чекпойнт (а коли ні)
Добрі випадки використання
1) Перед ризиковою зміною на рівні пулу, яку важко відкотити. Наприклад: ввімкнення фічі, що змінює формат on-disk, оновлення пулу в середовищі, де можуть вимагати відкату, або виконання незвичної послідовності операцій з пристроями.
2) Перед точковою операцією, де «відкотити останні 30 хвилин» має значення. Уявіть вікно технічного обслуговування, де ви виконуватимете команди, які можуть “вивести з ладу” конфіг пулу при помилці.
3) Перед експериментом на непролікованому пулі. Іноді у вас є лабораторний пул, що імітує прод, і ви потребуєте одного безпечного «перемоту назад».
Погані випадки використання
1) Натомість резервних копій або реплікації. Якщо пул знищено, чекпойнт теж знищено.
2) Як довгоживуча страховка. Чекпойнт, який “лежить тиждень на всякий випадок”, — класичний шлях до того, що пул втратить простір, хоча панелі виглядають нормальними.
3) На пулах, де і так замало вільного простору. Якщо ви вже під тиском вільного місця, чекпойнт перетворює «щільно» на «крихко». Можна все ж створити чекпойнт, але ваш план має включати активний моніторинг, жорсткий дедлайн і швидкий шлях скасування (видалення чекпойнта).
Правило великого пальця
Якщо ви не були б комфортні працювати з ефективно меншим об’ємом вільного місця, ніж маєте зараз, не створюйте чекпойнт без попереднього звільнення буфера. Сам чекпойнт не завжди одразу споживає місце; він обмежує вашу можливість відновити простір шляхом звільнення блоків.
Практичні завдання: команди, вивід, інтерпретація
Нижче — реальні операційні завдання для типового Linux + OpenZFS оточення. Деякі виводи змінюються залежно від версії, фіч пулу та платформи, але намір та інтерпретація залишаються. Команди припускають, що пул називається tank.
Завдання 1: Перевірте стан пулу перед будь-якими діями
cr0x@server:~$ sudo zpool status -xv tank
pool 'tank' is healthy
Інтерпретація: Якщо пул не здоровий, не додавайте «складність чекпойнта» до нестабільної ситуації. Виправте помилки, дочекайтесь завершення resilver і усуньте проблеми перш ніж продовжувати.
Завдання 2: Збережіть “до” стан для вашого change ticket
cr0x@server:~$ date -Is
2025-12-25T10:18:44+00:00
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:14:19 with 0 errors on Thu Dec 19 03:10:14 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Збережіть цей вивід разом із записом про зміну. В інциденті різниця між «ми думаємо, що все було добре» і «ось статус о 10:18 UTC» може коштувати годин розслідування.
Завдання 3: Перевірте вільний простір і сигнали ризику фрагментації
cr0x@server:~$ sudo zpool list -o name,size,alloc,free,capacity,fragmentation,health tank
NAME SIZE ALLOC FREE CAP FRAG HEALTH
tank 72T 58.2T 13.8T 80% 41% ONLINE
Інтерпретація: 80% заповнення з 41% фрагментацією — це робочий стан, але не «зайвий». Чекпойнт може зробити так, що видалення перестане допомагати. Якщо ви вже понад ~85–90% заповнення, вважайте чекпойнт небезпечним.
Завдання 4: Перевірте, чи вже існує чекпойнт
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint - -
Інтерпретація: Значення - означає, що чекпойнта немає. Якщо ви бачите таймстамп або непорожнє значення, чекпойнт уже існує і треба вирішити: залишити його, видалити чи відкотитися до нього.
Завдання 5: Створіть чекпойнт (і зафіксуйте час створення)
cr0x@server:~$ sudo zpool checkpoint tank
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint 2025-12-25T10:22:11+00:00 -
Інтерпретація: Цей таймстамп — ваша «точка неповернення» для всього, що станеться після. Запишіть його там, де люди його побачать, а не лише в історії шелу.
Завдання 6: Погодьтеся з поведінкою заблокованого простору через звільнення даних (тест «чому вільного не побільшало?»)
cr0x@server:~$ sudo zfs destroy -r tank/tmp/testdata
cr0x@server:~$ sudo zpool list -o name,alloc,free,capacity tank
NAME ALLOC FREE CAP
tank 58.2T 13.8T 80%
Інтерпретація: Якщо alloc/free ледь змінюються після великого видалення і у вас є чекпойнт, ви дізналися ключову операційну істину: видалення не обов’язково звільняють місце, поки чекпойнт існує.
Завдання 7: Перевірте подання простору на рівні dataset, щоб уникнути «паніки df»
cr0x@server:~$ df -h /tank
Filesystem Size Used Avail Use% Mounted on
tank 72T 58T 14T 81% /tank
cr0x@server:~$ sudo zfs list -o name,used,avail,refer,mountpoint tank
NAME USED AVAIL REFER MOUNTPOINT
tank 58.2T 12.9T 256K /tank
Інтерпретація: df і zfs list часто збігаються на верхньому рівні, але під час періодів з чекпойнтом ви можете опинитися в ситуації, коли поведінка додатків сигналізує “немає місця” раніше, ніж очікується, бо реальні можливості алокації ZFS суворіші, ніж розрахунок у користувацькому просторі.
Завдання 8: Переконайтеся, що ви випадково не “upgraded та activated” щось, від чого не можна відкотитися
cr0x@server:~$ sudo zpool get all tank | egrep 'feature@|compatibility|readonly'
tank readonly off default
tank compatibility off default
tank feature@async_destroy enabled local
tank feature@spacemap_histogram active local
tank feature@extensible_dataset enabled local
Інтерпретація: «Enabled» означає доступна; «active» — використовується в on-disk стані. Чекпойнт може допомогти відкотитися від деяких категорій «я передумав», але активація фіч може ускладнити сумісність і downgrade-шляхи. Не вгадуйте — інспектуйте.
Завдання 9: Сухий запуск рішення про відкат — перерахувати «що буде втрачено»
cr0x@server:~$ sudo zfs list -t snapshot -o name,creation -s creation | tail -n 5
tank/home@autosnap_2025-12-25_0900 Thu Dec 25 09:00 2025
tank/home@autosnap_2025-12-25_1000 Thu Dec 25 10:00 2025
tank/db@prechange_2025-12-25_1015 Thu Dec 25 10:15 2025
tank/db@postchange_2025-12-25_1030 Thu Dec 25 10:30 2025
tank/logs@hourly_2025-12-25_1100 Thu Dec 25 11:00 2025
Інтерпретація: Snapshots, створені після чекпойнта, будуть втрачені при відкаті пулу. Приймайте рішення про відкат із відкритими очима і попередьте зацікавлені сторони: «ви втратите все після 10:22».
Завдання 10: Відкат до чекпойнта (великий молот)
cr0x@server:~$ sudo zpool export tank
cr0x@server:~$ sudo zpool import tank
cr0x@server:~$ sudo zpool checkpoint -r tank
Інтерпретація: Відкат є руйнівною операцією і має розглядатися як подія технічного обслуговування. Export/import не завжди суворо потрібні для відкату, але на практиці це чистий спосіб гарантувати, що сервіси зупинені, точки монтування приглушені, і ви не робите відкат під час активних записів. Після відкату чекпойнт зазвичай зникає, бо ви повернулися до нього.
Завдання 11: Видалити чекпойнт (погодитися з новим світом і відновити повторне використання)
cr0x@server:~$ sudo zpool checkpoint -d tank
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint - -
Інтерпретація: Це крок «ми закінчили, залишаємо зміни». Операційно видалення часто найважливіша дія щодо чекпойнта — бо воно відновлює нормальне повторне використання простору. Встановіть дедлайн на цей крок при створенні чекпойнта.
Завдання 12: Слідкуйте за тиском простору поки існує чекпойнт
cr0x@server:~$ watch -n 5 'zpool list -o name,alloc,free,capacity,fragmentation tank; echo; zpool get checkpoint tank'
Every 5.0s: zpool list -o name,alloc,free,capacity,fragmentation tank; echo; zpool get checkpoint tank
NAME ALLOC FREE CAP FRAG
tank 60.1T 11.9T 83% 44%
NAME PROPERTY VALUE SOURCE
tank checkpoint 2025-12-25T10:22:11+00:00 -
Інтерпретація: Якщо alloc росте під час вашої зміни, можливо, ви фіксуєте старі блоки і створюєте нові. Зростаюча заповненість під час вікна з чекпойнтом — нормально; зростання заповненості біля краю — привід скасувати завчасно, видаливши чекпойнт або призупинивши зміну.
Завдання 13: Визначте інтенсивних записувачів під час вікна чекпойнта
cr0x@server:~$ sudo zpool iostat -v tank 5 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 60.1T 11.9T 5 802 1.20M 210M
raidz1-0 60.1T 11.9T 5 802 1.20M 210M
sda - - 1 270 410K 70.2M
sdb - - 2 265 420K 69.1M
sdc - - 2 267 370K 70.7M
-------------------------- ----- ----- ----- ----- ----- -----
Інтерпретація: Висока пропускна здатність запису під час вікна чекпойнта означає, що ви накопичуєте «новий світ» даних, блокуючи «старий світ». Якщо хочете, щоб чекпойнт залишався дешевим, мінімізуйте інтенсивність записів.
Завдання 14: Перевірте точки монтування і стан dataset після видалення/відкату
cr0x@server:~$ sudo zfs mount -a
cr0x@server:~$ sudo zfs list -o name,mounted,available,used,mountpoint tank | head
NAME MOUNTED AVAIL USED MOUNTPOINT
tank yes 12.9T 60.1T /tank
tank/home yes 12.9T 8.4T /tank/home
tank/db yes 12.9T 44.0T /tank/db
Інтерпретація: Після відкату не припускайте, що сервіси повернуться ідеально. Стан монтування та доступність dataset — перші перевірки «чи схопилося сховище?» перед перезапуском баз даних чи гіпервізорів.
Швидка діагностика: коли пул поводиться “странно”
Це чекліст на випадок «02:00 і щось не так». Мета — визначити, чи спричиняє симптоми чекпойнт, і чи ви маєте справу з вузьким місцем за простором, I/O або фрагментацією.
Перше: з’ясуйте, чи існує чекпойнт і як давно
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint 2025-12-25T10:22:11+00:00 -
Якщо чекпойнт є: трактуйте аномалії простору як «чекпойнт, поки не доведено протилежне». Якщо ні — продовжуйте стандартну триаж ZFS.
Друге: перевірте реальний резерв простору та червоні прапорці
cr0x@server:~$ sudo zpool list -o name,alloc,free,capacity,fragmentation,health tank
NAME ALLOC FREE CAP FRAG HEALTH
tank 60.1T 11.9T 83% 44% ONLINE
На що дивитися: заповненість, що підповзає до 90% під час наявності чекпойнта; фрагментація росте; health не ONLINE.
Третє: визначте, чи ви обмежені IOPS, пропускною здатністю або чимось іншим
cr0x@server:~$ sudo zpool iostat -v tank 2 5
cr0x@server:~$ sudo zpool status -v tank
Інтерпретація:
- Високі записи + мало вільного: ви йдете в бік «відмови алокації». Рішення швидко: видалити чекпойнт, паузити записувачів або додати місце.
- Симптоми високої затримки читання: чекпойнт рідко є прямою причиною, але корелює з періодами високої зміни і фрагментації, що може посилити затримку.
- Помилки або resilvering: не відкатуйте легковажно під час активності пристрою. Стабілізуйтеся спочатку, якщо тільки відкат не є єдиним виходом.
Четверте: перевірте, чи «працюють» видалення
cr0x@server:~$ sudo zpool list -o alloc,free,capacity tank
ALLOC FREE CAP
60.1T 11.9T 83%
Інтерпретація: Якщо ви видаляєте великі dataset’и і free не рухається під час вікна чекпойнта, не продовжуйте панічно видаляти. Ви не отримуєте запасу; ви лише ускладнюєте майбутній стан після видалення чекпойнта.
Три міні-історії з корпоративного життя
1) Інцидент через неправильне припущення
У них був бекенд для віртуалізації на великому ZFS пулі. Команда зберігання планувала зміну флагу фічі і, бажаючи бути обачними, створила чекпойнт «на всякий випадок». Вікно обслуговування пройшло тихо. Зміна здалася вдалою. Усі пішли додому.
Через два дні почалися алерти: ВМ періодично не могли завершити записи, потім каскад «файлова система лише для читання» у гостях. Он-кол бачив «15 ТБ вільного» на панелях і припустив, що проблема не в місці. Шукали привида: multipath, прошивка HBA, підозри на SSD у SLOG. Все виглядало переважно нормально.
Що насправді сталося було простіше й жорстокіше. За ті два дні пул зазнавав змін: образи ВМ, логи, зміна баз даних у гостях. Чекпойнт закріпив зростаючу кількість старих блоків, і видалення/звільнення не допомагали. Пул не був «без вільного простору» за наївною метрикою “free”, але він став ворожим до алокацій: фрагментація зросла, вільні сегменти metaslab стали менш корисні, і операції, що вимагали більш-менш суміжних алокацій, почали падати під навантаженням.
Неправильне припущення полягало в тому, що чекпойнт «безкоштовний, поки його не відкотиш». Це не так. Це живе обмеження на повторне використання простору. Вони видалили чекпойнт, і поведінка простору повернулася до норми за годину. Постмортем вимагав грубої дії: чекпойнти мають мати власника і час життя, а моніторинг має сигналізувати «чекпойнт старший X годин» так само, як сигналізує про деградацію vdev.
2) Оптимізація, що повернулася бумерангом
Платформна команда вирішила зменшити ризики обслуговування, стандартизувавши робочий процес: «чекпойнт перед кожною зміною зберігання». Здавалося б, це зрілість. Календар змін наповнився, чекпойнти стали частими. Хтось навіть автоматизував: коли ticket затверджено, автоматика створює чекпойнт і публікує таймстамп у чаті.
Потім стався бумеранг. Вони використовували один і той самий пул і для критичних баз даних, і для великого аналітичного навантаження, яке щодня переписує багато даних. Під час рутинної заміни пристрою чекпойнт створили і залишили довше, ніж очікувалося, бо постачальник відправив не ту модель диска і роботу відклали. Тим часом аналітика продовжувала бити по пулу.
Пул не впав. Він зробив щось гірше: уповільнився так, що це було складно швидко діагностувати. Латентність зросла, вікна реплікації зсунулися, і команда баз даних почала самостійно стримувати свої навантаження, щоб утримати хвостову латентність. Команда зберігання подивилася на чекпойнт і подумала: «Ми не відкотили, значить, це не має значення». Але мало значення, бо чекпойнт змусив пул одночасно нести дві реальності. Записи продовжували алокувати нові блоки, поки старі залишалися заблокованими. Карти простору ускладнилися, фрагментація зросла, і пул поводився так, ніби він старіший і більш заповнений, ніж насправді.
Виправлення було культурним: чекпойнти стали інструментом лише для змін з реальним значенням відкату, а не для кожної рутинної операції. Вони замінили «чекпойнт скрізь» на «чекпойнт коли відкат реально зменшує ризик» і поєднали це з короткоживучими dataset-snapshots для дрібних змін. Оптимізація провалилася, бо оптимізувала неправильний метрик: відчуту безпеку, а не операційну стабільність.
3) Нудна, але правильна практика, що врятувала ситуацію
Система, близька до фінансів, мала суворий процес змін: кожна зміна сховища вимагала префлайт чекліста, вікно обслуговування і план відкату, написаний простими словами. Це було настільки нудно, що інженери скаржилися — тихо, бо фінансові системи виграють аргументи своїм простим існуванням.
Під час планового оновлення пулу вони створили чекпойнт і одразу прикріпили нагадування в календарі: «Видалити чекпойнт до кінця вікна, якщо відкат не потрібен». Вони також поставили обмежувач у моніторингу: якщо чекпойнт існує більше чотирьох годин, викликати on-call та власника зміни. Це не було модно, просто була явна відповідальність і таймер.
Посеред вікна інженер помітив дивну поведінку сервісу. Не відмову, а просто «не так». Оскільки план відкату був вже написаний, вони не імпровізували. Зупинили залежні сервіси, експортували пул, чисто імпортували, відкотилися до чекпойнта і відновили сервіс. Пост-інцидент рев’ю виявило конфігураційну взаємодію, яку було б болісно розмотати вручну.
Збереження — це не був лише чекпойнт: це була дисципліна навколо нього: пригасити записи, мати дедлайн, і трактувати відкат як плановану операцію, а не емоційну реакцію. Нудне — недооцінене в зберіганні даних.
Типові помилки (із симптомами та виправленнями)
Помилка 1: Створення чекпойнта на пулі, що майже повний
Симптоми: заповненість пулу швидко зростає; видалення не повертають місце; додатки починають кидати ENOSPC або «диск заповнений» незважаючи на очікування за “free”; фрагментація збільшується.
Виправлення: якщо відкат більше не потрібен — видаліть чекпойнт. Якщо відкат може знадобитися, призупиніть інтенсивні навантаження і додайте місце (додаткові vdev або тимчасову міграцію). У кризі віддавайте пріоритет зниженню хріну над видаленням даних — видалення все одно буде заблоковане.
Помилка 2: Залишити чекпойнт «на всякий випадок»
Симптоми: повільно наростаючий тиск простору, що не корелює зі зростанням видимих даних; довготривале погіршення продуктивності при випадкових записах.
Виправлення: впровадьте політику закінчення терміну. Операційно: чекпойнт має мати людського власника, строк видалення і моніторинг, що сигналізує про старість чекпойнта.
Помилка 3: Припускати, що чекпойнти поводяться як snapshots
Симптоми: хтось очікує відновити один dataset; хтось намагається «записати» чекпойнт; плутанина щодо того, що буде втрачене.
Виправлення: навчіть команду простим правилом: snapshots — на рівні dataset; чекпойнти — на рівні пулу. Використовуйте snapshots для «хочу повернути директорію». Використовуйте чекпойнт для «хочу повернути пул».
Помилка 4: Відкат без загасання записів
Симптоми: сервіси повертаються пошкодженими на рівні додатків; бази даних потребують відновлення; ВМ можуть мати неконсистентні диски; виникає звинувачення на адресу ZFS.
Виправлення: поводьтеся з відкатом як з відновленням шару зберігання: зупиніть сервіси, скиньте буфери, відмонтуйте де можливо, export/import для гарантії відсутності активних записувачів. Потім робіть відкат. ZFS зробить те, що ви попросили; додатки зроблять те, що фізика дозволяє.
Помилка 5: Забути, що відкат стирає операційний прогрес
Симптоми: заміна пристрою «зникає», топологія відміняється або ретельно підготовлена міграція перевертається назад.
Виправлення: документуйте точно, які дії відбулися після чекпойнта. Якщо ви замінили диск після чекпойнта, відкат може повернути попередню топологію, що заплутає наступні операції. Плануйте кроки відкату, а не лише команду.
Помилка 6: Трактувати «вільний простір» як «доступний для алокації» під тиском
Симптоми: «у нас ще терабайти вільні», але алокації падають; продуктивність падає; метадані повільні; дивні стрибки латентності.
Виправлення: слідкуйте за заповненістю пулу і фрагментацією, і тримайте більше буфера, ніж думаєте — особливо під час вікна з чекпойнтом. Розгляньте тимчасове обмеження записувачів і переконайтесь, що autotrim (де доречно) не маскує поведінку на рівні пристрою.
Чеклісти / покроковий план
Чекліст A: Створення чекпойнта безпечно (продакшн)
- Підтвердьте стан: пул ONLINE, жодного resilver’а в процесі, якщо не маєте дуже специфічної причини.
- Перевірте запас: оцініть capacity і фрагментацію; якщо ви вище комфортних порогів, спочатку створіть запас.
- Визначте область відкату: що саме відкотиться? Запишіть у change record.
- Встановіть час життя: «видалити до кінця вікна» — хороший стандарт. Довші вікна потребують обґрунтування і моніторингу.
- Створіть чекпойнт: зафіксуйте таймстамп.
- Моніторте під час вікна: дивіться alloc/free і швидкість записів. Якщо тиск зростає — приймайте рішення заздалегідь.
- Завершіть вікно з наміром: або видаліть (commit), або відкотіться (revert). Не лишайте це неоднозначним.
Чекліст B: Видалення чекпойнта (найчастіший забутий крок)
- Переконайтесь, що сервіси працюють і зміна прийнята.
- Підтвердьте, що чекпойнт існує.
- Видаліть його.
- Перевірте, що воно зникло.
- Спостерігайте за поведінкою вільного простору протягом години: видалення повинні знову звільняти місце, і зріст alloc має відображати реальність.
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint 2025-12-25T10:22:11+00:00 -
cr0x@server:~$ sudo zpool checkpoint -d tank
cr0x@server:~$ sudo zpool get checkpoint tank
NAME PROPERTY VALUE SOURCE
tank checkpoint - -
Чекліст C: Безпечний відкат (коли ви справді цього хочете)
- Оголосіть вплив: усе після таймстампу чекпойнта буде втрачено.
- Загасіть: зупиніть додатки, відмонтуйте або перемонтуйте лише для читання, якщо можливо.
- Export/import: забезпечує чистий, консистентний стан імпорту пулу без активних записувачів.
- Відкат: виконайте rollback чекпойнта.
- Валідуйте: змонтуйте dataset’и, перевірте стан пулу, потім піднімайте сервіси в контрольованому порядку.
cr0x@server:~$ sudo systemctl stop libvirtd
cr0x@server:~$ sudo systemctl stop postgresql
cr0x@server:~$ sudo zpool export tank
cr0x@server:~$ sudo zpool import tank
cr0x@server:~$ sudo zpool checkpoint -r tank
cr0x@server:~$ sudo zpool status -xv tank
pool 'tank' is healthy
Поширені питання
1) Чи однаковий zpool checkpoint і ZFS snapshot?
Ні. Snapshots створюються на рівні dataset і дозволяють відновити або клонувати стан dataset. Чекпойнт — це пул-широка точка відкотування, яка перемотує назад усе на пулі, включно з усіма dataset і їх snapshots.
2) Чи можу я мати кілька чекпойнтів?
Зазвичай ні: один чекпойнт одночасно на пул. Обмеження частково щоб уникнути некерованого зростання заблокованого простору і складності.
3) Чи створення чекпойнта одразу споживає простір?
Зазвичай воно не виділяє великий обсяг одразу. Вартість проявляється по мірі модифікації даних після створення: старі блоки, які зазвичай могли б бути звільнені, лишаються заблокованими, щоб чекпойнт можна було відтворити.
4) Чому вільного не побільшало після видалення терабайтів?
Тому що чекпойнт іще посилається на старі блоки. З позиції чекпойнта дані все ще існують. Видалення чекпойнта зніме це обмеження і дозволить звичайному повторному використанню простору.
5) Чи можна «відправити» чекпойнт на іншу машину як snapshot?
Ні. Якщо вам потрібна портативність, використовуйте dataset snapshots з zfs send/zfs receive або реплікуйте пул іншим способом. Чекпойнт — не механізм реплікації.
6) Чи варто створювати чекпойнт перед zpool upgrade?
Іноді. Якщо ви в середовищі, де може знадобитися відкат, і у вас є достатній запас, це може бути розумною страховкою. Але найкраща “безпека оновлення” — тестування в staging, розуміння флагів фіч і наявність реальних бекапів/реплікації. Чекпойнт — тактичний undo, а не стратегія.
7) Чи захистить чекпойнт від апаратної відмови під час зміни?
Ні. Чекпойнт не створює другу копію ваших даних. Якщо ви втрачаєте пул або достатню кількість пристроїв, щоб зробити його недоступним, чекпойнт теж пропаде разом із ним.
8) Чи безпечно тримати чекпойнт кілька днів?
Технічно ZFS це підтримує, але операційно це ризиковано на активних пулах. Ви ставите ставку на те, що заблоковані блоки і фрагментація не підштовхнуть вас до тиску простору чи проблем з продуктивністю. Якщо треба тримати — моніторте жорстко і встановіть тверду дату видалення.
9) Чи виправить відкат корупцію на рівні додатку?
Він може відкотити зміни на рівні зберігання, але не гарантує консистентність додатку, якщо ви не загасили додаток в момент створення чекпойнта і перед відкатом. Бази даних, ВМ і розподілені системи піклуються про порядок записів і semantics flush, а не тільки про блоки на диску.
10) Яка найпростіша безпечна політика для чекпойнтів в продакшені?
Використовуйте їх лише для змін, де пул-широкий відкат справді цінний, завжди призначайте власника і дедлайн, і за замовчуванням видаляйте їх наприкінці вікна обслуговування.
Висновок
zpool checkpoint — це одна з тих фіч, що здається подарунком, поки ви не дізнаєтесь її ціну. Це пул-широкий аварійний undo, побудований на CoW, і він працює — часто дивовижно добре — коли ви використовуєте його для коротких, контрольованих вікон. Гострі краї походять з того самого джерела, що й сила: збереження минулого означає, що пул не може вільно повторно використовувати теперішнє.
Якщо запам’ятаєте тільки три речі, нехай це будуть: (1) чекпойнт — не резервна копія, (2) він може блокувати простір і тихо зруйнувати ваш запас, і (3) найбезпечніший чекпойнт — той, що має письмового власника, таймер і чітке рішення в кінці вікна: видалити або відкотитися. В зберіганні неоднозначність — це шлях, як «тимчасове» стає «постійним», а «постійне» — інцидентом.