Є правило в ZFS, яке звучить як забобон, поки ти не побачиш, як пул кульгає під час тривалого resilver і твій телефон для чергування розігрівається: vdev — це одиниця відмовостійкості, продуктивності та жалю. Ти можеш замінювати диски. Ти можеш налаштовувати datasets. Ти можеш додавати vdev. Але як тільки ти вибереш макет vdev, ти фактично визначив «особистість» пулу на весь його життєвий цикл.
Це не теоретичне попередження з дошки для записів. Це правда з продукційних середовищ, в яких зберігання має «просто працювати», і в хмарах, де воно має «просто бути дешевим». ZFS зробить саме те, що ти йому сказав — блискуче, невблаганно й без жодної симпатії до твоїх помилкових припущень.
Правило, яке ти порушуєш один раз
Правило просте: Ніколи не будуйте пул так, щоб не могли вголос пояснити — як ви будете його розширювати, замінювати і пережити тривалий resilver без того, щоб не ризикувати бізнесом.
Практично це правило зводиться до рішень про vdev:
- Відмовостійкість живе всередині vdev. Пул «настільки відмовостійкий, наскільки відмовостійкий його найменш захищений vdev», і він впаде, якщо будь-який топ-рівневий vdev вийде з ладу.
- Продуктивність агрегується між vdev. Більше vdev зазвичай означає більше IOPS і більше паралелізму; широкі RAIDZ vdev не поводяться як «більше шпинделів = більше швидкості» так, як люди очікують.
- Розширення відбувається додаванням vdev. Ти можеш додавати vdev до пулу. Історично ти не міг їх видаляти (і хоча деякі новіші функції існують у специфічних ситуаціях, плануйте так, ніби видалення не є частиною життєвого циклу).
- Ремонт (resilver) відбувається на рівні vdev і пристрою. Ширші vdev означають більшу кількість дисків у процесі, більше часу під навантаженням і часто більший ризик другої відмови до того, як ти знову станеш у безпеці.
Ось фраза, яку я використовую, коли хтось пропонує «креативний» макет vdev, щоб заощадити на бюджеті: ZFS — це файловий підсистема з думками, і його найсильніша думка — топологія це доля.
Жарт №1 (короткий і по темі): Найшвидший спосіб вивчити проєктування vdev у ZFS — побудувати неправильний пул, бо ZFS подбає, щоб ти його запам’ятав.
Vdev як ментальна модель: топологія важливіша за тюнінг
Якщо ти працював з RAID контролерами, ти звик думати у термінах «RAID group» і «LUN». ZFS об’єднує ці ідеї. Пул будується з vdev; datasets живуть на пулі; ZFS рівномірно розподіляє записи між vdev для балансування простору та продуктивності.
Що таке vdev насправді
vdev — це віртуальний пристрій, що надає сховище пулу. Цей vdev може бути:
- поодиноким диском (без відмовостійкості; не використовуйте в продакшені, якщо ви явно не погоджуєтесь на ризик його втрати),
- mirror (два або більше дисків, копії даних),
- RAIDZ group (одна, дві або три парності: raidz1/2/3),
- special vdev (метадані і/або дрібні блоки на швидшій пам’яті),
- log (SLOG) пристрій для прискорення синхронних записів,
- cache (L2ARC) пристрій.
Лише деякі з них додають до основної ємності зберігання (data vdev і special vdev, залежно від конфігурації). І лише деякі з них потрібні, щоб пул продовжував функціонувати.
Чому vdev — це домен відмов
Якщо ти побудував пул із чотирьох mirror, ти можеш втратити по одному диску в кожному mirror і все одно працювати. Якщо побудував пул з двох raidz2 vdev, ти можеш втратити два диски в одному vdev (не десь у пулі) і все одно працювати. Та деталь «куди припадуть відмови» руйнує показники в таблицях, які виглядають приємно.
Операційно ти не обираєш, де диски відмовлять. Ти обираєш радіус ураження, коли вони відмовлять.
Чому vdev — це одиниця продуктивності
ZFS смужкує записи через vdev, а не через окремі диски. Пул з більшою кількістю vdev зазвичай дає більше IOPS, бо ZFS може видавати більше незалежних IO паралельно. Ось чому «один великий RAIDZ2 з 12 дисками» часто розчаровує у порівнянні з «шістьма mirror-парами», хоча обидва використовують 12 дисків.
RAIDZ vdev може забезпечити хорошу послідовну пропускну здатність, але випадкові IO і затримки поводяться інакше. mirror-відро може часто задовольнити операції читання з будь-якого диска і краще обробляє дрібні випадкові записи без накладних витрат на парність. RAIDZ повинен виконувати паритетні обчислення і схеми read-modify-write для дрібних оновлень. ZFS пом’якшує частину цього за рахунок copy-on-write і груп транзакцій, але з фізикою не посперечаєшся тюнінгом.
Пастка «ти можеш додавати vdev»
Так, ти можеш розширити пул, додавши vdev. Це звучить як свобода. Пастка в тому, що ти не можеш (практично) «перерозподілити» дані так, як люди уявляють це з розподілених систем. ZFS розмістить нові записи на нових vdev, але існуючі дані залишаться там, де вони є, якщо їх не перезаписати. Твій гарячий dataset з минулого року залишиться на минулорічному vdev, якщо ти не мігруєш його активно.
Також, як тільки додано vdev, пул тепер залежить від цього vdev назавжди. Якщо ти додав «тимчасовий» поодинокий диск, щоб вижити тиждень, ти щойно створив постійне одноточкове місце відмови. Той тиждень перетворюється на рік. Він завжди перетворюється на рік.
Цікаві факти та історичний контекст
Інженерія зберігання сповнена фольклору. Ось конкретні контексти, які роблять правила vdev у ZFS менш довільними:
- ZFS був розроблений в Sun з ціллю наскрізної цілісності як ключовою, а не як додаткова опція. Контрольні суми для кожного блоку — це не функція; це світогляд.
- RAIDZ з’явився тому, що традиційний RAID-5/6 мав проблему «write hole» (втрата живлення під час оновлення смуги може лишити парність неконсистентною). Транзакційна модель copy-on-write в ZFS уникає цього класу корупції.
- «1 TB диск», який зробив RAID-5 небезпечним, став «18 TB дисками», що зробило його екзистенційним. З ростом дисків вік відновлення/resilver збільшився, і ймовірність помилки під час відновлення перестала бути дрібницею.
- Scrub у ZFS — не опційна гігієна; це спосіб перетворити мовчазну корупцію на виявлену й виправлену. Без scrub ти ставиш на кону бекапи та удачу проти битових помилок.
- 4K-секторні диски зробили вирівнювання (ashift) постійним рішенням. Невирівняний пул може падавати по продуктивності, що триватиме весь строк життя пулу.
- Раніше люди «виправляли» латентність кешем RAID контролера і потім виявили, що побудували машину для корупції, коли батареї вийшли з ладу. ZFS перемістив кешування в ОС і зробив поведінку при втраті живлення явною.
- OpenZFS став мульти-ОС екосистемою, тому ти бачиш відмінності в дефолтах, інструментах і прапорах функцій між платформами. Правила vdev лишаються вперто послідовними.
- dRAID існує здебільшого для вирішення часу відновлення і ризику на масштабі шляхом розподілу spare-ємності і прискорення заміни/resilver, особливо у великих RAIDZ-подібних групах.
- Special vdev — новіші, але операційно небезпечні при неправильному розумінні: якщо ти ставиш метадані на special vdev і втрачаєш його, пул може бути фактично втрачений, навіть якщо диски з даними в порядку.
Міра, RAIDZ, dRAID і спеціальні vdev: реальні компроміси
Mirrors: нудно, швидко й дорого (в хорошому сенсі)
Mirrors — це стандартна рекомендація для змішаних навантажень, бо вони добре поводяться під випадковістю, відмовляють передбачувано і швидко resilver’яться (особливо з підтримкою послідовного resilver і якщо пул не повністю заповнений). Mirrors також дають більше vdev при тій же кількості дисків, що означає більше паралелізму.
Але mirror «коштують» сирої ємності: two-way mirror зменшують доступний простір приблизно вдвічі. Three-way mirror — це варіант «я більше ніколи про це не хочу говорити» для критичних систем, за рахунок втрати двох третин сирої ємності.
RAIDZ: ефективність ємності з застереженнями по продуктивності
RAIDZ привабливий, коли тобі потрібна ємність і твоє навантаження більше послідовне або орієнтоване на великі блоки. RAIDZ2 часто є базовою опцією для nearline або «важко відновлюваних» пулів. RAIDZ1 ще використовується деінде, але це все більше рішення за ризиком, а не інженерне.
Два великі операційні підводні камені RAIDZ:
- Затримка дрібних випадкових записів, особливо під навантаженням, через те, що оновлення паритету не безкоштовні.
- Довгі resilver’и у міру зростання дисків і неприємна реальність, що під час resilver залишкові диски зазнають стресу, коли пул вже деградований.
Ширина RAIDZ має значення. Дуже широкі RAIDZ vdev можуть виглядати чудово в графіку ємності і потім покарати тебе вікном відновлення і непередбачуваними хвостовими затримками у найгірший момент.
dRAID: відповідь для «великих шасі»
dRAID (distributed RAID) призначений для великих пулів, де класичні часи відновлення RAIDZ стають неприйнятними. Розподіляючи парність і spare-ємність по багатьох дисках, він може скоротити час відновлення після відмови і зменшити неефективність, коли hot spare простоює до лиха.
Це не магічна паличка. Ти все одно маєш розуміти домени відмов, рівень парності та операційний робочий процес заміни. Але якщо ти будуєш великі полиці JBOD і хвилюєшся про час resilver, dRAID вартий серйозної уваги.
Special vdev: множник продуктивності з гострими краями
Special vdev може зберігати метадані (і опційно дрібні блоки) на швидшій пам’яті, наприклад SSD. Правильно зроблені, вони можуть трансформувати продуктивність файлової системи при роботі з метаданими, обходженням директорій і навантаженнях з дрібними файлами. Неправильно зроблені — вони можуть створити новий, менший домен відмов, що виведе весь пул з ладу.
Правило просте: якщо special vdev містить метадані, ставтеся до нього як до повноцінного data vdev з відмовостійкістю. Зробіть mirror. Моніторьте. Замінюйте проактивно.
SLOG і непорозуміння щодо sync записів
SLOG — це не кеш записів. Це окремий лог-пристрій, який використовується тільки для синхронних записів. Якщо твоє навантаження переважно асинхронне (що типово для багатьох додатків), SLOG може нічого не дати. Якщо твоє навантаження синхронне (бази даних, NFS з sync, певні шаблони для VM), правильно підібраний SLOG може драматично знизити затримку — якщо він захищений від втрати живлення і швидкий на низьких чергах.
Жарт №2 (короткий і по темі): Купити SLOG для асинхронного навантаження — все одно що встановити спойлер від гоночного авто на розвізному фургоні — змінює зовнішній вигляд, а не час кола.
Три міні-історії з корпоративного світу
1) Інцидент через хибне припущення: «Ми завжди зможемо видалити це пізніше»
Компанія була в процесі міграції. Старий SAN виводили з експлуатації, і новий ZFS-апарат (whitebox, компетентна конструкція) був збудований, щоб взяти на себе навантаження. Команда зберігання розмістила пул консервативно: mirror-vdev, гарний моніторинг, протестовані відновлення. Потім графік проєкту зсунувся.
До них звернулась продуктова команда з новим dataset, який не влазив. Найпростіше тимчасове рішення здавалося безпечним: додати один великий диск як тимчасовий vdev «лише до завершення постачання». Пул прийняв його. Dataset перетік. Криза минула. Усі повернулись до своїх справ.
Через шість місяців «тимчасовий диск» все ще був там. Він не входив до початкового плану замін. Він не був у таблиці гарантій. І він не був в mirror. Одного ранку він почав видавати помилки читання. ZFS зробив те, що робить: позначив vdev як faulted, і весь пул впав, бо пул не може вижити при втраті будь-якого топ-рівневого vdev.
Постмортем був похмурим не через екзотику відмови, а через її нудність. Хибне припущення було не «диски відмовляють». Воно було «ми легко зможемо скасувати зміни топології пізніше». Вони опинилися у форс-мажорній міграції з-під тиску на будь-яку доступну ємність. Вплив на бізнес був не через померлий диск; а через рішення топології, яке зробило одиночний диск критичною залежністю пулу.
Виправлення було простим, але болючим: перебудувати пул правильно і перемістити дані назад. Урок запам’ятався: не існує «тимчасових» топ-рівневих vdev.
2) Оптимізація, яка обернулась проти: «Один широкий RAIDZ простіший»
Інша організація мала новий аналітичний кластер. Вночі вони виконували великі послідовні скани, але вдень було інтерактивно: дашборди, ad-hoc запити та багато дрібних випадкових IO. Хтось запропонував один широкий RAIDZ2 vdev, щоб максимально використати простір і спростити управління. Менше vdev, менше рухомих частин, один набір паритетних дисків. План виглядав чистим.
Під час першого навантажувального тесту послідовна пропускна здатність була відмінною. Усі святкували. Потім прийшов продакшн. Денні запити почали показувати довгі хвостові стрибки затримок. Не постійна повільність — гірше. Кожні кілька хвилин щось зупинялося настільки, що спрацьовували timeout в додатку. Графіки збереження виглядали «в середньому нормально», саме так проблеми зберігання ховаються в корпоративних панелях.
Корінь проблеми не був таємничим. Це була невідповідність між навантаженням і поведінкою vdev. Широка RAIDZ2 група мала пристойну пропускну здатність, але страждала від змішаних дрібних IO під конкуренцією. У пулу був один data vdev, тож ZFS мав обмежені місця для планування паралельної роботи. Додай помірно заповнений пул, певну фрагментацію з часом — і інтерактивна затримка стала жахливою.
Вони випробували звичні речі: налаштування recordsize, зміни компресії, більше RAM, навіть L2ARC. Покращення були незначні, бо основний обмежувач був структурний. Зрештою вони перебудували як кілька mirror-vdev і проблема зникла. «Оптимізація» обернулась, бо оптимізувала не ту метрику — корисні TB — за рахунок метрики, яку відчували користувачі: p99 затримки.
Тиха мораль: простота — це добре, але пул з одним vdev рідко буває простим у продакшні.
3) Нудна, але правильна практика, яка врятувала день: «Scrub, spare, дисципліна заміни»
Цей кейс ніколи не з’являється в архітектурних слайдах, бо не сексуальний. Підприємство середнього розміру використовувало ZFS для зберігання VM з mirror-vdev, консервативним використанням ємності і розкладом: щомісячні scrubs, алерти на checksum помилки і політику заміни будь-якого диска з повторними помилками, навіть якщо він ще не відмовив повністю.
Одного кварталу партія дисків почала демонструвати періодичні проблеми читання. Не достатньо, щоб викликати негайну відмову, але достатньо, щоб накопичувати checksum помилки. Scrub виявив це рано. Команда не сперечалася з дисками. Вони замінили їх організовано, по одному учаснику mirror, у робочий час, поки пул був здоровий.
Пізніше того року електроінцидент влучив у інший стій. Системи відновилися, але той самий пул, який бачив хиткі диски, був би у небезпечному стані, якби маргінальні диски ще були присутні. Натомість пул повернувся чистим. Жодних деградованих vdev. Жодних аварійних resilver на вже хворих носіях. Реакція на інцидент була майже нудною: перевірити статус, підтвердити розклад scrub, рухатися далі.
Практика, яка їх врятувала, не була хитрим налаштуванням. Це була операційна дисципліна: scrubs, моніторинг і проактивна заміна. У зберіганні нудне — це перевага.
Практичні завдання: команди + інтерпретація
Ось завдання, які я реально виконую в продакшені, коли перевіряю vdev дизайн, діагностую проблеми або прибираю після чогось, що пішло не так. Команди припускають OpenZFS на системі типу Linux; підлаштуйте імена пристроїв і пулів відповідно.
Завдання 1: Перевірити топологію пулу (сировинний тест)
cr0x@server:~$ sudo zpool status -v
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1 ONLINE 0 0 0
ata-SAMSUNG_SSD_2 ONLINE 0 0 0
raidz2-1 ONLINE 0 0 0
ata-WDC_1 ONLINE 0 0 0
ata-WDC_2 ONLINE 0 0 0
ata-WDC_3 ONLINE 0 0 0
ata-WDC_4 ONLINE 0 0 0
ata-WDC_5 ONLINE 0 0 0
ata-WDC_6 ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Визначте топ-рівневі vdev (mirror-0, raidz2-1). Пул виходить з ладу, якщо будь-який топ-рівневий vdev відмовить. Дозволені змішані типи vdev, але вони можуть створити нерівномірну продуктивність і дивну поведінку при розширенні.
Завдання 2: Отримати огляд ємності і фрагментації
cr0x@server:~$ zpool list -o name,size,alloc,free,capacity,health,fragmentation
NAME SIZE ALLOC FREE CAPACITY HEALTH FRAG
tank 100T 72T 28T 72% ONLINE 31%
Інтерпретація: Ємність понад ~80% і зростаюча фрагментація часто спричиняють скарги на затримки, особливо на RAIDZ. Фрагментація сама по собі не зло, але вона корелює з труднощами виділення і IO-ампліфікацією.
Завдання 3: Показати ashift (вирівнювання секторів) для vdev
cr0x@server:~$ sudo zdb -C tank | egrep -i 'vdev|ashift' | head -n 30
vdev_tree:
type: 'root'
id: 0
guid: 123456789
children[0]:
type: 'mirror'
id: 0
ashift: 12
children[1]:
type: 'raidz'
id: 1
ashift: 12
Інтерпретація: ashift=12 означає 4K сектори. ashift фактично постійний для цього vdev. Якщо випадково побудували з ashift=9 на 4K дисках, ви можете бачити постійну write amplification і погану продуктивність.
Завдання 4: Визначити datasets з увімкненим sync (важливість SLOG)
cr0x@server:~$ zfs get -r -o name,property,value sync tank
NAME PROPERTY VALUE
tank sync standard
tank/vm sync always
tank/backups sync disabled
Інтерпретація: Якщо важливі datasets мають sync=always, корисний SLOG може вплинути. Якщо більшість мають standard і ваші програми не роблять sync-записів, SLOG не дасть ефекту.
Завдання 5: Підтвердити вибір recordsize і volblocksize
cr0x@server:~$ zfs get -o name,property,value recordsize tank
NAME PROPERTY VALUE
tank recordsize 128K
cr0x@server:~$ zfs get -o name,property,value volblocksize tank/vm-zvol
NAME PROPERTY VALUE
tank/vm-zvol volblocksize 16K
Інтерпретація: recordsize важливий для фс; volblocksize важливий для zvol і його важко змінити після створення. Невідповідності можуть створювати read-modify-write накладні витрати і погану компресію.
Завдання 6: Спостерігати реальний IO і затримки по vdev
cr0x@server:~$ sudo zpool iostat -v tank 2
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 72T 28T 120 800 15M 110M
mirror-0 1.2T 0.8T 90 500 12M 60M
ata-SAMSUNG_SSD_1 - - 45 250 6M 30M
ata-SAMSUNG_SSD_2 - - 45 250 6M 30M
raidz2-1 70T 27T 30 300 3M 50M
ata-WDC_1 - - 5 50 0.5M 8.5M
...
Інтерпретація: Якщо один vdev насичений або показує непропорційно багато роботи, ви знайшли вузьке місце. Пули не «усереднюють» повільний vdev; вони чекають за ним, коли алокації потрапляють туди.
Завдання 7: Перевірити лічильники помилок і знайти «тихо вмираючий» диск
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1 ONLINE 0 0 0
ata-SAMSUNG_SSD_2 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-WDC_7 ONLINE 0 0 12
ata-WDC_8 ONLINE 0 0 0
errors: No known data errors
Інтерпретація: CKSUM помилки на одному пристрої часто пов’язані з кабелем, контролером або самим диском. «No known data errors» означає, що ZFS виправив те, що міг, але апарат надсилає некоректні дані. Не нормалізуйте checksum помилки.
Завдання 8: Очистити тимчасові помилки після виправлення апаратури (лише після доказів)
cr0x@server:~$ sudo zpool clear tank
Інтерпретація: Очищення помилок ховає історію. Робіть це після заміни кабелю/HBA/диска, коли хочете підтвердити, що проблема зникла. Якщо помилки повернуться — ви все ще в зоні ураження.
Завдання 9: Замінити вийшовший диск у mirror
cr0x@server:~$ sudo zpool offline tank ata-WDC_7
cr0x@server:~$ sudo zpool replace tank ata-WDC_7 /dev/disk/by-id/ata-WDC_NEW_7
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
replacing-0 ONLINE 0 0 0
ata-WDC_7 OFFLINE 0 0 0
ata-WDC_NEW_7 ONLINE 0 0 0 (resilvering)
ata-WDC_8 ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Використовуйте стабільні шляхи пристроїв (by-id). Слідкуйте за resilver. Якщо resilver займає несподівано довго, перевірте заповненість пулу, IO конкуренцію і чи не потрапляєте ви на повільний пристрій.
Завдання 10: Моніторити прогрес resilver і швидкість
cr0x@server:~$ sudo zpool status tank
scan: resilver in progress since Tue Dec 24 10:12:03 2025
3.20T scanned at 540M/s, 1.10T issued at 185M/s, 72T total
1.10T resilvered, 1.53% done, 4 days 10:21:19 to go
Інтерпретація: «Scanned» vs «issued» показує вам, чи є обмеження та IO конкуренція. Якщо «issued» низький — пул занадто зайнятий або vdev/пристрій повільний. Під час resilver ваша маржа відмовостійкості зменшена; ставтесь до цього як до інциденту, поки він не завершиться.
Завдання 11: Запустити scrub і зрозуміти його витрати
cr0x@server:~$ sudo zpool scrub tank
cr0x@server:~$ sudo zpool status tank
scan: scrub in progress since Tue Dec 24 12:00:00 2025
9.80T scanned at 1.1G/s, 2.40T issued at 270M/s, 72T total
0B repaired, 3.33% done, 0 days 18:10:40 to go
Інтерпретація: Scrub споживає IO. Плануйте їх, але не пропускайте. Scrub, який знаходить checksum помилки — це не «невдача»; це рання система попередження, що виконує свою роботу.
Завдання 12: Показати коефіцієнт стискання і підтвердити, що вас не обдурюють
cr0x@server:~$ zfs get -o name,property,value,source compression,compressratio tank
NAME PROPERTY VALUE SOURCE
tank compression zstd local
tank compressratio 1.72x -
Інтерпретація: Стиснення може бути множником ємності і інколи покращувати продуктивність, але воно змінює шаблони записів і використання CPU. Якщо compressratio ~1.00x — ви мало отримуєте.
Завдання 13: Виявити навантаження з інтенсивними метаданими (кандидати на special vdev)
cr0x@server:~$ zfs get -o name,property,value primarycache,secondarycache tank/home
NAME PROPERTY VALUE
tank/home primarycache all
tank/home secondarycache all
cr0x@server:~$ sudo zpool iostat -v tank 2 | head -n 20
Інтерпретація: Якщо ваше навантаження — обходи директорій, дрібні файли і метадані, проблема може бути в затримці на метадані IO. Special vdev може допомогти, але лише за умови відмовостійкого проєктування та моніторингу, як ніби ваша робота залежить від цього (бо так і є).
Завдання 14: Перевірити ARC і чи бракує вам пам’яті
cr0x@server:~$ grep -E 'c_min|c_max|size|hits|misses' /proc/spl/kstat/zfs/arcstats | head
c_min 4 8589934592
c_max 4 68719476736
size 4 53687091200
hits 4 2147483648
misses 4 268435456
Інтерпретація: ARC — ваш перший кеш. Якщо misses високі та затримки погані, можливо ви IO-bound або просто недокешовані. Не поспішайте купувати SSD; перевірте, чи RAM не найпоширеніший і дешевий шлях до покращення продуктивності.
План швидкої діагностики
Це потік «у вас є 15 хвилин до того, як канал інцидентів розгориться». Мета — визначити, чи є вузьке місце в топології, в конкретному пристрої, в поведінці sync, в тиску по ємності або в чомусь вище по стеку.
Перше: Пул здоровий і чи він вже деградований?
cr0x@server:~$ sudo zpool status -x
pool 'tank' is healthy
Якщо не здоровий: припиніть вдавати, що це «проблема продуктивності». Деградовані пули поводяться інакше, resilver’и конкурують з навантаженням, і ризик підвищується.
Друге: Чи один vdev або диск повільний чи видає помилки?
cr0x@server:~$ sudo zpool iostat -v tank 1
cr0x@server:~$ sudo zpool status tank
Що шукати: один пристрій з набагато нижчою пропускною здатністю, багато помилок, або vdev, що бере непропорційно багато операцій. Один поганий диск може потягнути весь RAIDZ vdev у затримки.
Третє: Чи ви обмежені ємністю (місцем або фрагментацією)?
cr0x@server:~$ zpool list -o name,capacity,fragmentation
NAME CAPACITY FRAG
tank 89% 54%
Інтерпретація: Висока ємність плюс висока фрагментація — класичний драйвер затримок алокації. «Виправлення» рідко в середині sysctl. Зазвичай це «додати vdev, звільнити місце або мігрувати».
Четверте: Чи ви платите за sync-записи?
cr0x@server:~$ zfs get -r sync tank | head
cr0x@server:~$ sudo zpool status tank | egrep -i 'logs|log'
Інтерпретація: Якщо sync увімкнений і у вас немає SLOG (або він поганий), затримки можуть стрибати під fsync-важким навантаженням. Якщо sync вимкнений скрізь, не ганяйтеся за SLOG-примарами.
П’яте: Чи ARC робить свою роботу, чи ви постійно читаєте з диска?
cr0x@server:~$ awk '{print $1,$3}' /proc/spl/kstat/zfs/arcstats | egrep 'hits|misses'
hits 2147483648
misses 268435456
Інтерпретація: Зростаючий коефіцієнт misses при навантаженні на читання може вказувати на пам’ятевий тиск або робочу множину, більшу ніж ARC. Це також може означати, що ваш шаблон IO по суті некешований (великі скани).
Шосте: Підтвердіть навантаження і зіставте його з топологією
Ця частина людська, а не команда. Питайте:
- Це здебільшого дрібні випадкові IO (VM, бази даних)? Mirrors зазвичай виграють.
- Це здебільшого великі послідовні IO (бекапи, медіа)? RAIDZ може підійти.
- Чи ми змішуємо навантаження, що інтенсивно працює з метаданими, з масивним зберіганням? Розгляньте special vdev — обережно.
- Чи ми нещодавно додавали новий vdev і очікували, що старі дані перемістяться? Вони не перемістилися.
Поширені помилки: конкретні симптоми та виправлення
Помилка 1: Додавання поодинокого vdev «тимчасово»
Симптом: Пул стає на відстані одного диска від повного простою; пізніше один диск відмовляє і весь пул падає.
Виправлення: Не робіть цього. Якщо вже зробили: перемістіть дані, перебудуйте пул правильно, поверніть дані. Якщо потрібно терміново додати ємність — додайте відмовостійкий vdev (mirror або RAIDZ), який відповідає вашим вимогам до довговічності.
Помилка 2: Побудувати одну величезну RAIDZ і чекати IOPS як у mirror
Симптом: Гарні послідовні бенчмарки, жахливі p95/p99 затримки при змішаному навантаженні; «середня пропускна здатність виглядає добре».
Виправлення: Перепроєктуйте з більшою кількістю vdev (часто mirrors) або кількома RAIDZ vdev помірної ширини. Перестаньте намагатися тюнити навколо невідповідності топології.
Помилка 3: Ігнорувати ashift і вирівнювання секторів
Симптом: Хронічна затримка запису і нижча за очікувану пропускна здатність, особливо на SSD; немає очевидних «помилок».
Виправлення: Перевірте ashift за допомогою zdb -C. Якщо неправильно — реальне виправлення це перебудова/міграція. Ви не можете надійно «виправити» ashift на місці.
Помилка 4: Ставитися до special vdev як до кешу
Симптом: Втрата пулу або серйозний ризик корупції після падіння special vdev; метадані недоступні, хоча диски з даними здорові.
Виправлення: Виконайте mirror (або інший захист) для special vdev. Моніторьте їх як data vdev. Використовуйте SSD з високою витривалістю. Плануйте заміни.
Помилка 5: Купити дешевий SSD для SLOG
Симптом: Затримка синхронних записів не покращується або погіршується; періодичні зависання; пристрій швидко зношується.
Виправлення: Використовуйте пристрій з захистом від втрати живлення і низькою затримкою. Підтвердьте, що ваше навантаження справді використовує sync-записи. Оцініть за затримками на рівні додатку, а не тільки за лічильниками ZFS.
Помилка 6: Працювати «надто гаряче» (пул заповнений)
Симптом: Записи зависають, час scrub/resilver зростає, фрагментація підскакує, і з’являється «випадкова дивність» під навантаженням.
Виправлення: Тримайте запас вільного місця. Додавайте vdev до того, як ви досягнете обриву продуктивності. Якщо вже повно — перемістіть холодні дані або негайно розширюйте.
Помилка 7: Змішувати диски різного розміру і чекати плавних наслідків
Симптом: Mirrors марнують ємність, RAIDZ vdev обмежується найменшим диском, розширення стає заплутаним.
Виправлення: Тримайте членів vdev однорідними, коли можливо. Якщо потрібно змішувати — робіть це свідомо і документуйте, як це впливає на доступний простір і стратегію заміни.
Помилка 8: Плутати «zpool add» з «upgrade»
Симптом: Хтось додає vdev в очікуванні, що існуючий RAIDZ розшириться в ширину; пізніше вони розуміють, що топологія змішана назавжди.
Виправлення: Розширення шляхом додавання vdev — не те саме, що зміна форми vdev. Плануйте ширину vdev наперед; використовуйте додаткові vdev для зростання.
Чеклісти / покроковий план
Покроково: Проєктування пулу, який вам не перестане подобатись
- Запишіть навантаження одним реченням: «зберігання VM з випадковими записами», «ціль бекапів з послідовними записами», «NFS home dirs з метаданним шумом» тощо.
- Визначте толерантність до відмов: скільки дисків може відмовити в одному vdev без простою? Виберіть mirror/raidz2/raidz3 відповідно.
- Виберіть ширину vdev свідомо: не просто «всі диски в одну групу». Віддавайте перевагу більшій кількості vdev перед дуже широкими vdev для IOPS-важких навантажень.
- Вирішіть, як будете розширювати: «додавати ще одну mirror-пару щокварталу», або «додавати ще один raidz2 vdev з 6 дисків» тощо.
- Вирішіть, як будете замінювати диски: іменування by-id, вікна обслуговування, запасні на полиці, документована процедура.
- Встановіть ashift правильно перед створенням пулу. Сприймайте це як постійне рішення.
- Плануйте scrubs і моніторинг: частота scrub, пороги алертів (checksum помилки, повільні resilver), і хто отримує виклик.
- Тримайте запас: визначте поріг ємності, який тригеритиме розширення до того, як продуктивність підскочить вниз.
- Протестуйте поведінку при деградації: симулюйте один диск offline і спостерігайте вплив на додаток; перевірте час resilver при представницькому навантаженні.
Покроково: Перевірки перед тим, як вкласти дані
- Підтвердьте топологію і відмовостійкість.
- Підтвердьте ashift.
- Підтвердьте властивості datasets для передбачуваного використання (recordsize, compression, atime, sync).
- Запустіть представницький навантажувальний тест, що включає змішаний IO і вимірює хвостову затримку.
- Витягніть диск (або поставте його offline) у стенді і спостерігайте resilver та додаток.
Операційний чекліст: коли диск виходить з ладу
- Підтвердьте стан пулу (
zpool status). - Ідентифікуйте точний фізичний диск (мапінг by-id → шасі).
- Перевірте, чи пул вже в процесі scrub/resilver.
- Зменшіть непотрібне навантаження, якщо можливо; resilver під час насичення збільшує вікно ризику.
- Замініть диск, використовуючи стабільні шляхи пристроїв; моніторьте resilver до завершення.
- Після завершення, якщо є сумніви в цілісності, запустіть scrub.
Питання та відповіді
1) Яке насправді «одне правило» про vdev?
Проєктуйте vdev так, ніби ви закріплені з ними назавжди — бо так і є. Ви можете додавати vdev, але не можете легко скасувати погане рішення топ-рівня без міграції даних.
2) Чи можна змішувати mirror і RAIDZ vdev в одному пулі?
Це дозволено і інколи практично (наприклад, додати special vdev або mirror vdev для підвищення IOPS). Але змішані топології можуть створити нерівномірну продуктивність і заплутану поведінку алокацій. Якщо так робите — документуйте чому і як будете розширюватися послідовно.
3) Чому більше vdev зазвичай допомагає продуктивності?
ZFS планує IO по топ-рівневих vdev. Більше vdev означає більше незалежних черг і більше паралелізму. Один широкий vdev може стати одним горлечком для випадкових IO і затримок.
4) Чи варто використовувати RAIDZ1?
Лише якщо ви явно прийняли профіль ризику і вікно відновлення для ваших розмірів дисків і навантаження, і маєте надійні бекапи. Для багатьох сучасних розгортань з великими дисками RAIDZ2 є більш захищеною базовою опцією.
5) Чи додає vdev ребаланс існуючі дані?
Ні. Нові алокації віддаватимуть перевагу новому vdev на основі вільного місця і ваг, але старі блоки зазвичай лишаються там, де вони були. Якщо потрібно перемістити дані — перепишіть їх (send/receive, реплікація або міграція на рівні додатку).
6) Чи потрібен мені SLOG?
Лише якщо ваше навантаження робить синхронні записи і вам важлива латентність sync. Підтвердіть це за властивістю dataset sync і поведінкою додатку. Якщо потрібен — використовуйте пристрій з захистом від втрати живлення.
7) Чи безпечні special vdev?
Вони безпечні, якщо розглядати їх як критичні, відмовостійкі компоненти. Вони небезпечні, якщо ставитись до них як до кешу, який можна втратити. Якщо метадані там — втрата може бути катастрофічною.
8) Який розумний розклад scrub?
Зазвичай — щомісячно для багатьох пулів, іноді частіше для високоризикових середовищ. Правильна відповідь залежить від ємності, навантаження і того, як швидко ви хочете виявляти латентні помилки. Неправильна відповідь — «ніколи».
9) Чому мій resilver займає вічність?
Поширені причини: висока заповненість пулу, велике продакшн-навантаження, повільні або маргінальні диски, проблеми контролера або дуже широкий RAIDZ vdev. Перевірте zpool status (issued vs scanned), zpool iostat -v і лічильники апаратних помилок.
10) Яка найбезпечніша стратегія розширення?
Додавайте vdev, що відповідають вашому існуючому профілю відмовостійкості і продуктивності, тримайте ширину vdev послідовною і розширюйте до того, як ви досягнете критичної заповненості. Якщо потрібно змінити профіль — плануйте міграцію, а не імпровізовану латочку.
Висновок
Проєктування vdev у ZFS — це не темне мистецтво. Це просто невблаганно. Файлова система охоче прийме ваш «тимчасовий» диск, ваш занадто широкий RAIDZ, ваш недозахищений special vdev і ваше невірно вирівняне ashift — а потім буде виконувати ці рішення в продакшені на повному навантаженні, о 3 ранку.
Якщо ви візьмете з цього одне: vdev — це не конфігураційна дрібниця; це контракт, який ви підписуєте з вашим майбутнім «я». Підписуйте те, з чим можете жити: відмовостійкість, яку зможете пояснити; продуктивність, яку зможете передбачити; розширення, яке зможете виконати; і нудні операційні практики, які триматимуть вас подалі від дзвінків інцидентів, коли сховище технічно «в порядку», але бізнес горить.