Мультиорендне сховище виходить з ладу найменш поетичним способом: пул досягає 100%, оновлення метаданих зупиняються, і раптом ваша «дрібна проблема»
перетворюється на відмову з запрошенням на зустріч посеред ночі. Один галасливий орендар не потребує зла; достатньо безконтрольного кешу збірки або циклу логів.
ZFS дає інструменти, щоб тримати орендарів у межах їхніх меж. Хитрість — вибрати правильний тип квоти, розмістити її на відповідному кордоні
і розуміти, як знімки і резерви змінюють вашу ментальну модель. Якщо ви помилитесь у будь-чому з цього, ви не забезпечите справедливості —
ви просто створите новий і цікавий режим відмови.
Цілі проєктування: що означає «безпечний мультиоренд»
Безпека мультиорендного ZFS — це не «усім дати квоту». Це набір явних результатів:
- Один орендар не може заповнити пул (або якщо може — ви помічаєте це заздалегідь, а зона ураження обмежена).
- Вільне місце в пулі тримається вище безпечного порога, щоб ZFS міг розподіляти, скидати та зберігати прийнятну затримку.
- Орендарі отримують передбачувані помилки: ідеально EDQUOT (quota exceeded), а не ENOSPC (pool full) і не «все повільно».
- Операції можуть пояснити використання простору без інтерпретацій: «цей dataset великий через знімки» — це реальна відповідь.
- Видалення працює, коли потрібно. «Диск повний і ви не можете видалити» — класична жахіття для сховищ.
Ви проєктуєте межі. Датасети — це ті межі. Квоти їх застосовують. Резерви їх гарантують. А знімки — це
гріми, що перетинають межі, про яких потрібно пам’ятати, інакше ви займаєтесь перформанс-артом.
Оціночна порада: використовуйте datasets як контейнери для орендарів, а не як просто каталоги. Якщо ви не можете поставити ZFS-властивість на це,
ви не зможете надійно ним керувати.
Цікаві факти та історичний контекст
- ZFS була створена в Sun у середині 2000-х з наскрізною цілісністю даних і підходом pooled storage як першокласними цілями, а не доповненнями.
- Квоти з’явилися рано, оскільки ZFS очікувала консолідацію: кілька споживачів, що ділять пул, кожен потребує передбачуваних обмежень.
- Знімки дешево створювати, бо на початку це лише метадані; витрати проявляються пізніше через збережені блоки.
- «Referenced» vs «used» у звітах ZFS існують саме тому, що знімки ускладнюють питання «скільки простору моє?».
- Резерви спроєктовані для справедливості та доступності: вони тримають критичні датасети живими навіть під тиском пулу.
- Zvol та файлові системи керуються по-різному: квоти на файлових системах не завжди прямо відображаються на споживачів zvol; стратегія провізування важлива.
- Історично ZFS хотіла запас вільного місця (часто 10–20%), щоб зберегти ефективність алокації і уникнути патологічної фрагментації і стрибків затримки.
- OpenZFS розвивав інструменти (наприклад, розширені звіти по квотах), коли оператори почали використовувати його у більших, голосніших мультиорендних середовищах.
Примітиви квот: quota, refquota, reservation і чому назви важливі
Межі датасету — це межа політики
ZFS не робить «квоти на дерево каталогів» так само нативно, як традиційні файлові системи. Вона робить властивості на датасетах.
Це — перевага. Вона змушує вас визначати реальних орендарів. Орендар — це датасет. Все інше — деталі реалізації.
quota: обмежує датасет і його нащадків
quota обмежує загальний простір, який датасет може спожити, включно з простором, що займають нащадки (child datasets).
Це правильний інструмент, коли орендар володіє піддеревом датасетів.
Але це також інструмент, що здатен здивувати людей, тому що він взаємодіє зі знімками. Якщо у вашого датасету є знімки,
блоки, утримувані знімками, враховуються у використанні таким чином, що може бути неінтуїтивним. Якщо ви хочете обмежити «живі дані орендаря»,
ймовірно вам потрібен refquota.
refquota: обмежує referenced-простір (живі дані), а не знімки
refquota обмежує referenced-простір датасету: блоки, до яких наразі доступний хед датасету.
Знімки не входять у «referenced», тому орендарі не застрягатимуть через те, що старі знімки утримують простір у заручниках.
Це звучить як магія. Але це не так. Пул все ще може заповнитися, тому що знімки все одно споживають простір пулу. Ви просто змістили зону ураження:
ви запобігли випадковому EDQUOT через утримання історії, але не запобігли глобальному ENOSPC в пулі.
reservation і refreservation: гарантований простір, але без халяви
Резерви відтинають простір, який інші не можуть використати. Це ваш важіль «тримати цю службу працюючою».
reservation включає нащадків. refreservation застосовується до referenced-простору.
Резерви можуть врятувати вас під час тиску на пул. Вони також можуть перетворити «ми мало вільного» на «ми мертві», якщо їх занадто багато,
бо вони роблять вільний простір видимим для пулу, але недоступним для більшості датасетів.
Чому «один користувач вбиває пул» все ще трапляється з квотами
Квоти зупиняють орендаря від запису понад ліміт. Вони не забезпечують автоматично загальний пул-безпечний запас.
Якщо ви встановите квоти, що в сумі дають 200% від пулу, ви створили oversubscription. Для багатьох робочих навантажень це може бути прийнятно.
Це також може стати тим, як ви швидко дізнаєтесь, що таке «облік простору під знімками».
Парафраз ідеї, приписано: Коли ви будуєте системи, ви міняєте легкі проблеми на складні; робота з надійністю — це вибір складних проблем, які ви можете моніторити.
— Charity Majors (парафраз)
Також: квоти не зменшують write amplification. Орендар може залишатися в межах квоти і все одно зруйнувати затримку, примушуючи фрагментацію,
роблячи багато синхронних операцій або дрібні часті перезаписи. Квоти — про керування місткістю, не про продуктивність. Потрібні обидва підходи.
Жарт №1: Квота — це як дієта — ефективна, поки ви не знайдете, що знімки — це нічні закуски, які ви не записали.
Моделі розміщення dataset, що не ненавидять вас
Модель A: один датасет на орендаря (за замовчуванням переможець)
Створіть pool/tenants/$tenant як файлову систему dataset. Покладіть усе для цього орендаря туди.
Застосуйте квоти, стиснення, вибір recordsize, політики знімків і точки монтування на рівні орендаря.
Переваги: чисте керування, легка звітність, низьке когнітивне навантаження. Недоліки: більше датасетів (що нормально, доки ви не перестараєтесь), і потрібна автоматизація.
Модель B: батьківський датасет з дочірніми по сервісу
Приклад: pool/tenants/acme/home, pool/tenants/acme/db, pool/tenants/acme/cache.
Поставте quota на батька, щоб обмежити загальний слід орендаря, і refquota на конкретні діти, щоб тримати живі дані в порядку.
Ця модель дозволяє налаштовувати властивості під навантаження (recordsize для БД, logbias, стиснення), зберігаючи при цьому ліміт на рівні орендаря.
Це зрілий дизайн для платформи.
Модель C: каталог на орендаря всередині одного датасету (уникати)
Традиційні UNIX-адміні люблять це через простоту: /srv/tenants/acme, /srv/tenants/zenith.
На ZFS це неправильна абстракція. Ви втрачаєте нативне управління і в результаті приробляєте користувацькі/групові квоти, проектні квоти або зовнішні інструменти.
Є обґрунтовані причини — наприклад мільйони орендарів, коли кількість датасетів стає проблемою управління — але робіть такий вибір свідомо.
Для більшості корпоративних мультиорендних систем (десятки до тисяч) dataset-per-tenant безпечніший і простіший.
Модель D: zvol на орендаря (лише коли потрібно)
Якщо орендарям потрібні блочні пристрої (диски віртуальних машин, iSCSI LUN), використовуйте zvols. Квоти на zvol — це volsize.
Тонка провізія (thin provisioning) може сильно oversubscribe пул, якщо не бути обережним. Для мультиорендного середовища ви повинні поєднати це зі строгим моніторингом
і політикою запасу пулу.
Знімки: мовчазне обійшення квоти
Дві найпоширеніші «сюрпризи з квотами»:
- Орендар досягає квоти навіть після видалення великої кількості файлів.
- Орендар залишається в межах квоти, але пул все одно заповнюється і страждають усі.
Як знімки плутають видалення
Якщо знімок посилається на блоки, які використовував файл, видалення файлу з живого датасету не звільняє ці блоки. Знімок досі їх власник.
Ось чому оператори говорять «простір застряг у знімках». Він не застряг; правильно віднесений до історії.
Якщо ви використовували quota (не refquota), блоки, утримувані знімками, враховуються у «used» і можуть тримати орендаря на межі квоти.
Орендар буде клястися, що видалив речі. Він видалив. Політика зберігання не згодна.
Чому refquota допомагає користувачам, але може нашкодити пулам
refquota покращує UX: воно робить застосування квоти відповідним живому хеду датасету.
Але воно пересуває ризик: знімки можуть рости, поки пул не відчує тиск. Якщо ви обираєте refquota, ви також повинні вибрати:
обмеження знімків, дисципліну утримання та оповіщення на рівні пулу.
Утримання знімків — це політика, а не стратегія бекупу
Знімки чудові для короткострокового відкату, стрімів реплікації та судової відновлюваності. Вони не дають права зберігати все назавжди
на найгарячішому пулі. Ставте утримання в бюджет: визначайте його, забезпечуйте виконання і переглядайте, коли орендарі змінюють поведінку.
Жарт №2: Знімки — як офісні шухляди зі сміттям — ніхто їх не хоче, але всі панікують, коли ви пробуєтесь їх почистити.
Практичні завдання (команди, вивід, рішення)
Найшвидший шлях правильно налаштувати квоти — запускати один і той самий невеликий набір команд щоразу та інтерпретувати їх послідовно.
Нижче — реальні завдання, які ви можете виконати на хості ZFS. Кожне включає: команду, що означає вивід, і яке рішення прийняти.
Завдання 1: Підтвердити стан пулу та чи ви вже в біді
cr0x@server:~$ zpool status -x
all pools are healthy
Значення: відомих помилок пулу немає. Це не означає, що у вас є вільний простір і не означає, що продуктивність нормальна.
Рішення: якщо це не «healthy», спочатку виправте апаратні/пул помилки. Квоти не врятують деградований пул від поганої латентності.
Завдання 2: Перевірити ємність пулу, фрагментацію та запас
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
NAME SIZE ALLOC FREE CAP FRAG HEALTH
tank 21.8T 18.9T 2.9T 86% 42% ONLINE
Значення: використано 86%, фрагментація зростає. Багато пулів ZFS стають неприємними вище ~85–90%, залежно від навантаження.
Рішення: якщо cap > 85%, розглядайте квоти як вторинні; потрібен план ємності (видалити знімки, додати vdev, перемістити орендарів).
Завдання 3: Визначити найбільші датасети в першу чергу (звичні підозрювані)
cr0x@server:~$ zfs list -o name,used,refer,avail,mountpoint -S used | head -n 10
NAME USED REFER AVAIL MOUNTPOINT
tank/tenants/zenith 6.21T 1.02T 1.48T /srv/tenants/zenith
tank/tenants/acme 3.88T 3.62T 2.11T /srv/tenants/acme
tank/tenants/blue 2.45T 2.40T 1.90T /srv/tenants/blue
tank/backups 1.91T 1.88T 4.05T /tank/backups
tank/tenants 512K 192K 2.90T /srv/tenants
Значення: зверніть увагу на USED vs REFER. У zenith велике USED але мале REFER: знімки або нащадки володіють різницею.
Рішення: якщо USED ≫ REFER, дослідіть знімки/дітей перш ніж кричати на орендаря.
Завдання 4: Подивитися квоти та резервації, застосовані по орендарях
cr0x@server:~$ zfs get -r -o name,property,value,source quota,refquota,reservation,refreservation tank/tenants | head -n 25
NAME PROPERTY VALUE SOURCE
tank/tenants quota none default
tank/tenants refquota none default
tank/tenants reservation none default
tank/tenants refreservation none default
tank/tenants/acme quota 5T local
tank/tenants/acme refquota none default
tank/tenants/acme reservation none default
tank/tenants/acme refreservation none default
tank/tenants/blue quota 3T local
tank/tenants/blue refquota 2500G local
tank/tenants/blue reservation none default
tank/tenants/blue refreservation none default
tank/tenants/zenith quota 7T local
tank/tenants/zenith refquota 1500G local
tank/tenants/zenith reservation 500G local
tank/tenants/zenith refreservation none default
Значення: ви можете швидко аудитуавти управління. Змішана стратегія прийнятна, але має бути свідомою.
Рішення: якщо орендарі спираються на «видалення звільняє простір», віддавайте перевагу refquota плюс контроль знімків.
Якщо ви хочете «все включено», використовуйте quota.
Завдання 5: Встановити квоту для орендаря (жорстка межа) і одразу перевірити
cr0x@server:~$ sudo zfs set quota=2T tank/tenants/acme
cr0x@server:~$ zfs get -o name,property,value tank/tenants/acme quota
NAME PROPERTY VALUE
tank/tenants/acme quota 2T
Значення: записи, що перевищать 2T для цього піддерева датасету, будуть провалюватись помилкою квоти.
Рішення: якщо в acme є дочірні датасети, пам’ятайте, що quota включає їх. Якщо ви хочете обмежити тільки хед-датасет, використовуйте refquota.
Завдання 6: Встановити refquota для «живих даних» і підтвердити поведінку refer
cr0x@server:~$ sudo zfs set refquota=1500G tank/tenants/acme
cr0x@server:~$ zfs get -o name,property,value tank/tenants/acme refquota
NAME PROPERTY VALUE
tank/tenants/acme refquota 1500G
Значення: хед датасету не може перевищити 1.5T referenced. Знімки можуть все ще рости.
Рішення: поєднайте це з політикою утримання/лімітами знімків, інакше ви просто відкладаєте дискусію до моменту, коли пул заповниться.
Завдання 7: Гарантувати запас для критичної служби за допомогою reservation
cr0x@server:~$ sudo zfs set reservation=200G tank/tenants/platform
cr0x@server:~$ zfs get -o name,property,value tank/tenants/platform reservation
NAME PROPERTY VALUE
tank/tenants/platform reservation 200G
Значення: 200G відрізано для цього дерева датасетів. Інші орендарі не можуть його використати.
Рішення: використовуйте резерви помірно. Вони призначені для «необхідних, щоб триматись» датасетів, а не для політичного спокою.
Завдання 8: Виявити зростання використання через знімки на датасеті
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -S used tank/tenants/zenith | head -n 8
NAME USED REFER CREATION
tank/tenants/zenith@daily-2025-12-25 210G 1.02T Thu Dec 25 01:00 2025
tank/tenants/zenith@daily-2025-12-24 198G 1.01T Wed Dec 24 01:00 2025
tank/tenants/zenith@daily-2025-12-23 176G 1.00T Tue Dec 23 01:00 2025
tank/tenants/zenith@daily-2025-12-22 165G 1008G Mon Dec 22 01:00 2025
tank/tenants/zenith@daily-2025-12-21 152G 1004G Sun Dec 21 01:00 2025
tank/tenants/zenith@daily-2025-12-20 141G 1001G Sat Dec 20 01:00 2025
tank/tenants/zenith@daily-2025-12-19 135G 999G Fri Dec 19 01:00 2025
Значення: USED кожного знімка — це унікальні блоки, які тримає цей знімок. Зростання тут часто означає churn (перезапис) у живому датасеті.
Рішення: якщо USED знімків пухне, скоротіть утримання, перемістіть «хвилясті» навантаження або налаштуйте робоче навантаження (наприклад, припиніть перезапис великих файлів).
Завдання 9: Підтвердити, який простір реально доступний орендарю під квотою
cr0x@server:~$ zfs get -o name,avail,used,quota,refquota tank/tenants/acme
NAME AVAIL USED QUOTA REFQUOTA
tank/tenants/acme 320G 1.68T 2T 1500G
Значення: AVAIL відображає більш жорстке обмеження між вільним простором пулу і застосуванням quota/refquota. Тут refquota, ймовірно, лімітує.
Рішення: якщо AVAIL несподівано мале, перевірте, чи refquota нижче за задумане, або чи знімки/нащадки враховуються через quota.
Завдання 10: Знайти, які діти споживають квоту батька
cr0x@server:~$ zfs list -r -o name,used,refer,quota,refquota -S used tank/tenants/acme
NAME USED REFER QUOTA REFQUOTA
tank/tenants/acme 1.68T 1.45T 2T 1500G
tank/tenants/acme/cache 220G 210G none 250G
tank/tenants/acme/db 110G 108G none none
tank/tenants/acme/home 35G 34G none none
Значення: кеш великий і близький до свого refquota. Це часто нормально: кеші мають бути обмежені.
Рішення: якщо кеш не обмежений, встановіть refquota. Якщо база даних спайкова, розгляньте окремі квоти і резерв, щоб підтримувати її.
Завдання 11: Визначити, чи «простір не звільняється» через знімки чи відкриті файли
cr0x@server:~$ sudo zfs destroy -n tank/tenants/zenith@daily-2025-12-19
would destroy tank/tenants/zenith@daily-2025-12-19
would reclaim 135G
Значення: сухий запуск destroy показує, який простір можна звільнити, видаливши знімок. Це золото для прийняття рішення.
Рішення: якщо відновлюваний простір великий і ви в біді, видаліть знімки (починаючи зі старих) за політикою.
Якщо відновлення мале — ви не гонитесь за знімками; шукайте відкриті-але-видалені файли або інші датасети.
Завдання 12: Перевірити відкриті-але-видалені файли, що фіксують простір (класична пастка ENOSPC)
cr0x@server:~$ sudo lsof +L1 /srv/tenants/acme | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 2714 acme 12w REG 0,118 2147483648 0 553211 /srv/tenants/acme/logs/app.log (deleted)
Значення: процес все ще тримає дескриптор на видалений файл. Простір не буде звільнений, поки процес не закриє його.
Рішення: перезапустіть або сигналом змусьте процес перестворити логи. Не видаляйте більше файлів; ви просто створите більше «видалено, але відкрито».
Завдання 13: Підтвердити точки монтування і уникнути «запису поза датасетом, який ви думаєте»
cr0x@server:~$ zfs get -o name,mountpoint,canmount tank/tenants/acme
NAME MOUNTPOINT CANMOUNT
tank/tenants/acme /srv/tenants/acme on
Значення: якщо точки монтування неправильні, орендарі можуть писати в батьківський датасет (без квоти) і обходити обмеження.
Рішення: перевірте точку монтування кожного орендаря і переконайтесь, що батьківські датасети не записувані орендарями.
Завдання 14: Застосувати «нудні запобіжні заходи» на батьківському датасеті
cr0x@server:~$ sudo zfs set readonly=on tank/tenants
cr0x@server:~$ zfs get -o name,readonly tank/tenants
NAME PROPERTY VALUE
tank/tenants readonly on
Значення: орендарі не зможуть випадково писати в батьківський монтуємий простір (якщо він монтується), що змушує записи йти в датасети орендарів.
Рішення: для мультиоренда зробіть батьків незаписуваємими і використовуйте явні дочірні точки монтування. Це запобігає випадковому обходу.
Завдання 15: Моніторити логічний тиск простору по датасету (наближення квоти)
cr0x@server:~$ zfs list -o name,used,quota,refquota,available -r tank/tenants | awk 'NR==1 || $3!="none" || $4!="none"{print}'
NAME USED QUOTA REFQUOTA AVAIL
tank/tenants/acme 1.68T 2T 1500G 320G
tank/tenants/blue 2.45T 3T 2500G 550G
tank/tenants/zenith 6.21T 7T 1500G 790G
Значення: швидкий вигляд керованих датасетів. AVAIL дає оперативний індикатор «чи скоро записи почнуть падати?».
Рішення: налаштуйте оповіщення на %used від квоти і також на cap пулу. Орендар може бути в порядку, поки пул ні.
Завдання 16: Для zvol-орендарів перевірити ризик тонкої провізії
cr0x@server:~$ zfs list -t volume -o name,volsize,used,refer,logicalused,logicalrefer -S logicalused
NAME VOLSIZE USED REFER LOGICALUSED LOGICALREFER
tank/vm/tenant01 800G 120G 120G 640G 640G
tank/vm/tenant02 800G 160G 160G 790G 790G
Значення: logicalused показує, що гість вважає, що використав; USED — що пул реально виділив.
Тонка провізія приховує ризик, поки не перестане.
Рішення: якщо logicalused наближається до volsize у багатьох орендарів, трактуйте це як реальний тиск ємності і плануйте простір відповідно.
Швидкий план діагностики
Коли мультиорендний пул у біді, у вас немає часу на філософську чистоту. Потрібний швидкий шлях до: «що займає що?»
і «це проблема ємності чи продуктивності?»
По-перше: підтвердити, чи маєте надзвичайну ситуацію на рівні пулу
- Ємність пулу:
zpool list -o name,alloc,free,cap,frag. Якщо cap > 90%, припускайте, що все почне працювати дивно. - Стан пулу:
zpool status. Якщо деградований, очікуйте гіршу латентність і повільніші видалення. - Кандидати для негайного звільнення:
zfs list -t snapshot -o name,used -S used.
По-друге: визначити, чи біль — «hit квоти» чи «пул повний»
- Якщо орендарі бачать помилки типу «Disk quota exceeded», ви маєте справу з управлінням на рівні датасету.
- Якщо всі бачать «No space left on device», ви маєте справу з виснаженням пулу або голодуванням через резервації.
- Перевірте
zfs get avail,quota,refquotaна ураженому датасеті і порівняйте з вільним місцем пулу.
По-третє: вирішити знімки vs відкриті файли vs інший датасет
- Знімки: якщо USED ≫ REFER на датасеті, перерахувайте знімки і зробіть dry-run destroy, щоб оцінити відновлення.
- Відкриті-але-видалені файли: запустіть
lsof +L1на монтуванні. Якщо знайдете — перезапустіть винуватця. - Неправильна точка монтування / обхід: перевірте точки монтування і чи записи потрапили в батьківський датасет без квоти.
По-четверте: якщо симптом — продуктивність, не плутайте це з ємністю
- Висока фрагментація + великий cap може виглядати як «проблеми з квотами», бо записи таймаутяться або зависають.
- Вимірюйте IO-тиск за допомогою
zpool iostat -v 1і дивіться на насичені vdev. - Якщо ви близькі до повного, найкращий «тюнінг продуктивності» — звільнити простір.
Три корпоративні міні-історії з полів квот
Міні-історія 1: відмова через хибне припущення
Середня компанія вела спільний пул ZFS для внутрішніх команд: аналітика, CI-системи, кілька веб-проєктів. Вони зробили розумно:
датасет на команду, квоти на кожний датасет. Гордилися. Пул був стабільним. Потім в один понеділок половина CI-завдань впала з ENOSPC.
На черговому виклику думали, що команда перевищила квоту. Але квоти були в нормі. Кожен датасет команди все ще мав запас.
Пул же був на 98%, і ZFS поводилась як система з 98% заповнення: алокація ставала дорогою, і оновлення метаданих сповільнились.
Хибне припущення було тонким: «Якщо у кожної команди є квота, пул не може заповнитись». Квоти не підсумовуються самі по собі у безпеку.
Вони тихо oversubscribe-или, бо квоти ставилися на основі бізнес-очікувань, а не реальної ємності пулу, і утримання не було обмежене.
Справжній винуватець: автоматизовані знімки, що трималися «трохи», а з часом стали «назавжди», бо ніхто не хотів видаляти історію.
Одна команда з високим churn (артефакти, що перезаписуються щодня) викликала ріст знімків. Їхні живі дані залишались під refquota,
але знімки потроху з’їдали пул.
Виправлення не було героїчним. Вони визначили утримання знімків за класами орендарів, додали ліміти на кількість знімків і встановили оповіщення пулу на 80/85/90%.
Також почали щомісячний перегляд датасетів, у яких USED-REFER перевищував поріг. Нудно, послідовно, ефективно.
Міні-історія 2: оптимізація, що відкотилась
Інша компанія пропонувала «пісочниці для розробників» на ZFS. Вони прагнули чудового UX, тому перемкнули багато датасетів орендарів
з quota на refquota. Мета: перестати чути, що видалення файлів не повертає можливість запису через знімки.
Це спрацювало. Скарг стало менше. Команда платформи відсвяткувала тихою задоволеністю. І тоді пул почав заповнюватися швидше, ніж передбачалось,
але ніхто не помічав це одразу, бо дашборди орендарів виглядали добре.
Відкат стався через видимість. З refquota орендарі ніколи не бачили «перевищення ліміту», бо їхні живі дані були обмежені,
а знімки дозволено були рости непомітно. Система змістила відмову від «орендар не може писати» до «пул повний», що гірше у мультиорендному середовищі.
Інцидент закінчився звичним шляхом: видаляли знімки під тиском, реплікаційні затримки стрибнули, і кілька відновлень стали неможливими.
Не катастрофа, але болісно і уникально.
Виправлення полягало в тому, щоб зробити утримання знімків частиною політики квот. Вони впровадили:
ліміти знімків на датасет, розклади знімків по орендарях і звіт, що ранжує орендарів за «snapshot-only простором».
Refquota лишилась — але з обмеженнями і пуловим запасом.
Міні-історія 3: нудна, але правильна практика, що врятувала ситуацію
Регульована організація вела мультиорендний кластер ZFS для команд застосунків. Інженери зберігання були алергічні до сюрпризів,
тому зробили два нецікаві кроки: тримали 20% вільного простору як політику і зарезервували невелику ділянку для платформних датасетів
(логи, auth, моніторингові спули).
Наприкінці кварталу пакетна робота однієї аплікації почала генерувати значно більше вихідних даних, ніж зазвичай. Датасет орендаря досяг квоти.
Аплікація впала голосно — саме те, чого ви хочете. Пул залишився здоровим, моніторинг працював, інші команди не помітили.
On-call отримав чисте сповіщення: «tenant quota exceeded». Не «pool full». Не «IO latency 10x». Не «все горить».
Вони тимчасово збільшили квоту орендаря, але тільки після переміщення старих знімків у холодніший пул і скорочення утримання.
Ключ не в самій квоті. А в комбінації: запас пулу, резервації для критичних сервісів і послідовна звітність.
Інцидент залишився scoped-до-орендаря. Саме це і є мета мультиоренд-інженерії.
Поширені помилки: симптом → корінь → виправлення
1) Симптом: «Я видалив 500GB, але я все ще на квоті»
Корінь: знімки все ще посилаються на видалені блоки; enforcement quota їх рахує.
Виправлення: або видаліть/скіньте знімки, або перейдіть на refquota для цього датасету і контролюйте знімки окремо.
2) Симптом: орендар під квотою, але пул досягає 100%
Корінь: refquota обмежує лише живі дані; знімки, інші датасети і тонка провізія zvol все ще споживають простір пулу.
Виправлення: впровадьте утримання/ліміти знімків, моніторте «snapshot-only» ріст (USED-REFER) і тримайте пуловий запас.
3) Симптом: випадкові ENOSPC хоча zpool list показує вільний простір
Корінь: резервації або спеціальні обмеження алокації означають, що вільний простір недоступний для цього датасету.
Виправлення: аудитуйте reservation/refreservation; зменшіть або видаліть некритичні резерви; забезпечте резерви для критичних датасетів, а не всім підряд.
4) Симптом: орендар якось пише поза квотою
Корінь: записи потрапляють у батьківський датасет (неправильна точка монтування, bind-mount плутанина або права на батьківському монтуванні).
Виправлення: заблокуйте батьківські датасети (readonly=on, canmount=off там, де потрібно), перевірте точки монтування і обмежте права.
5) Симптом: пул не повний, але затримка жахлива і записи повзуть
Корінь: висока фрагментація, дрібний churn, синк-важке навантаження або деградований vdev; керування місткістю тут не допоможе.
Виправлення: тримайте запас, відокремлюйте churn-навантеження в свої vdev/pool, вимірюйте zpool iostat. Розгляньте SLOG/special vdev, де потрібно.
6) Симптом: «простір не звільняється» після видалення великих файлів, знімків не знайдено
Корінь: відкриті-але-видалені файли, що тримаються процесами.
Виправлення: lsof +L1 щоб знайти винуватців; перезапустіть або правильно проведіть ротацію логів.
7) Симптом: реплікація орендаря росте без очевидного живого росту
Корінь: часті перезаписи створюють багато дельт знімків; send-потоки ростуть навіть якщо живі дані стабільні.
Виправлення: зменшіть churn (зміни в аплікації), відрегулюйте частоту знімків або перемістіть орендаря в пул, призначений для churn.
Чеклісти / поетапний план
Крок за кроком: безпечно налаштувати нового орендаря
- Створіть датасет на орендаря (або на орендаря/сервіс, якщо потрібні різні властивості).
- Встановіть точку монтування явно і переконайтесь, що батьківські датасети не записувані орендарями.
- Виберіть модель квот:
- Використовуйте
quota, якщо знімки — «їхня проблема» і ви хочете жорсткий загальний кап. - Використовуйте
refquota, якщо хочете, щоб UX відображав живі дані і ви централізовано керуєте знімками.
- Використовуйте
- Визначте політику знімків: частота і утримання. Покладіть це в код, а не в плутану пам’ять колективу.
- Додайте оповіщення: %used квоти, пороги cap пулу та зростання snapshot-only.
- Задокументуйте режим відмови, який побачить орендар: EDQUOT vs ENOSPC і що їм робити.
Крок за кроком: забезпечити пуловий запас (план «не будіть мене посеред ночі»)
- Виберіть цільовий запас вільного місця (звично 10–20% залежно від навантаження і розташування vdev).
- Оповіщайте зарані на кількох порогах (наприклад, 80/85/90%), а не тільки на 95%, коли вже погано.
- Аудитуйте oversubscription: сума квот vs розмір пулу; приймайте oversubscription лише якщо можете обґрунтувати безпеку.
- Обмежте ріст знімків: ліміти утримання і, де підтримується, ліміти кількості/простору знімків на орендаря.
- Тримайте резерв для платформних датасетів: моніторинг, логи та метадані автентифікації не повинні конкурувати з орендарями під час інциденту.
Крок за кроком: діяти, коли пул майже повний
- Зупиніть кровотечу: знайдіть найшвидше відновлення (зазвичай знімки) і підтвердьте відновлення через
zfs destroy -n. - Якщо орендарі пишуть поза квотами, негайно виправте точки монтування і права.
- Перевірте відкриті-але-видалені файли і перезапустіть винуватців.
- Тимчасово скоротіть утримання знімків, потім відновіть розумну політику з узгодженням.
- Заплануйте розширення ємності або переміщення даних; «ми будемо обережні» — не план ємності.
ЧаПи
1) Використовувати quota чи refquota для орендарів?
Якщо орендарі керують власними знімками або ви хочете обмежити «загальний слід разом з історією», використовуйте quota.
Якщо ви централізовано керуєте знімками і хочете, щоб UX відображав живі дані, використовуйте refquota, але тоді потрібно окремо контролювати ріст знімків.
2) Чи можуть квоти запобігти тому, щоб пул досяг 100%?
Сами по собі — ні. Квоти обмежують датасети. Виснаження пулу все одно може статися через знімки, інші датасети, тонку провізію zvol,
резервації та oversubscription. Потрібна політика запасу пулу і оповіщення.
3) Чому USED так відрізняється від REFER?
REFER — це простір, посиланий хедом датасету (живий вигляд). USED включає блоки, утримувані знімками і нащадками.
Великий розрив зазвичай означає знімки або дочірні датасети.
4) Яку помилку побачать аплікації, коли квота спрацює?
Зазвичай «Disk quota exceeded» (EDQUOT). Якщо ж сам пул не має місця, аплікації побачать «No space left on device» (ENOSPC),
що впливає на всіх і є набагато гіршим для операцій.
5) Якщо я видалю знімки, чи завжди я отримаю простір негайно?
Зазвичай так, але кількість звільненого простору залежить від шарінгу блоків. Використовуйте zfs destroy -n snapshot, щоб оцінити відновлення.
Якщо відновлення мале — знімок не є головною проблемою.
6) Чи є резервації хорошим способом «захистити» кожного орендаря?
Ні. Резерви призначені для захисту критичних сервісів, а не для створення відчуття безпеки у всіх. Надмірне використання резервів може позбавити пул
можливості і спричинити заплутані ENOSPC навіть коли пул декларує вільний простір.
7) Як заборонити орендарям обходити квоти, записуючи в інші місця?
Використовуйте dataset-per-tenant точки монтування, робіть батьківські датасети незаписуваними, перевіряйте mountpoint і canmount,
і переконайтесь, що права не дозволяють записувати в спільні батьки.
8) Чи рахуються знімки проти refquota?
Ні, це саме суть. Проте знімки все равно рахуються проти пулу. Refquota — це обмеження живих даних на датасеті, а не механізм безпеки пулу.
9) Який найпростіший мультиорендний патерн, що працює в продакшні?
Один датасет на орендаря, чітка модель квот (quota або refquota), автоматизовані знімки з жорстким утриманням,
і оповіщення як по лімітам орендарів, так і по запасу пулу. Тримайте це нудним.
Висновок: наступні кроки, що рятують від дзвінка о 2-й ранку
Квоти ZFS — це не примха; це спосіб запобігти тому, щоб один орендар перетворив спільне сховище на спільний інцидент.
Але квоти працюють лише тоді, коли ваша структура датасетів відповідає моделі tenancy, і коли знімки та резервації трактуються як політика першого класу.
Практичні наступні кроки:
- Перевірте ваші межі орендарів: якщо орендарі — це каталоги, сплануйте міграцію до dataset-per-tenant.
- Виберіть семантику квот свідомо:
quotaдля загального сліду,refquotaдля UX живих даних — і реалізуйте відсутні запобіжні заходи. - Впровадьте ліміти утримання знімків і звіт «snapshot-only простір».
- Встановіть пуловий запас вільного місця і оповіщення до 85%; не чекайте 95%, щоб вивчити фізику.
- Резервуйте простір лише для платформних критичних датасетів, щоб ви могли працювати, коли орендарі поводяться неправильно.
Зробіть це добре, і «один користувач вбив пул» стане історією, яку ви розповідаєте новачкам як попередження, а не як квартальну традицію.