Основи ZFS iostat: перетворення цифр на вузьке місце

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

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

zpool iostat — це місце, куди відчуття відправляються вмирати. Це також місце, де добрі інженери іноді застрягають,
бо вивід виглядає простим і повним чисел, які здаються такими, що підтверджують будь-яку вашу ранню теорію.
Ось як перетворити ті числа на вузьке місце, яке можна назвати, виміряти і виправити.

Що таке ZFS iostat (і чим він не є)

ZFS дає кілька «лінз» iostat. Та, яку мають на увазі більшість людей, — це zpool iostat, який показує
пропускну здатність і швидкість I/O по пулу та по vdev. Залежно від прапорців, він також може показувати затримку, розмір черги та
розподіли по пристроях. Це погляд ZFS на роботу, а не погляд блочного пристрою і не обов’язково те, що
ваш додаток вважав відправленим.

Чим він не є: це не повний профайлер продуктивності, він не скаже «базі даних не вистачає індексу», і не розділить
«погане навантаження» від «поганого дизайну сховища» сам по собі. Але він скаже, куди пул витрачає час:
який vdev, який пристрій, читання проти записів, пропускна здатність проти IOPS проти затримки, і чи ви заблоковані на
найповільнішому диску або на власних конфігураційних рішеннях.

Корисне правило: якщо ви не можете пояснити інцидент у термінах кількох стабільних метрик (IOPS, пропускна здатність, затримка),
ви ще не завершили відладку; ви тільки почали складати оповідь.

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

  • ZFS почався в Sun на початку 2000-х, щоб вирішити складність файлової системи та менеджера томів, об’єднавши їх в одну систему зі сквозними контрольними сумами.
  • Ідея «пулу зберігання» була радикальною в світі розділів і таблиць LUN; вона змінила підхід оперативних команд до управління ємністю.
  • vdev — це одиниця продуктивності: ZFS нано-розподіляє дані між vdev, а не між окремими дисками так, як багато хто помилково припускає.
  • Математика парності RAIDZ — ось чому малі випадкові записи болючіші на RAIDZ, ніж на дзеркалах; «збільшення запису» — не маркетинг, а арифметика.
  • OpenZFS розійшовся й зійшовся: кілька платформ продовжували розвиток ZFS після Oracle, і функції разом з інструментами розвивалися нерівномірно по OS.
  • SLOG став важливим, бо синхронні записи — це контракт; ZIL існує, щоб його задовольнити, а iostat — один з найшвидших способів побачити, чи цей контракт дорогий.
  • Спеціальні vdev були введені для обробки метаданих/малих блоків на швидшому носії; це продуктивне золото і операційний борг одночасно.
  • Боротьба з ashift відбувалася тому, що диски «брехали» (або їх неправильно розуміли) про фізичні розміри секторів; неправильний ashift може назавжди вплинути на продуктивність.
  • «L2ARC вирішує все» — повторювана міфологема з часів перших адміністраторів кешування; він не виправляє затримку записів і може вкрасти пам’ять, яка була потрібна в інших місцях.

Путівник полем: як читати zpool iostat серйозно

Почніть з виводу за замовчуванням, але на цьому не зупиняйтеся

Стандартний вивід zpool iostat — це м’який вступ: операції читання/запису та пропускна здатність по пулу і, опційно, по vdev.
Він підходить, щоб зрозуміти «чи він зайнятий?», але не підходить для питання «чому повільно?», бо вузькі місця зазвичай
про розподіл затримки та один повільний шлях, а не про агреговану пропускну здатність.

Що насправді означають колонки

Імена колонок трохи відрізняються по платформах і версіях OpenZFS, але концепції стабільні:

  • r/s, w/s: операції читання/запису в секунду, які ZFS бачить на цьому шарі (пул/vdev/пристрій).
  • rkB/s, wkB/s: пропускна здатність читання/запису в кілобайтах за секунду.
  • await (коли доступно): середній час I/O, що витрачається на очікування + час обслуговування (черга + пристрій).
  • r_await, w_await: та сама ідея, розділена по читаннях/записах (дуже корисно коли синхронні записи кусають).
  • sqd (інколи показується): середня глибина черги. Висока черга разом з ростом затримки — класичний сигнал «пристрій насичено».
  • util не є зазвичай колонкою ZFS як у Linux iostat; не імпортуйте семантику Linux автоматично. ZFS має свою власну інструментацію.

Речення, яке економить години

Продуктивність ZFS домінує найповільніший vdev, задіяний в операції, і zpool iostat — найшвидший спосіб визначити, який з них поводиться як найповільніший учасник групового проекту.

Практична модель: куди іде час

Коли додаток каже «запиши це», ZFS перетворює це на танець: транзакційні групи (TXG), copy-on-write (COW),
контрольні суми, опційна компресія, виділення metaslab, і лише потім фактичні I/O на пристрої. Читання — це інша історія:
попадання в ARC, попадання в L2ARC, префетч, реконструкція RAIDZ і, нарешті, диски.

zpool iostat не покаже вам час коміту TXG прямо, але він покаже симптоми:
сплески записів, піки затримки, один vdev, що робить більше роботи ніж інші, або пристрій SLOG, який приймає всю
навантаження синхронних записів.

Якщо потрібна швидка мапа від симптому до «який шар болить», ось відверта версія:

  • Високий w_await, низька пропускна здатність: малі записи, синхронні записи, накладні витрати парності RAIDZ або затримка пристрою.
  • Високий rkB/s, помірний r/s, зростаючий r_await: великі читання, що насичують пропускну здатність.
  • Високий r/s, низький rkB/s, високий r_await: випадкові читання, погане кешування або конкуренція за метадані.
  • Один топ-рівневий vdev на максимумі: нерівномірне розподілення, один vdev менший/заповнений або фактичний проблемний пристрій.

Одна цитата, яку варто тримати на стіні:
Надія — не стратегія. — Jim Lovell

Практичні завдання: команди, виводи, рішення (12+)

Це те, що ви реально робите о 02:17, коли хтось каже «сховище повільне». Кожне завдання має: команду,
що ви дивитесь, і рішення, яке воно підтримає. Виконуйте їх по порядку, якщо ви новачок; перескакуйте, якщо маєте підозру і сліди від попередніх інцидентів.

Завдання 1: Отримайте рухливу картинку, а не знімок

cr0x@server:~$ zpool iostat -v 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    420    310   42.1M  18.7M
  mirror    1.56T  1.44T    210    155   21.0M   9.4M
    sda         -      -    110     78   10.4M   4.9M
    sdb         -      -    100     77   10.6M   4.5M
  mirror    1.56T  1.44T    210    155   21.1M   9.3M
    sdc         -      -    105     77   10.5M   4.6M
    sdd         -      -    105     78   10.6M   4.7M

Значення: Ви отримуєте п’ять односекундних зразків з деталізацією vdev та дисків. Шукайте дисбаланс
(один диск або дзеркало робить значно більше), і форму навантаження: велика пропускна здатність проти великої кількості операцій.

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

Завдання 2: Увімкніть перегляд затримки (якщо підтримується)

cr0x@server:~$ zpool iostat -v -l 1 5
                              capacity     operations     bandwidth    total_wait
pool                        alloc   free   read  write   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----  -----  -----
tank                        3.12T  2.88T    430    320   43.2M  19.1M    4ms   28ms
  mirror                    1.56T  1.44T    215    160   21.5M   9.6M    3ms   26ms
    sda                         -      -    112     81   10.7M   5.0M    3ms   25ms
    sdb                         -      -    103     79   10.8M   4.6M    3ms   28ms
  mirror                    1.56T  1.44T    215    160   21.7M   9.5M    4ms   31ms
    sdc                         -      -    109     80   10.8M   4.8M    4ms   32ms
    sdd                         -      -    106     80   10.9M   4.7M    4ms   30ms

Значення: «total_wait» (або подібне) — це ваш швидкий і простий сигнал затримки.
Тут записи значно повільніші за читання, і вони повільні скрізь, а не лише на одному диску.

Рішення: Якщо час очікування записів високий по всіх vdev, запитайте: синхронні записи? парність RAIDZ?
повільний SLOG? TXG-стагнація? Якщо тільки один vdev/диск, ставтеся до цього як до проблеми апаратури/шляху, поки не доведено інше.

Завдання 3: Звузьте до підозрілих пулів, якщо у вас кілька пулів

cr0x@server:~$ zpool iostat -v tank 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    440    330   44.1M  19.8M
  mirror    1.56T  1.44T    220    165   22.0M   9.9M
    sda         -      -    112     83   10.8M   5.1M
    sdb         -      -    108     82   11.2M   4.8M
  mirror    1.56T  1.44T    220    165   22.1M   9.9M
    sdc         -      -    110     82   11.0M   4.9M
    sdd         -      -    110     83   11.1M   5.0M

Значення: Уникайте шуму з різних пулів. Особливо на машинах з кількома орендарями, ваш «повільний додаток»
може бути не єдиним джерелом I/O.

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

Завдання 4: Підтвердіть стан пулу перед тим, як переслідувати привиди продуктивності

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 06:41:12 with 0 errors on Mon Dec 23 03:12:01 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Значення: Якщо ви бачите зростаючі READ/WRITE/CKSUM помилки, «проблеми» продуктивності можуть бути через
повторні спроби, ремапінг і страждання системи. ZFS збереже цілісність даних, а ваша затримка стане гострішою.

Рішення: Будь-які ненульові, що зростають лічильники помилок: припиніть оптимізувати.
Почніть замінювати апаратуру, перевіряти кабелі/HBA і переглядати SMART-дані.

Завдання 5: Перевірте, чи scrub або resilver не «з’їдає» ваші ресурси

cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub in progress since Tue Dec 24 11:02:09 2025
        1.43T scanned at 1.21G/s, 820G issued at 694M/s, 3.12T total
        0B repaired, 26.18% done, 00:52:14 to go
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Значення: Scrub — це легітимний споживач I/O. Він також хороша гігієна.
Але під час піку він може проштовхнути вже щільну затримку через край.

Рішення: Якщо система чутлива до затримок, плануйте scrubs поза піковими годинами і/або налаштуйте пріоритет scrub.
Якщо ви не можете терпіти scrubs — ви не можете терпіти експлуатацію сховища.

Завдання 6: Дізнайтеся, чи ви обмежені IOPS чи пропускною здатністю

cr0x@server:~$ zpool iostat -v 2 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T   4200    180   32.1M   6.2M
  mirror    1.56T  1.44T   2100     90   16.0M   3.1M
    sda         -      -   1050     45    8.0M   1.6M
    sdb         -      -   1050     45    8.0M   1.5M
  mirror    1.56T  1.44T   2100     90   16.1M   3.1M
    sdc         -      -   1050     45    8.1M   1.6M
    sdd         -      -   1050     45    8.0M   1.5M

Значення: 4200 читань/сек, але лише 32 MB/s: це малі блоки випадкового I/O. Якщо затримка висока,
додавання більше шпинделів (більше vdev) допоможе більше ніж «швидші диски» самі по собі.

Рішення: Робочі навантаження, обмежені IOPS, хочуть дзеркал, більше vdev і адекватних recordsize; навантаження, що потребують пропускної здатності, хочуть послідовного розташування, менше парних штрафів та часто більших блоків.

Завдання 7: Перевірте, чи синхронні записи — лиходій

cr0x@server:~$ zfs get -o name,property,value,source sync tank/db
NAME     PROPERTY  VALUE  SOURCE
tank/db  sync      standard  local

Значення: sync=standard означає, що синхронні записи виконуються, коли додатки запитують їх.
Бази даних часто це роблять.

Рішення: Якщо затримка записів жахлива і ви бачите багато синхронних записів, ваш SLOG (якщо є) має бути
швидким і з захистом від втрати живлення. Якщо ви «виправляєте» це, встановивши sync=disabled, будьте чесні і назвіть це
«вибором втрати даних як функції».

Завдання 8: Перевірте наявність SLOG та чи він справді використовується

cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
        logs
          nvme0n1   ONLINE       0     0     0

errors: No known data errors

Значення: Є окремий лог-пристрій. Це SLOG (separate intent log).
Він прискорює лише синхронні записи, а не звичайні асинхронні записи.

Рішення: Якщо у вас немає синхронно-важких навантажень, SLOG не допоможе і може ускладнити домени відмов.
Якщо є — SLOG має бути з низькою затримкою і з захистом від втрати живлення.

Завдання 9: Слідкуйте за лог-пристроєм під навантаженням (чи піки на ньому?)

cr0x@server:~$ zpool iostat -v 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    120   1800    3.1M  22.4M
  mirror    1.56T  1.44T     60    900    1.5M  11.1M
    sda         -      -     30    450  760K     5.5M
    sdb         -      -     30    450  740K     5.6M
  mirror    1.56T  1.44T     60    900    1.6M  11.3M
    sdc         -      -     30    450  780K     5.7M
    sdd         -      -     30    450  820K     5.6M
logs
  nvme0n1       -      -      0   5200      0  41.6M

Значення: Великі операції запису на nvme0n1 під «logs» сильно вказують, що синхронні записи
фіксуються в SLOG. Якщо пул має високе write wait і лог-пристрій показує багато операцій, у вас навантаження, що домінують синхронні записи.

Рішення: Якщо операції лог-пристрою високі і затримка велика — оновіть/замініть SLOG, перевірте PLP, і переконайтеся, що ви не використовуєте дешевий споживчий NVMe, який «перетворюється на гарбуза» при стійких синхронних записах.

Завдання 10: Перевірте recordsize датасету та невідповідність робочого навантаження

cr0x@server:~$ zfs get -o name,property,value,source recordsize tank/db
NAME     PROPERTY    VALUE  SOURCE
tank/db  recordsize  128K   default

Значення: Багато баз даних віддають перевагу меншим блокам (наприклад, 8K–16K), щоб не читати/писати зайвих даних.
128K recordsize все ще може працювати, але для випадкових навантажень воно може посилювати I/O.

Рішення: Якщо ваш iostat показує високі IOPS з малою пропускною здатністю (малий випадковий I/O), розгляньте встановлення
recordsize ближче до розміру сторінки БД (після підтвердження рекомендацій конкретної БД).

Завдання 11: Перевірте компресію (вона може зменшити I/O або витратити CPU)

cr0x@server:~$ zfs get -o name,property,value,source compression tank/db
NAME     PROPERTY     VALUE   SOURCE
tank/db  compression  lz4     local

Значення: lz4 зазвичай виграш: менше даних записано, менше читається з диска, часто швидше.
Але на системах з навантаженим CPU або вже стиснених даних це може бути нейтрально або трохи гірше.

Рішення: Якщо iostat показує насичення диска, а CPU має вільні ресурси, компресія — ваш друг.
Якщо CPU завантажений, а диск простає, не «оптимізуйте сховище» більшою компресією.

Завдання 12: Перевірте ashift (вирівнювання), бо це назавжди

cr0x@server:~$ zdb -C tank | grep -E 'ashift|vdev_tree' -n | head
118:        vdev_tree:
134:            ashift: 12

Значення: ashift=12 означає 4K сектори. Якщо пул створено з ashift=9 на 4K дисках,
малі записи можуть перетворитися на кошмари read-modify-write.

Рішення: Неправильний ashift — це помилка, що вимагає перебирання. Якщо він неправильний і продуктивність важлива, плануйте міграцію.
Немає магічної «фішки», що безпечно перепише геометрію пулу на місці.

Завдання 13: Виявіть нерівномірне заповнення vdev (упередженість розподілу)

cr0x@server:~$ zpool list -v tank
NAME         SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH
tank        6.00T  3.12T  2.88T        -         -    19%    52%  1.00x  ONLINE
  mirror    3.00T  2.40T   600G        -         -    28%    80%      -  ONLINE
  mirror    3.00T   720G  2.30T        -         -     8%    24%      -  ONLINE

Значення: Одне дзеркало заповнене на 80% і більш фрагментоване; інше — на 24%. ZFS намагається збалансувати,
але історія пулу, розширення і поведінка metaslab можуть призвести до перекосу. Перекіс може зробити один vdev «гарячою точкою».

Рішення: Якщо iostat показує, що заповнений vdev робить більше роботи або має більшу затримку, стратегія ребалансування важлива:
розгляньте додавання vdev раніше, тримайте пули нижче агресивних порогів заповнення і уникайте «додати пізніше» як стратегії продуктивності.

Завдання 14: Скорелюйте ZFS iostat з OS-метриками пристроїв

cr0x@server:~$ iostat -x 1 3
Linux 6.6.0 (server) 	12/25/2025 	_x86_64_	(32 CPU)

Device            r/s     w/s   rkB/s   wkB/s  await  aqu-sz  %util
sda             110.2    81.4  10960.0  5092.0   4.2    0.8   42.1
sdb             105.9    79.6  11010.0  4780.0   4.0    0.7   41.7
sdc             109.8    80.2  11030.0  4960.0   4.6    1.0   44.9
sdd             108.8    80.7  11080.0  5030.0   4.4    0.9   44.1
nvme0n1           0.0  5200.3      0.0 41600.0   0.3    0.6   62.0

Значення: ZFS бачить логічну роботу; ОС бачить фактичні черги пристроїв і їх завантаження.
Якщо ZFS каже, що диск зайнятий, а ОС каже, що він простягає — можливо, ви обмежені вище пристрою (локи, CPU, TXG).
Якщо ОС показує високий await і високий %util — пристрій дійсно обмежує.

Рішення: Використовуйте OS iostat, щоб підтвердити, чи проблема в «плануванні ZFS», чи в «пристрої, який не встигає».
Це рятує від заміни дисків, коли потрібно налаштувати синхронні записи, або навпаки.

Завдання 15: Перевірте тиск на ARC та запас пам’яті (бо читання брешуть)

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:10:01  8420  1120     13   620   55   410   36    90    8   58G    64G
12:10:02  9010  1460     16   780   53   590   40    90    6   58G    64G
12:10:03  8770  1310     14   700   53   520   40    90    7   58G    64G

Значення: Рівень пропусків 13–16% може бути нормальним або жахливим залежно від навантаження.
Якщо пропуски стрибають і диски загоряються в zpool iostat, «затримка сховища» може бути просто тим, що кеш працює як задумано.

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

Жарт №1: Якщо довго дивитись на iostat, перші не моргають числа. Можете моргнути ви.

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

Коли потрібно швидко знайти вузьке місце, виконайте це в порядку. Мета не ідеальне розуміння; мета — правильне перше виправлення
і чіткий таймлайн інциденту.

По-перше: чи це проблема стану, яка маскується під проблему продуктивності?

  • Запустіть zpool status -v. Шукайте помилки, деградування vdev, повільний resilver або пристрій, що «флапає».
  • Запустіть метрики на рівні ОС (iostat -x), щоб побачити, чи один пристрій страждає.

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

По-друге: визначте обсяг і форму I/O

  • zpool iostat -v 1 5: який пул, який vdev, який пристрій найгарячіший?
  • Подивіться на IOPS проти пропускної здатності: багато операцій з малою пропускною здатністю кричить про випадковий/малий I/O.
  • Якщо доступно, додайте -l для підказок по wait/latency: читання в порядку, а от записи жахливі?

По-третє: вирішіть, чи вузьке місце — синхронні записи, парність RAIDZ чи заповненість/фрагментація

  • Перевірте zfs get sync на уражених датасетах.
  • Перевірте на SLOG у zpool status, потім спостерігайте статистику лог-vdev в zpool iostat -v.
  • Перевірте zpool list -v на нерівномірне заповнення vdev і підказки щодо фрагментації.

По-четверте: валідуйте одним перехресним метриком

  • Використайте iostat -x, щоб підтвердити фактичну поведінку черги/await на пристрої.
  • Використайте arcstat (або еквівалент платформи) щоб виключити або підтвердити кешування як причину завантаження дисків.

Наприкінці цього плейбуку ви маєте змогу чесно сказати одну з цих фраз:
«Ми насичені по випадкових читаннях IOPS», «Синхронні записи обмежені лог-пристроєм», «Один vdev перевантажений»,
«Ми платимо податок фрагментації/заповнення», або «Пристрій/шлях відмовляє і повторює спроби».

Три корпоратні міні-історії з передової

Інцидент через неправильне припущення: «Це дзеркально, отже швидко»

Середня SaaS-компанія мігрувала клієнтський PostgreSQL-кластер на новий сервер зі сховищем під ZFS.
Пул був збудований з кількох дзеркал. Чисто, просто, заспокійливо. Усі спали краще.

Через тижні під час пікового трафіку почали з’являтися сплески затримки. Графіки були бісучі: CPU не завантажений, мережа в нормі.
On-call запустив zpool iostat -v і побачив, що одне дзеркало показує помітно вищий write wait, ніж інше.
Припущення було миттєвим: «ZFS має балансувати між дзеркалами; дзеркало не може бути вузьким місцем, воно резервне.»
Вони почали шукати в інших місцях.

Справжня проблема була в нерівномірному заповненні vdev, спричиненому попереднім робочим процесом розширення. Одне дзеркало було значно заповнене й більш фрагментоване.
Це дзеркало стало «гарячою точкою» алокації — воно виконувало більше роботи, ставало повільнішим, і пул здавався повільнішим.
Вивід zpool list -v все це намагався сказати увесь час.

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

Оптимізація, що відкотилася: «Вимкнути sync, відправити»

Команда платформи даних мала канал ingesiton, що писав багато дрібних транзакцій. Під час тесту навантаження затримка записів здавалась поганою.
Хтось знайшов zfs set sync=disabled і швидко прогнав бенчмарк. Затримка впала. Пропускна здатність зросла.
Запит на зміну було готово.

У продакшені перші тижні були чудові. Потім подія з харчуванням в стійці. Сервери перезавантажились. Пайплайн перезапустився чисто.
І через кілька годин з’явилася тиха неконсистентність даних: downstream завдання побачили дублювання і зниклі записи. Команда витратила дні,
«відлагоджуючи Kafka», потім «відлагоджуючи базу даних», і врешті-решт простежила це до підтверджених записів, які ніколи не дійшли на диск.

Ретроспектива була незручною, бо ніхто «не зробив неправильно» в своїй локальній рамці.
Бенчмарк був реальний. Поліпшення було реальним. Навантаження було реальним.
Помилка була в тому, що контракт на міцність даних трактували як налаштування.

Виправлення не було «ніколи чіпати sync». Це було «побудувати правильний шлях запису». Вони додали належний SLOG-пристрій із захистом від втрати живлення,
перевірили його під навантаженням через статистику zpool iostat для logs, і залишили sync=standard.
Продуктивність покращилася, і всі стали спати краще.

Нудна, але правильна практика, що врятувала день: базове зняття показників

Внутрішня платформа використала ZFS на флоті хостів віртуалізації. У них була політика, яка нікого не заводила:
захоплювати 60-секундний зразок zpool iostat -v -l 1 під час «звичних» годин кожного тижня і зберігати його з метаданими хоста.
Без панелей, без пафосу — просто текстові файли з часовими мітками. Те, що ви випадково видаляєте під час весняного прибирання.

Одного дня надійшли скарги на затримки VM. Хости зовні виглядали «в порядку». Пул не був заповнений.
Не було помилок. Та в UI гіпервізора були періодичні затримки.

On-call порівняв поточний зразок iostat з базовим і побачив різницю відразу: write wait подвоївся при тих же IOPS.
Це було не «більше навантаження». Це було «така ж навантаження, але повільніший час обслуговування».
Це звузило пошук до «щось змінилося в I/O-шляху», а не «хтось додав орендарів».

Винуватею виявився апдейт прошивки HBA, який змінив поведінку черг під змішаним навантаженням читань/записів.
Вони відкотили прошивку на постраждалих хостах, підтвердили, що затримка повернулась до бази, і потім працювали з вендором над виправленням.
Нудні базові знімки врятували їх від тижня переслідування привидів і кидання відповідальності.

Жарт №2: Затримка сховища — як корпоративні погодження: ніхто не помічає, поки раптом не стає проблемою для всіх.

Поширені помилки: симптом → корінна причина → виправлення

1) «IOPS пулу високі, отже диски повільні»

  • Симптом: Високий r/s або w/s в zpool iostat; затримка додатка зростає.
  • Корінна причина: Навантаження змінилося на менші I/O або більш випадкове; агрегована пропускна здатність може бути помірною.
  • Виправлення: Перевірте розмір I/O (IOPS проти MB/s), налаштуйте recordsize датасету, додайте vdev (більше шпинделів/дзеркал), або перемістіть «гарячі» дані на SSD/спеціальний vdev.

2) «Один диск у дзеркалі робить менше, отже все гаразд»

  • Симптом: В дзеркалі один диск показує менше операцій і/або вищий wait.
  • Корінна причина: Пристрій повільний, виконує повтори, має проблему шляху або контролер обмежує його.
  • Виправлення: Перевірте лічильники zpool status, журнали ОС, SMART, перепідключіть/замініть кабелі, перемістіть диск на інший порт/HBA, замініть пристрій при потребі.

3) «Ми додали SLOG; записи все ще повільні; SLOG марний»

  • Симптом: SLOG є; затримка записів залишається високою.
  • Корінна причина: Навантаження не синхронне, або SLOG повільний/споживчого класу, або sync виключений/увімкнений неочікувано.
  • Виправлення: Підтвердіть поведінку sync (zfs get sync), спостерігайте активність «logs» vdev в zpool iostat -v, використовуйте низьколатентний пристрій з PLP, і не очікуйте, що SLOG прискорює асинхронні записи.

4) «RAIDZ має бути в порядку; це як апаратний RAID»

  • Симптом: Малі випадкові записи мають високий wait; пропускна здатність низька; CPU в нормі.
  • Корінна причина: Накладні витрати парності RAIDZ і поведінка read-modify-write на малих оновленнях.
  • Виправлення: Використовуйте дзеркала для навантажень, чутливих до IOPS, або змініть розміри блоків/робоче навантаження, або додайте більше vdev, або ізолюйте навантаження випадкових записів в дзеркальні/SSD пули.

5) «Затримка висока, отже пул перевантажений»

  • Симптом: Високий total_wait; додаток гальмує; але %util пристрою не високий.
  • Корінна причина: Вузьке місце може бути вище дисків: TXG sync, конкуренція CPU, тиск пам’яті або конкурентні локи.
  • Виправлення: Перевірте OS iostat -x, спостерігайте поведінку ARC, перевірте CPU steal/interrupts, і шукайте TXG-стагнацію через системні логи і ZFS-налаштування (платформно-залежні).

6) «Продуктивність погіршилась після включення special vdev; ZFS зламався»

  • Симптом: Читання стали імпульсними; операції з метаданими гальмують.
  • Корінна причина: Special vdev замалий, насичений або на пристрої з поганою консистентністю затримки; також концентрація метаданих збільшує залежність від цього пристрою.
  • Виправлення: Переконайтеся, що special vdev має достатню ємність і редундантність, моніторьте його як критичний шар, і не використовуйте один дешевий пристрій як метадані-опору.

7) «Ми лише на 80% заповнені; ємність не може впливати на продуктивність»

  • Симптом: Затримка поступово зростає при заповненні пулу; розподіл стає нерівномірним; фрагментація зростає.
  • Корінна причина: Вільний простір стає важче виділяти ефективно; росте фрагментація metaslab; деякі vdev стають гарячішими.
  • Виправлення: Тримайте пули комфортно нижче «високих» меж для вашого навантаження, додавайте vdev раніше і уникайте розширень в останній момент під час піку навантаження.

Чеклісти / покроковий план

Покроково: від «повільно» до «вузьке місце» за 15 хвилин

  1. Підтвердіть пул і датасет, що задіяні.
    Перевірте точки монтування/томи і зіставте їх з пулами. Не діагностуйте на невірній машині.
  2. Спочатку перевірте стан.
    Запустіть zpool status -v. Є помилки, деградовані пристрої, resilver або scrubs? Трактуйте це як пріоритет.
  3. Зніміть короткий iostat.
    Запустіть zpool iostat -v 1 10-l, якщо доступно). Збережіть його. Інциденти без артефактів стають аргументами.
  4. Класифікуйте форму навантаження.
    IOPS-важке (високі операції, низький MB/s) проти bandwidth-важкого (помірні операції, високий MB/s). Вирішіть, який тип обладнання допоможе.
  5. Визначте гарячий vdev.
    Якщо один vdev гарячіший, запитайте «чому»: перекіс заповнення, інший тип диску, інший шлях, помилки або насичення лог/спеціального пристрою.
  6. Перевірте поведінку sync.
    Запустіть zfs get sync на датасетах. Якщо синхронно-важке, підтвердіть SLOG і його поведінку в iostat.
  7. Перехресна перевірка на рівні ОС.
    Запустіть iostat -x 1 5. Підтвердіть чергу/await пристрою. Якщо пристрої простіють — припиніть звинувачувати диски.
  8. Визначте перше безпечне пом’якшення.
    Приклади: призупинити/перепланувати scrub, перемістити навантаження, обмежити швидкість батч-завдання, додати лог-пристрій, додати vdev або мігрувати датасет.

Чекліст: що зафіксувати для постмортему

  • Принаймні 60 секунд зразків zpool iostat -v, плюс перегляд затримки якщо доступно.
  • Вивід zpool status -v в час інциденту.
  • Метрики пристроїв ОС (iostat -x) для кореляції.
  • Властивості датасету: sync, recordsize, compression, atime, і будь-яка конфігурація special vdev.
  • Чи був активний scrub/resilver і його швидкість.
  • Чітка заява: IOPS-bound, bandwidth-bound, sync-bound або single-vdev-bound.

Питання та відповіді (FAQ)

1) У чому різниця між zpool iostat і Linux iostat?

zpool iostat показує логічний погляд ZFS по пулу/vdev, включно з віртуальними пристроями як logs та special vdev.
Linux iostat показує поведінку блочних пристроїв (черга, await, utilization). Використовуйте обидва: ZFS для знаходження гарячого vdev,
ОС iostat для підтвердження насичення пристрою або проблем шляху.

2) Чому один vdev стає вузьким місцем, якщо ZFS «розподіляє» дані?

ZFS розподіляє по топ-рівневих vdev. Якщо один vdev більш заповнений, повільніший, помиляється або просто має менше дисків, він може стати обмежувальним фактором.
Агрегатна швидкість пулу підтягнеться до найповільнішого vdev, задіяного в навантаженні.

3) Чи SLOG прискорює всі записи?

Ні. SLOG прискорює синхронні записи (записи, які мають бути гарантовано зафіксовані перед поверненням).
Асинхронні записи буферизуються і комітяться через TXG; SLOG мало змінює той шлях.

4) Чому мої записи повільніші за читання в iostat?

Поширені причини: синхронні записи без хорошого SLOG, накладні парності RAIDZ для малих записів, майже заповнений/фрагментований пул,
або пристрій з непостійною затримкою запису. Якщо читання в порядку, а записи жахливі — перевірте sync і поведінку лог-vdev.

5) Чи високі IOPS завжди погано?

Високі IOPS — це просто характеристика навантаження. Вони стають проблемою, коли затримка зростає або система не виконує SLO.
Правильне питання: чи ми обмежені IOPS (малі випадкові) чи пропускною здатністю (великі послідовні)?

6) Скільки зразків треба робити з zpool iostat?

Для триажу 5–10 секунд з інтервалом в 1 секунду підходить. Для діагностики джітера захопіть принаймні 60 секунд і зніміть те ж саме під «звичними» годинами для порівняння.
Проблеми зі сховищем люблять ховатися у варіативності.

7) Чи може фрагментація пояснити піки затримки?

Може, особливо коли пули заповнюються. Фрагментація зазвичай підвищує середню вартість I/O і збільшує дисперсію.
Якщо ви бачите зростаючі часи очікування при схожих IOPS, і пул наближається до повного — фрагментація/податок за ємність реальний підозрюваний.

8) Який найбезпечніший «швидкий фікс» під час інциденту?

Найбезпечніший — зменшити конкуруючі I/O: призупинити/перепланувати scrub, обмежити швидкість батчів або перемістити гучного орендаря.
Зміна sync або перебудова геометрії пулу не є фіксом під час інциденту, якщо ви не готові взяти на себе ризик.

9) Чому zpool iostat показує низьку пропускну здатність, але додаток каже, що багато пише?

Додатки «пишуть» на логічному рівні; ZFS може стискати, коалесцирувати, відкладати або задовольняти записи через кеш і батчинг TXG.
Фактична пропускна здатність, що потрапляє на диск, — це те, що реально б’є по носі дисків. Якщо додаток пише малі випадкові блоки, пропускна здатність може виглядати низькою, навіть якщо система страждає.

10) Чи довіряти середнім показникам затримки?

Довіряйте їм як підказці, а не вердикту. Середні приховують tail latency, а саме вона важлива для користувачів.
Використовуйте зразки в часі, корелюйте з фазами навантаження і підтверджуйте метриками черг на рівні ОС.

Наступні кроки, які можна зробити сьогодні

Якщо ви експлуатуєте ZFS у продакшені, зробіть ці три речі до того, як наступний інцидент зробить їх за вас:

  1. Створіть базову лінію. Захоплюйте щотижневий zpool iostat -v (і перегляд затримки, якщо доступно) для кожного важливого хоста.
    Зберігайте це в нудному, довговічному місці.
  2. Документуйте ваш контракт запису. Для кожного критичного датасету: чи потрібен sync? Якщо так — який SLOG і як ви його валідуєте під навантаженням?
    Якщо ні — чому ні і хто підписався на цей ризик?
  3. Припиніть ставитись до «заповнений пул» як до події тільки ємності. Визначте ваш поріг продуктивності (часто значно нижче 90%),
    і плануйте додавання vdev, поки пул ще комфортний.

Коли ви зможете назвати вузьке місце з доказами — IOPS-bound, bandwidth-bound, sync-bound або single-vdev-bound —
шляхи виправлення стануть прямолінійними. Не завжди дешевими. Але простими. Оце і є домовленість.

← Попередня
ZFS zdb: інструмент, якого ви боїтесь, поки він не знадобиться
Наступна →
Docker: Обмежте лог-спам біля джерела — патерни логування додатків, які рятують диски

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