ZFS Refreservation: гарантування місця без відключення застосунків

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

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

Це глибоке, практичне керівництво по ZFS refreservation: що воно насправді гарантує, чого не гарантує, як взаємодіє з квотами і знімками, і як використовувати його, щоб критичні застосунки продовжували працювати, поки інше бореться за останні байти. Мета не академічна правильність. Мета — більше ніколи не спостерігати, як абсолютно «здоровий» пул виводить з ладу tier‑0 сервіс тому, що кілька останніх ГіБ з’їло щось нудне.

Що таке refreservation (і навіщо воно потрібне)

refreservation — це властивість датасету ZFS, яка резервує місце на основі referenced‑даних для цього датасету. Простими словами: це ZFS, що каже «незалежно від того, що відбувається в пулі, цей датасет матиме принаймні N байт доступних для запису, поки сам пул не перейшов у фізично неможливий стан».

Частина «ref» важлива. ZFS — copy‑on‑write. «used» датасету — це не лише те, що в його поточному файловому стані. Знімки можуть утримувати старі блоки. Клони можуть ділитися блоками. Видалення не завжди звільняє місце так, як ви думаєте. Ось як виникає класичний аргумент про ZFS:

  • Застосунок: «Я видалив 500GB. Чому я не можу записати 10GB?»
  • ZFS: «Тому що ці 500GB все ще посилаються зі знімків, клонів або інших датасетів. Гарна спроба.»

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

Оперативний опис: refreservation — це спосіб не дозволити «важливим датасетам» бути позбавленими місця через «цікаві датасети». Важливі: бази даних, журнальні черги, сховища метаданих, завантажувальні томи віртуальних машин. Цікаві: усе, куди люди можуть скидати дані, особливо логи, бакети для завантажень, артефакти збірки або «тимчасові» scratch‑зони, які тимчасові з 2019 року.

Жарт №1: Refreservation як покласти свій обід у холодильник офісу з написаним іменем — тільки воно реально працює.

Цікаві факти та історичний контекст

Інженерія зберігання сповнена «нових» ідей, які насправді старі, але з кращими інструментами. Кілька контекстних пунктів, що допомагають зрозуміти refreservation:

  1. ZFS створювався для цілісності від кінця до кінця, а не лише для управління ємністю. Контролі простору, як квоти й резервації, існують тому, що «коректно, але заповнено» все одно ламає застосунки.
  2. Файлові системи copy‑on‑write ускладнюють видалення. Традиційні файлові системи зазвичай звільняють блоки при видаленні; ZFS звільняє блоки тільки коли нічого на них не посилається. Знімки — найпоширеніше «щось».
  3. Парадокс «df» існував ще до ZFS. Навіть у старих системах зарезервовані блоки, службові накладні витрати й відкладене виділення викликали ситуації «df показує вільне». ZFS просто робить причини більш вагомими — і більш заплутаними.
  4. Тонке провізіювання стало масовим у віртуалізації і принесло новий клас відмов: гостьові ОС думають, що мають місце; бекенд не погоджується о 3:00. Резервації ZFS — один із чесніших способів керувати тонким проти товстого підходів.
  5. Знімки перейшли зі «функції бекапу» в «операційну за замовчуванням». Як тільки команди почали створювати знімки часто (щогодини, кожні 15 хвилин, іноді кожні 5), тиск на простір став повсякденною проблемою.
  6. «Тримати 20% вільними» — це не забобон. Багато систем зберігання (включаючи ZFS) деградують у продуктивності й гнучкості виділення при заповненні. Refreservation не виправить фізику.
  7. Наслідування властивостей ZFS — це і фіча, і підводний камінь. Резервації й квоти можуть успадковуватися несподівано; refreservation часто встановлюють на рівні датасету, бо «один розмір підходить усім» не працює.
  8. Refquota/refreservation виникли через реальний біль адміністраторів. «ref»‑властивості існують тому, що «used» може включати простір, який ви не можете вільно звільнити (знімки/клони).

Ментальна модель: referenced vs available space

Якщо ви експлуатуєте ZFS довго, у вас з’являються два умовні реєстри:

  • Логічна власність: те, що здається, що датасет містить зараз.
  • Фізична реальність: які блоки все ще посилаються десь у пулі.

ZFS показує це розділення через просторові властивості датасету. Точний вивід різниться за платформами (OpenZFS на Linux проти illumos‑похідних), але ідеї стабільні:

  • used: загальний простір, спожитий датасетом і його нащадками, включаючи знімки (залежно від контексту) та накладні витрати.
  • referenced: простір, на який посилається поточний стан датасету (без знімків).
  • usedbydataset, usedbysnapshots, usedbychildren: найкращий розподіл «куди воно пішло?».
  • available: що ZFS вважає записуваним у датасет, після квот/резервацій та обмежень пулу.

refreservation пов’язаний із referenced. Думайте про нього так: «Я хочу гарантувати, що цей датасет може збільшити свої referenced байти щонайменше на N, незважаючи на багаж знімків десь в іншому місці». Механіка тонка, але оперативний ефект ясний: воно вирізає простір у пулі, який інші датасети не можуть претендувати.

Reservation vs refreservation vs квоти

ZFS пропонує кілька важелів, що звучать схоже. Вони не взаємозамінні. Ось практична мапа:

reservation

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

refreservation

refreservation стосується власного referenced‑простору датасету (не знімків). Це більш точний інструмент, коли вам важливо, щоб датасет міг продовжувати писати свій поточний live‑стан, навіть якщо є знімки і видалення не відразу повертають місце.

quota

quota обмежує, скільки простору датасет (і зазвичай його нащадки) може спожити. Це «ви не можете рости понад цей ліміт». Добре для мультенантного контролю. Погано, якщо ви виставили й забули.

refquota

refquota обмежує referenced простір (поточні live‑дані), а не знімки. Це часто те, що вам потрібно, коли ви не хочете, щоб знімки були причиною відмови запису — хоча ви все одно обмежені загальною ємністю пулу.

Коротке правило прийняття рішень

  • Якщо ви хочете обмежити live‑дані застосунку: використовуйте refquota.
  • Якщо ви хочете обмежити все, включно зі спалахом знімків: використовуйте quota.
  • Якщо ви хочете гарантувати мінімальний шматок для live‑записів датасету: використовуйте refreservation.
  • Якщо ви хочете гарантувати мінімальний шматок для цілого піддерева: використовуйте reservation.

Жарт №2: Якщо квоти — це дієта, refreservation — це підготовка їжі — менш захопливо, більш ефективно, і всі її ненавидять, поки не настане криза.

Як ZFS застосовує refreservation (що насправді гарантується)

Резервації ZFS — це не магічний додатковий простір; це зони виключення. Коли ви встановлюєте refreservation, ZFS зменшує те, що інші датасети бачать як доступне, бо цей простір зарезервований.

Три важливі операційні істини:

  1. Refreservation допомагає тільки якщо у пулу є місце, щоб її виконати. Якщо пул справді повний (або ефективно повний через slop‑простір і потреби метаданих), ZFS не може виділити блоки, яких не існує. Refreservation — це політика, а не закон термодинаміки.
  2. Refreservation не резервує «місце для знімків». Йдеться про зростання referenced/live‑даних. Знімки все ще можуть споживати пул і створювати проблеми, просто не викрадати гарантований шматок від live‑записів того датасету.
  3. Refreservation може змусити інші датасети відмовити раніше — і в цьому суть. Це механізм пріоритетизації. Ваш датасет архіву логів має впасти раніше, ніж датасет бази даних.

Також ZFS чесний, але не завжди інтуїтивний: значення available для датасету вже відображає ці політичні обмеження. Якщо ваша refreservation велика, zfs list для інших датасетів покаже менше available, навіть якщо в пулі є сире вільне місце.

Три міні‑історії з корпоративного світу

Міні‑історія №1: Аварія через неправильне припущення («Знімки — це бекапи, правда?»)

Середня компанія запускала API для клієнтів на PostgreSQL на ZFS. Макет сховища виглядав чисто: один пул, датасет для бази, датасет для WAL і датасет для логів. Вони робили часті знімки, бо це здавалося відповідальним. І так воно й було — поки не стало ні.

Розробник запустив backfill‑завдання, яке створило велику тимчасову таблицю, а потім видалив її. Команда спостерігала, як файлове використання бази зросло, а потім впало. Усі зітхнули. Але пул не відновився. Бо знімки утримували блоки, «звільнене» місце насправді не було вільним. Пул повільно підходив до повного протягом наступних кількох годин, поки писання продовжувалися.

При ~95% використання пулу (ефективно) продуктивність погіршилась. Латентність зросла. Autovacuum почав трястися. Потім датасет WAL отримав ENOSPC. PostgreSQL зробив те, що роблять БД, коли не може писати WAL: перестав бути базою даних.

Неправильне припущення було тонким: «Якщо база видаляє дані, пул отримує місце назад». На ZFS зі знімками це не гарантовано. Вони не мали refreservation на WAL, не мали refquota для контролю тимчасового росту, і політика збереження знімків була «назавжди, поки ми не згадаємо очистити». Виправлення не було героїчним: додали refreservation на WAL, розмірене refquota для бази, і встановили політику життя знімків з виконанням.

Постмортем містив рядок, який я бачив у різних формах: «Ми ставилися до знімків як до бекапів». Знімки — це машина часу, прикріплена до вашого шару алокації. Вони надзвичайно корисні — просто не безкоштовні.

Міні‑історія №2: Оптимізація, що вийшла боком («Тонке все!»)

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

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

Через два тижні якийсь пайплайн збірки вийшов з-під контролю. Він наповнив датасет артефактів багатогігабайтними бінарними файлами. Оскільки нічого не було зарезервовано, датасет артефактів без проблем поглинув залишковий простір пулу. Коли гіпервізор спробував записати в диск VM (невелике оновлення метаданих), запис провалився. Раптом VM, що мали багато здаваного вільного місця всередині гостя, не могли закомітити записи на рівні сховища. Результат — маса примонтованих лише для читання файлових систем і безліч «як це можливо?»

Урок не в тому, що тонке провізіювання погане. Урок у тому, що тонке без правил пріоритету — це гра в рулетку. Резервації/refreservation — це ті правила. Команда відновила гарантії для завантажувальних томів і баз даних, і перемістила артефакт‑датасет за квоту плюс окремий «overflow» пул. Щільність трохи впала. Сон покращився значно.

Міні‑історія №3: Нудна, але правильна практика, що врятувала день («Захистіть журнал»)

Команда платежів запускала чергу повідомлень, чия надійність залежала від write‑ahead журналу. Черга не була гламурною, але це була система запису для роботи в польоті. Хтось у команді вже постраждав від інцидентів через заповнений диск, тому вони зробили щось зовсім нецікаве: створили окремий датасет для журналу і встановили refreservation, виходячи з максимальної швидкості запису та часу реагування на інцидент.

Місяці потому під час ескалації клієнта включили «режим налагодження». Логи вибухнули. Не мило — в терабайтах за день. Датасет логів проковтнув усе, включно зі знімками, і пул став щільним за кілька годин.

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

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

Практичні завдання (команди + інтерпретація)

Оце практичні завдання, які можна виконати на OpenZFS‑системі (зазвичай Linux з ZFS‑on‑Linux/OpenZFS). Команди вимагають привілеїв. Замініть назви пулів/датасетів під вашу середу.

Завдання 1: Отримати стан пулу і реальну ємність

cr0x@server:~$ zpool status -v
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 0 days 00:12:41 with 0 errors on Sun Dec 22 02:10:11 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          sda       ONLINE       0     0     0
          sdb       ONLINE       0     0     0

errors: No known data errors

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

Завдання 2: Подивитися вільне місце на пулі і підказки про фрагментацію

cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
NAME  SIZE  ALLOC  FREE  CAP  FRAG  HEALTH
tank  7.25T  6.10T  1.15T  84%   29%  ONLINE

Інтерпретація: Високі CAP і зростаючий FRAG — це умови, де «має працювати» перетворюється в «чому це повільно і відмовляє?». Якщо ви постійно вище ~85–90%, ви в зоні ризику незалежно від резервацій.

Завдання 3: Інвентар датасетів і їх доступного простору

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint
NAME               USED  AVAIL  REFER  MOUNTPOINT
tank               6.10T  1.02T   192K  /tank
tank/db            2.40T   220G  2.10T  /tank/db
tank/db-wal         180G   120G   175G  /tank/db-wal
tank/logs          1.60T   140G  1.20T  /tank/logs
tank/artifacts     1.90T    90G  1.50T  /tank/artifacts

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

Завдання 4: Показати властивості, пов’язані з резервацією, для всіх датасетів

cr0x@server:~$ zfs get -r -o name,property,value,source reservation,refreservation,quota,refquota tank
NAME             PROPERTY        VALUE  SOURCE
tank             reservation     none   default
tank             refreservation  none   default
tank             quota           none   default
tank             refquota        none   default
tank/db          reservation     none   default
tank/db          refreservation  300G   local
tank/db          quota           none   default
tank/db          refquota        3T     local
tank/db-wal      reservation     none   default
tank/db-wal      refreservation  200G   local
tank/db-wal      quota           none   default
tank/db-wal      refquota        none   default
tank/logs        reservation     none   default
tank/logs        refreservation  none   default
tank/logs        quota           2T     local
tank/logs        refquota        none   default

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

Завдання 5: Встановити refreservation для критичного датасету

cr0x@server:~$ sudo zfs set refreservation=200G tank/db-wal
cr0x@server:~$ zfs get refreservation tank/db-wal
NAME         PROPERTY        VALUE  SOURCE
tank/db-wal  refreservation  200G   local

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

Завдання 6: Підтвердити, як refreservation впливає на доступний простір інших датасетів

cr0x@server:~$ zfs list -o name,avail tank/logs tank/artifacts tank/db-wal
NAME           AVAIL
tank/logs      90G
tank/artifacts 40G
tank/db-wal    120G

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

Завдання 7: Побачити, де зв’язане місце (датасет vs знімки)

cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots,usedbychildren,refer -t filesystem tank/db
NAME      USED  USEDBYDATASET  USEDBYSNAPSHOTS  USEDBYCHILDREN  REFER
tank/db  2.40T          2.10T            260G              40G  2.10T

Інтерпретація: Якщо USEDBYSNAPSHOTS великий, видалення не звільнить місце. Якщо ваш застосунок «звільнив» дані, а пул цього не показав — починайте з цього розподілу.

Завдання 8: Перелік знімків і пошук великих винуватців

cr0x@server:~$ zfs list -o name,used,refer,creation -t snapshot tank/db | tail -n 5
tank/db@auto-2025-12-23-0000   12.4G  2.06T  Tue Dec 23 00:00 2025
tank/db@auto-2025-12-23-0100    9.8G  2.07T  Tue Dec 23 01:00 2025
tank/db@auto-2025-12-23-0200   15.1G  2.07T  Tue Dec 23 02:00 2025
tank/db@auto-2025-12-23-0300   11.2G  2.08T  Tue Dec 23 03:00 2025
tank/db@auto-2025-12-23-0400   10.6G  2.08T  Tue Dec 23 04:00 2025

Інтерпретація: USED у знімку — це простір, унікальний для цього знімку (відносно інших). Великі числа часто корелюють з інтенсивними робочими навантаженнями (бази даних, CI‑артефакти) і можуть виправдовувати посилення утримання або переміщення навантажень.

Завдання 9: Перевірити, чи датасет блокується квотою/refquota, а не повнотою пулу

cr0x@server:~$ zfs get -o name,property,value quota,refquota tank/logs
NAME       PROPERTY  VALUE
tank/logs  quota     2T
tank/logs  refquota  none

Інтерпретація: Якщо застосунок бачить ENOSPC, але пул не повний, квоти — головний підозрюваний. Квота — це «локальна повнота», навіть якщо пул має ємність.

Завдання 10: Виміряти реальний referenced‑запас проти розміру refreservation

cr0x@server:~$ zfs get -o name,property,value referenced,refreservation tank/db-wal
NAME         PROPERTY        VALUE
tank/db-wal  referenced      175G
tank/db-wal  refreservation  200G

Інтерпретація: Коли referenced 175G, а refreservation 200G, ви фактично гарантуєте близько 25G додаткового referenced‑зростання (залежно від реальності пулу). Якщо referenced вже вище за refreservation, вам не «боргують» додатково; резервація вважається повністю використаною.

Завдання 11: Використати reservation, коли потрібно захистити піддерево

cr0x@server:~$ sudo zfs set reservation=500G tank/db
cr0x@server:~$ zfs get reservation tank/db
NAME     PROPERTY     VALUE  SOURCE
tank/db  reservation  500G   local

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

Завдання 12: Безпечно видалити refreservation (і перевірити вплив)

cr0x@server:~$ sudo zfs set refreservation=none tank/db-wal
cr0x@server:~$ zfs get refreservation tank/db-wal
NAME         PROPERTY        VALUE  SOURCE
tank/db-wal  refreservation  none   default

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

Завдання 13: Перевірити обмеження «slop space» пулу (чому останні кілька ГіБ не поводяться як треба)

cr0x@server:~$ zfs get -o name,property,value special_small_blocks 2>/dev/null
cr0x@server:~$ zfs list -o name,avail tank

Інтерпретація: Багато операторів здивовані практичним лімітом, коли ZFS стає обережним порядком при заповненні, щоб зберегти працездатність пулу. Якщо ви проєктуєте гарантії, не плануйте використовувати «100% розміру пулу». Залишайте резерв.

Завдання 14: Визначити, чи видалення блокується знімками/клонами

cr0x@server:~$ zfs get -o name,property,value used,referenced,usedbysnapshots tank/artifacts
NAME            PROPERTY        VALUE
tank/artifacts  used            1.90T
tank/artifacts  referenced      1.50T
tank/artifacts  usedbysnapshots 380G

Інтерпретація: Якщо «видалені» дані були частиною referenced‑стану, але знімки їх утримали, usedbysnapshots росте. Це часта причина «rm -rf не допомогло».

Завдання 15: Створити «жертвений» датасет з квотою, щоб поглинати сміття

cr0x@server:~$ sudo zfs create tank/scratch
cr0x@server:~$ sudo zfs set quota=200G tank/scratch
cr0x@server:~$ zfs get -o name,property,value quota tank/scratch
NAME          PROPERTY  VALUE
tank/scratch  quota     200G

Інтерпретація: Це операційна версія «поклади брудні речі в одну кімнату з замком». Тимчасові завдання можуть писати сюди і влучати у стіну до того, як зачеплять продакшн‑датасети.

Швидкий план діагностики

Коли щось відмовляє з ENOSPC, повільними записами або «доступного простору не має сенсу», не копайтеся хаотично. Перевірте в такому порядку.

1) Реальність пулу: чи пул справді повний або нездоровий?

cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
cr0x@server:~$ zpool status -v

Що шукати: CAP > ~90%, дуже висока фрагментація або деградований стан. Якщо пул «палає», налаштування на рівні датасету другорядні.

2) Обмеження датасету: quota/refquota/reservation/refreservation

cr0x@server:~$ zfs get -r -o name,property,value,source quota,refquota,reservation,refreservation tank

Що шукати: Датасет, що досяг quota/refquota, або інші датасети, які «втрачають» доступність через велику reservation/refreservation десь ще.

3) Місце, утримуване знімками і дітьми

cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots,usedbychildren,refer -t filesystem tank
cr0x@server:~$ zfs list -t snapshot -o name,used,creation | tail

Що шукати: Великий usedbysnapshots на «хворих» датасетах; дочірній датасет, що споживає батьківську резервацію; знімки, що множать ріст.

4) Якщо симптом — продуктивність: перевірити насичення I/O пулу і латентність

cr0x@server:~$ iostat -x 1 5
cr0x@server:~$ zpool iostat -v 1 5

Що шукати: Високе завантаження дисків, довгі await‑часи та нерівномірне навантаження на пристрої. Пул поряд з повним також підсилює write amplification і метаданний треш.

5) Підтвердити погляд застосунку (файлова система vs ZFS)

cr0x@server:~$ df -hT /tank/db /tank/db-wal
cr0x@server:~$ zfs list -o name,avail,used,refer tank/db tank/db-wal

Що шукати: Розбіжність між df і zfs list зазвичай означає політику ZFS (квота/резервація) або реальність знімків, а не загальний погляд ОС.

Типові помилки (симптоми + виправлення)

Помилка 1: «Ми встановили refreservation і тепер пул ‘втратив’ місце.»

Симптом: Інші датасети показують різко зменшене AVAIL. Хтось каже, що ви «спожили» сотні гігабайт без запису даних.

Що відбувається: Резервації/refreservation зменшують загальну доступність; це виконання гарантії.

Виправлення: Правильно підібрані гарантії на основі гіршого випадку записів і часу реагування. Якщо потрібно захистити кілька сервісів — розподіліть менші гарантії замість одного великого carve‑out. Підтвердіть за допомогою:

cr0x@server:~$ zfs get -r -o name,property,value refreservation,reservation tank

Помилка 2: Припущення, що refreservation захистить від знімків, що заповнюють пул

Симптом: Ви встановили refreservation на критичний датасет, але записи все одно відмовляють, коли пул майже повний.

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

Виправлення: Впроваджуйте політику утримання знімків і забезпечуйте запас ємності. Розглядайте «пул > 90%» як інцидент, а не метрику. Дослідіть використання знімків:

cr0x@server:~$ zfs list -o name,used,usedbysnapshots -t filesystem tank | sort -h -k3

Помилка 3: Використання reservation, коли мали на увазі refreservation (або навпаки)

Симптом: Ви резервували місце на батьківському датасеті, але дочірній датасет все одно отримує ENOSPC; або ви встановили refreservation на батька й воно не поводиться як «гарантія для піддерева».

Що відбувається: reservation і refreservation застосовуються по‑різному щодо ієрархії й обліку простору.

Виправлення: Визначте, чи ви захищаєте одиночний датасет для live‑записів (refreservation), чи ціле піддерево (reservation). Перевірте успадкування і місце застосування резервації:

cr0x@server:~$ zfs get -r -o name,property,value,source reservation,refreservation tank/db

Помилка 4: Розгляд квот як «безпечні значення за замовчуванням» без моніторингу

Симптом: Сервіс відмовляє у записах, хоча пул має достатньо вільного місця.

Що відбувається: Датасет досяг quota або refquota. З погляду застосунку — диск закінчився.

Виправлення: Моніторьте used датасетів відносно квот і тривожте завчасно. Швидка перевірка:

cr0x@server:~$ zfs get -o name,property,value quota,refquota tank/service

Помилка 5: Робити гарантії більшими, ніж ваш «часовий запас» на реакцію

Симптом: Менш критичні датасети постійно отримують ENOSPC; команди починають обходити контролі; ви опиняєтеся у циклі whack‑a‑mole.

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

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

cr0x@server:~$ zfs get -r -H -o value refreservation,reservation tank | awk '
{ if ($1 != "none") sum += $1 }
END { print sum }'

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

Контрольні списки / покроковий план

Чек‑ліст A: Впровадження refreservation для критичного сервісу (без сюрпризів)

  1. Виміряйте піковий обсяг запису. Подивіться на найгірший об’єм запису за 1–6 годин, плюс накладні витрати і час реагування на інцидент.
  2. Підтвердіть запас пулу. Якщо пул живе вище 85–90%, виправте ємність спочатку. Гарантії на хронічно повному пулі — це перестановка меблів.
  3. Створіть виділений датасет. Не діліть датасет між «критичними записами» і «усім іншим».
  4. Встановіть refreservation на датасет. Почніть скромно, потім коригуйте за спостереженнями.
  5. Опційно обмежте шумних сусідів. Додайте quota або refquota для лог/артефакт‑датасетів, щоб вони падали раніше, ніж tier‑0.
  6. Підтвердіть зміни доступності. Переконайтеся, що avail інших датасетів не впало нижче безпечних порогів.
  7. Симулюйте режим відмови. Наповніть нетривкий датасет до квоти і переконайтеся, що критичний датасет продовжує писати.

Чек‑ліст B: Реакція на інцидент ємності, коли пул підходить до повного

  1. Визначте основних споживачів (zfs list та розподіл usedbysnapshots).
  2. Перевірте утримання знімків і видаліть правильні знімки (не випадкові) коли безпечно.
  3. Переконайтеся, що ніде не працює вибуховий датасет без обмеження (без квоти), поки критичні датасети без гарантій.
  4. Зменшіть churn: зупиніть роботу, що генерує хвилю записів.
  5. Лише потім розгляньте екстрені зміни властивостей (тимчасове зменшення квот, тимчасові резервації) з явними кроками відкату.

Покроково: Розумна політика «тиравання» з refreservation

Практичний шаблон, що добре працює в корпоративних мультисервісних пулах:

  1. Tier 0 датасети (повинні продовжувати писати): встановіть refreservation; розгляньте виділений пул або спеціальні vdev, якщо доречно; алертуйте при падінні avail нижче гарантійного запасу.
  2. Tier 1 датасети (важливі, але деградуються): помірні квоти/refquota; менші резервації при потребі.
  3. Tier 2 датасети (best effort): квоти обов’язкові; знімки зберігаються коротко; приймайте ENOSPC як контрольовану відмову.

FAQ

1) Чи гарантує refreservation вільне місце навіть якщо пул 99% заповнений?

Ні. Воно гарантує політичну доступність у межах фізичної здатності пулу виділяти блоки. Близькі до повного пули можуть відмовляти у виділенні через потреби в метаданих і операційні запаси ZFS.

2) Який найпростіший спосіб визначити, чи ENOSPC спричинений квотою чи заповненістю пулу?

Перевірте і пул, і датасет:

cr0x@server:~$ zpool list -o name,cap,free
cr0x@server:~$ zfs get -o name,property,value quota,refquota tank/the-dataset

Якщо пул має вільне місце, але датасет близький до ліміту quota/refquota — це локальне обмеження датасету.

3) Чому видалення файлів не звільняє місце на ZFS?

Тому що знімки (а іноді й клони) все ще можуть посилатися на блоки. Видалення прибирає посилання з live‑файлової системи, але блоки залишаються виділеними, доки на них щось посилається.

4) Чи слід використовувати refreservation для баз даних?

Часто так — для write‑ahead журналів/журналій і інших томів, критичних для збереження даних, бо саме вони першими виведуть сервіс при неможливості запису. Поєднуйте з дисципліною знімків і моніторингом ємності.

5) Чи допоможе refreservation з проблемою «df показує місце але записи відмовляють»?

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

6) Чи те ж саме refreservation і передалокація файлу?

Ні. Передалокація файлу (наприклад, fallocate) виділяє блоки для конкретного файлу. Refreservation — це гарантія на рівні датасету, що зменшує те, що інші датасети можуть використати. Це політика, а не конкретне розміщення блоків.

7) Як знімки взаємодіють з refreservation?

Знімки споживають простір пулу у міру змін live‑датасету. Refreservation не «резервує простір для знімків», але допомагає гарантувати захищений запас для росту live‑referenced‑даних датасету.

8) Як підібрати розмір refreservation?

Базуйтеся на: піковій швидкості запису × (час виявлення + час пом’якшення) плюс запас на операційні коливання. Якщо ваш WAL може вирости на 30G за годину під час піку, резервування 10G — це оптимізм, а не інженерія.

9) Чи можна встановити refreservation на zvol?

Так, і це може бути особливо актуально для zvol‑підтриманих VM‑дисків, де ви хочете гарантувати бекенд‑місто. Але також врахуйте volsize і чи ви фактично не використовуєте тонке провізіювання.

Висновок

ZFS refreservation — не код для шахрайства з ємністю. Це інструмент проектування режимів відмов. У спільному пулі щось врешті‑решт спробує з’їсти весь доступний простір — логи, артефакти, неконтрольований запит, «тимчасовий» експорт. Без гарантій першим відмовить не те, що потрібно, і інцидент перетвориться на бізнес‑проблему.

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

← Попередня
Proxmox pvedaemon.service не працює: чому завдання не запускаються і як це виправити
Наступна →
Драйвери Arc: як покоління GPU виправляють публічно

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