ZFS рідко «виходить із ладу» драматично. Воно гальмує. Тихо. Графік трошки коливається. Затримки зростають.
Додатки починають таймаутити. Хтось створює тікет про «періодичне уповільнення». І потім — бо Всесвіт не любить смиренність — ваше
наступне розгортання натискає на проблему і отримує звинувачення за все.
Секрет у тому, щоб помітити деградацію продуктивності ZFS, поки це ще вікно обслуговування, а не посмертний аналіз. Це польовий посібник для
читання журналів і суміжної правди (повідомлення ядра, помилки пристроїв, потоки подій ZFS), щоб рано помічати уповільнення і вирішувати,
що робити далі — швидко, точно і без ритуалів-копіювань.
Мислення: журнали — це хронологія, а не настрій
«Журнали» ZFS — це множина. Є потік подій ZFS, кільцевий буфер ядра, системний журнал systemd, журнали SMART/пристроїв
і власне уявлення ZFS про стан пулу. Мета не в тому, щоб накопичити більше тексту. Мета — зіставити часові лінії:
що стало повільнішим, коли це почалось і що ще змінилось.
Ось операційна позиція, яка тримає вас подалі від проблем:
- Надавайте перевагу затримці над пропускною здатністю. Користувачі відчувають 99-й процентиль латентності. Дашборди, що показують лише MB/s, вас обмануть.
- Припускайте, що ZFS чесний щодо цілісності даних і консервативний щодо продуктивності. Коли воно гальмує, зазвичай воно вас захищає від чогось гіршого.
- Будьте підозрілими щодо наративів «почалося після X». Проблеми ZFS часто інкубуються тижнями: один слабкий диск, невірно підібраний recordsize, один шлях синхронного запису, який ви забули.
- Корелюйте на рівні пристроїв. Більшість «проблем продуктивності ZFS» — це або затримка пристроїв, чергування, або шлях синхронного запису, який робить саме те, що ви йому наказали.
Рядок журналу — це підказка, а не вирок. Вам все одно треба зіставити його з реальністю: zpool iostat, arcstat, iostat,
і тим, що насправді роблять ваші додатки.
Цікаві факти та історичний контекст (щоб ви припинили гадати)
- ZFS народився в епоху Solaris з моделлю цілісності даних end-to-end — контрольні суми всюди — тому що «безшумна корупція» вже була проблемою, просто ще не стала популярною.
- Intent log (ZIL) — це не кеш записів. Це механізм для відтворення синхронних семантик після краху. Більшість записів ніколи не живуть в «журналі» довго.
- SLOG — це пристрій, а не фіча. Додавання окремого лог-пристрою допомагає лише синхронним записам і може зашкодити, якщо він повільний або неправильно налаштований.
- Scrub створювали як проактивний аудит, а не як інструмент «лікувати при поломці». Це те, як ZFS доводить, що ваші дані залишаються вашими даними.
- Поведінка resilver еволюціонувала. Сучасні OpenZFS resilver-и можуть бути послідовними й розумнішими щодо того, що копіювати, але ви все одно платите в I/O конкуренції.
- ARC/L2ARC тюнінг має довгу історію поганих порад. Багато «гайдів з продуктивності» десятирічної давнини оптимізували під інші навантаження і інші пропорції RAM-to-disk.
- ashift на все життя. Невірне припущення про розмір сектору при створенні пулу може закріпити вас у write amplification — тихо дорого, голосно боляче.
- Стиснення стало загальноприйнятим в ZFS-операціях, бо CPU здешевів, а I/O — ні. Але виграш залежить від форми ваших даних, а не від надій.
Що насправді означає «повільний ZFS»: карта вузьких місць
«ZFS повільний» — це як сказати «місто переповнене». Яка вулиця? Яка година? Яке перекриття смуги?
На практиці уповільнення ZFS групуються у кілька категорій. Ваші журнали зазвичай вкажуть на одну:
1) Затримка пристрою та відновлення після помилок
Один поганий диск може зупинити vdev. У RAIDZ і дзеркалах найповільніший елемент часто стає темп-автом.
Журнали ядра Linux можуть показувати скидання лінку, таймаути команд або події «замерзлих черг». ZFS може показувати помилки читання/запису/контрольної суми.
Навіть якщо диск «відновився», витрати на повторні спроби оплачуються у часових затримках вашими додатками.
2) Шлях синхронного запису: проблеми ZIL/SLOG
Якщо ваше навантаження виконує синхронні записи (бази даних, NFS, деяке VM-сховище, усе, що часто викликає fsync),
тоді затримка ZIL важлива. З SLOG ваша синхронна латентність часто дорівнює латентності SLOG.
Без SLOG синхронні записи потрапляють у пул і переймають латентність пулу. Журнали не скажуть «fsync — ваша проблема» цими словами,
але паттерн помітний: зростаючий await, сплески вирівняні з txg sync і багато скарг під час періодів великих комітів.
3) Сплески часу синхронізації transaction group (txg)
ZFS групує зміни в transaction groups. Коли txg комітиться («синхронізується»), система може бачити короткі хвилі записного I/O.
Якщо час синхронізації зростає, все, що залежить від цих комітів, гальмує. Це може проявлятися як періодичні паузи, NFS «не відповідає»,
або сплески латентності додатків кожні кілька секунд.
4) Проблеми з метаданими та фрагментацією
Фрагментація — не моральний недолік; це фізика плюс час. Деякі робочі навантаження (образи VM, бази даних, дрібні випадкові записи)
можуть перетворити пул на дорогий фестиваль seek-ів. Журнали ZFS не надрукують «ви фрагментовані», але ваші iostat-патерни покажуть це,
а час scrub/resilver буде гіршати.
5) Тиск пам’яті: thrash ARC
Коли hit rate ARC падає, читання йдуть на диск. Це не завжди погано — іноді робоча множина просто більша за RAM.
Але раптове падіння ARC може статися після пам’ятного розгортання, зміни щільності контейнерів або невиваженого налаштування L2ARC.
Сигнал зазвичай такий: більше дискових читань, вища латентність і ядро, яке виглядає… зайнятим.
Одну перефразовану ідею, часто приписувану John Allspaw, варто тут згадати: Надійність походить із навчання і адаптації, а не з імітації здатності все передбачити.
ZFS адаптується. Ваше завдання — навчитися читати його підказки, поки воно не почало кричати.
Швидкий план діагностики (перші/другі/треті перевірки)
Якщо ви на виклику, у вас немає часу на інтерпретативні танці. Потрібна послідовність, що звужує простір пошуку.
Цей план розрахований на Linux + OpenZFS, але логіка переноситься.
Перший: чи пул зараз здоровий?
- Запустіть
zpool status -x. Якщо він каже не «all pools are healthy», зупиніться і розберіться з цим спочатку. - Перевірте
zpool events -vна недавні збої пристроїв, скидання лінків або помилки контрольних сум. - Пошукайте scrub/resilver, що йдуть. «Здоровий» пул може бути повільним, якщо він перебудовується.
Другий: це проблема пристрою чи навантаження/синхронізації?
- Запустіть
zpool iostat -v 1і слідкуйте за розподілом латентності по vdev. Один повільний диск? Один повільний дзеркальний член? Ось ваш підозрюваний. - Запустіть
iostat -x 1і перевіртеawait,svctm(якщо є) та%util. Високий await + високий util = насичення пристрою/черги. - Перевірте, чи корелює латентність зі сплесками синхронних записів: шукайте високі записи з відносно низькою пропускною здатністю, але високим await.
Третій: підтвердьте режим відмови журналами й лічильниками
- Журнал/ядро:
journalctl -kдля таймаутів, скидань, помилок NCQ, транспортних помилок, скасованих команд. - SMART:
smartctlдля перевірки reallocated sectors, pending sectors, CRC errors (часто кабель/бекплейн). - Статистика ZFS: поведінка ARC (
arcstat, якщо доступно), повідомлення txg sync (залежно від збірки), і історія подій.
Одне речення правила: якщо ви можете назвати найповільніший компонент, ви зазвичай можете виправити відмову.
Якщо не можете — ви ще здогадуєтесь, звужуйте далі.
Практичні завдання: команди, виводи та рішення (12+)
Це завдання, які я реально виконую в продакшені, коли ZFS сповільнюється. Кожне включає, що означає вивід і яке рішення ви приймаєте далі.
Копіювання/вставка дозволені. Панікувати не можна.
Завдання 1: Швидка перевірка стану пулу
cr0x@server:~$ sudo zpool status -x
all pools are healthy
Значення: Немає відомих збоїв, немає деградувань vdev, немає активних помилок. Це не гарантує продуктивності, але викреслює один великий клас аварій.
Рішення: Перейдіть до діагностики латентності (zpool iostat, iostat), а не до відновлювальних операцій.
Завдання 2: Повний статус з лічильниками помилок і поточною роботою
cr0x@server:~$ sudo zpool status
pool: tank
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
scan: scrub repaired 0B in 02:14:33 with 0 errors on Mon Dec 23 03:12:18 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_860-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_860-2 ONLINE 0 0 3
errors: No known data errors
Значення: Пул онлайн, але один пристрій має помилки контрольних сум. ZFS виправив їх за рахунок надлишковості, але тепер є запах проблем надійності й продуктивності.
Рішення: Розберіться з шляхом до цього пристрою (SMART, кабелі, бекплейн, HBA). Не робіть zpool clear як терапію; очищуйте лише після розуміння причин.
Завдання 3: Слідкування за латентністю по vdev в реальному часі
cr0x@server:~$ sudo zpool iostat -v 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 4.12T 3.15T 210 980 23.1M 61.4M
mirror-0 2.06T 1.57T 105 510 11.6M 30.7M
ata-SAMSUNG_SSD_860-1 - - 60 250 6.7M 15.2M
ata-SAMSUNG_SSD_860-2 - - 45 260 4.9M 15.5M
-------------------------- ----- ----- ----- ----- ----- -----
Значення: Баланс навантаження в дзеркалі виглядає приблизно симетрично в часі. Якщо один учасник показує значно менше операцій, але вищу латентність (не в цьому базовому вигляді),
або якщо операції vdev різко падають при стабільному попиті пулу — це натяк, що пристрій відстає або повторює спроби.
Рішення: Якщо дисбаланс триває, зіставте з журналами ядра і SMART; розгляньте виведення/заміну підозрілого пристрою, якщо помилки підтверджуються.
Завдання 4: Додати колонки латентності (де підтримується)
cr0x@server:~$ sudo zpool iostat -v -l 1
capacity operations bandwidth total_wait disk_wait
pool alloc free read write read write read write read write
-------------------------- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
tank 4.12T 3.15T 220 1020 24.0M 63.2M 3ms 28ms 2ms 24ms
mirror-0 2.06T 1.57T 110 520 12.0M 31.6M 2ms 30ms 2ms 27ms
ata-SAMSUNG_SSD_860-1 - - 55 260 6.1M 15.8M 2ms 8ms 2ms 7ms
ata-SAMSUNG_SSD_860-2 - - 55 260 5.9M 15.8M 2ms 90ms 2ms 85ms
-------------------------- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
Значення: Один диск має сплески disk_wait (85–90ms), тоді як інший лишається низьким. Це ваш «темп-автом».
Рішення: Забирайте дані з журналів ядра та SMART. Якщо це шлях кабель/HBA — виправте його. Якщо проблема в самому SSD — плануйте заміну до того, як він «відновиться» під час наступної відмови.
Завдання 5: Перевірити конкуренцію зі scrub/resilver
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: resilver in progress since Thu Dec 26 08:11:02 2025
312G scanned at 1.24G/s, 48.2G issued at 192M/s, 7.11T total
48.2G resilvered, 0.68% done, 10:27:11 to go
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
errors: No known data errors
Значення: Триває resilver. Ваш пул виконує додаткові читання/записи, і латентність зазвичай погіршується.
Рішення: Якщо це production для користувачів, вирішіть, чи обмежити швидкість resilver/scrub (де підтримується),
або тимчасово перемістити навантаження. Також підтвердіть, що первинна проблема повністю усунена — не дозволяйте другому диску хитатися під час resilver.
Завдання 6: Прочитати недавній потік подій ZFS
cr0x@server:~$ sudo zpool events -v | tail -n 30
TIME CLASS
Dec 26 2025 08:10:58.123456789 ereport.fs.zfs.vdev.io
pool = tank
vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
vdev_guid = 1234567890123456789
errno = 5
size = 131072
offset = 9876543210
flags = 0x180
Dec 26 2025 08:10:58.223456789 ereport.fs.zfs.vdev.checksum
pool = tank
vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
vdev_guid = 1234567890123456789
Значення: ZFS записує I/O-помилки і проблеми контрольних сум для конкретного пристрою.
Рішення: Розглядайте це як апаратну діагностику шляху: SMART, кабелі, HBA, каркас. Якщо повторюється — замінюйте пристрій.
Якщо припинилось після переміщення кабелю, все одно тримайте під наглядом; переривчасті CRC-помилки люблять повертатися.
Завдання 7: Перевірка журналів ядра на скидання та таймаути транспорту
cr0x@server:~$ sudo journalctl -k --since "2 hours ago" | egrep -i "ata|nvme|scsi|reset|timeout|error" | tail -n 40
Dec 26 09:01:14 server kernel: ata7.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
Dec 26 09:01:14 server kernel: ata7.00: failed command: READ FPDMA QUEUED
Dec 26 09:01:14 server kernel: ata7: hard resetting link
Dec 26 09:01:18 server kernel: ata7: link is slow to respond, please be patient (ready=0)
Dec 26 09:01:20 server kernel: ata7: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
Dec 26 09:01:20 server kernel: ata7.00: configured for UDMA/133
Значення: Події скидання лінку. Навіть коли вони «відновлюються», час повторних спроб створює сплески латентності і може зупинити vdev.
Рішення: Перевірте кабелі/бекплейн, живлення і прошивку HBA. Якщо це окремий відсік, переставте диск в інший слот, щоб ізолювати шлях енклоужуру.
Завдання 8: SMART-діагностика (SATA/SAS пристрої)
cr0x@server:~$ sudo smartctl -a /dev/sdb | egrep -i "Reallocated|Pending|Offline_Uncorrectable|CRC_Error_Count|Power_On_Hours"
9 Power_On_Hours 0x0032 094 094 000 Old_age Always - 23874
197 Current_Pending_Sector 0x0012 100 100 000 Old_age Always - 8
198 Offline_Uncorrectable 0x0010 100 100 000 Old_age Offline - 2
199 UDMA_CRC_Error_Count 0x003e 200 200 000 Old_age Always - 0
Значення: Pending sectors і offline uncorrectable — реальні проблеми носія. CRC count нуль вказує, що це не «тільки кабель».
Рішення: Плануйте заміну. Якщо пул надлишковий — замініть запобіжно. Якщо це один диск (не робіть так зазвичай), спочатку зробіть бекап, а потім міняйте негайно.
Завдання 9: NVMe health і журнал помилок
cr0x@server:~$ sudo nvme smart-log /dev/nvme0 | egrep -i "critical_warning|media_errors|num_err_log_entries|percentage_used"
critical_warning : 0x00
media_errors : 12
num_err_log_entries : 398
percentage_used : 87%
Значення: Помилки носія і високий percentage_used можуть корелювати зі зростанням латентності та ймовірним відмовленням.
Рішення: Якщо цей NVMe — SLOG або special vdev, ставтесь до цього як до термінового випадку — ці ролі різко деградують продуктивність при неполадках.
Завдання 10: Визначити synchrony-важкі навантаження через властивості набору даних
cr0x@server:~$ sudo zfs get -o name,property,value -s local sync,logbias,primarycache,recordsize tank/app tank/vm
NAME PROPERTY VALUE
tank/app sync standard
tank/app logbias latency
tank/app primarycache all
tank/app recordsize 128K
tank/vm sync always
tank/vm logbias latency
tank/vm primarycache metadata
tank/vm recordsize 16K
Значення: sync=always вимушує синхронні семантики навіть якщо додаток цього не просить. Це може бути правильно, або це самоіндукована проблема продуктивності.
Рішення: Перевірте, чому встановлено sync=always. Якщо це для бази даних, яка вже керує довговічністю, ви можете платити двічі. Якщо це для NFS/VM — залиште і інвестуйте в належний SLOG.
Завдання 11: Підтвердити наявність SLOG і базове розташування
cr0x@server:~$ sudo zpool status tank | sed -n '1,80p'
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
logs
nvme-SAMSUNG_MZVLB1T0-1 ONLINE 0 0 0
errors: No known data errors
Значення: Існує одиночний SLOG-пристрій. Це поширено, але також одиночна точка продуктивності і (залежно від вашої терпимості) ризику для латентності синхронних записів.
Рішення: Для критичних синхронних навантажень краще використовувати дзеркальні SLOG-пристрої. І переконайтесь, що SLOG має низьку латентність у умовах безпечного від втрати живлення.
Завдання 12: Перевірити, чи система тоне в чергах I/O
cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server) 12/26/2025 _x86_64_ (32 CPU)
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await %util
sda 12.0 340.0 480 14560 83.2 18.4 52.6 3.1 54.4 99.2
sdb 10.0 332.0 420 14400 85.7 1.2 3.7 2.8 3.8 34.5
nvme0n1 0.0 25.0 0 2048 163.8 0.4 15.8 0.0 15.8 40.1
Значення: sda завантажений ~99% з глибокою чергою і високим await, тоді як sdb в нормі. У дзеркалі це може тягнути vdev вниз.
NVMe показує помірний await; якщо це ваш SLOG, 15ms може бути занадто повільно для очікувань «швидкого fsync».
Рішення: Дослідіть, чому sda повільний: помилки, прошивка, термічне тротлінг, проблеми контролера. Якщо це член дзеркала, розгляньте тимчасове виведення з пулу, щоб побачити, чи покращиться латентність (з усвідомленням ризиків).
Завдання 13: Перевірити поведінку ARC (якщо доступно arcstat)
cr0x@server:~$ arcstat 1 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
09:12:01 3120 980 31 220 7 710 23 50 1 96.2G 96.0G
09:12:02 2980 940 31 240 8 650 22 50 1 96.2G 96.0G
09:12:03 3050 970 32 210 7 710 23 50 1 96.2G 96.0G
09:12:04 3105 995 32 230 7 715 23 50 1 96.2G 96.0G
09:12:05 3002 960 32 220 7 690 23 50 1 96.2G 96.0G
Значення: ~31–32% miss rate може бути нормою або катастрофою залежно від вашого сховища і навантаження. Якщо miss% раптом підскочив відносно базової лінії,
диски бачитимуть більше читань і латентність зросте.
Рішення: Порівняйте з базовою лінією за минулий тиждень. Якщо ARC capped (c дорівнює arcsz) і у вас є вільна RAM, розгляньте підняття ARC max.
Якщо ARC тисне інше споживання пам’яті — вирішіть проблему тиску пам’яті, а не «тюньте ZFS» у глухий кут.
Завдання 14: Перевірити стиснення набору даних та ступінь логічного/фізичного I/O
cr0x@server:~$ sudo zfs get -o name,property,value compression,compressratio tank/app
NAME PROPERTY VALUE
tank/app compression lz4
tank/app compressratio 1.62x
Значення: Стиснення працює і, ймовірно, економить I/O. Якщо compressratio ≈ 1.00x, ви платите CPU за нульову вигоду по I/O (зазвичай невелике з lz4, але не нуль).
Рішення: Якщо CPU — вузьке місце і дані несжимаємі, розгляньте вимкнення стиснення для цього датасета. Інакше лиште lz4 — це одна з рідкісних «за замовчуванням», що виправдовує себе.
Завдання 15: Знайти, хто зараз вантажить пул
cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 45.20 M/s | Total DISK WRITE: 112.30 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
18342 be/4 postgres 2.10 M/s 65.40 M/s 0.00 % 84.21 % postgres: checkpointer
20111 be/4 root 0.00 B/s 28.20 M/s 0.00 % 62.10 % zfs send -w tank/app@snap
9321 be/4 libvirt-qemu 1.10 M/s 12.80 M/s 0.00 % 20.33 % qemu-system-x86_64
Значення: Маємо checkpointer, що сильно пише, zfs send, що відправляє дані, і віртуальні машини, що читають/пишуть. Це карта конкуренції.
Рішення: Якщо латентність помітна користувачам, призупиніть або перенесіть масовий трансфер (zfs send) або обмежте його швидкість. Не сперечайтесь з фізикою.
Жарт №1: Сховище — єдине місце, де «в середньому все добре» прийнятно аж до моменту, коли ні.
Три корпоративні міні-історії (анонімізовано, болісно правдоподібні)
Міні-історія 1: Інцидент, спричинений невірним припущенням
Середня SaaS-компанія запускала клієнтський Postgres на ZFS-backed VM storage. Місяцями було стабільно, команда пишалася:
дзеркальні SSD, стиснення ввімкнено, щотижневі scrub-и, базовий моніторинг. Єдине, що не моніторили — латентність синхронних записів. Бо в їхніх головах
«SSD швидкі».
З’явилась нова вимога з комплаєнсу: забезпечити семантику довговічності для підмножини навантажень. Інженер встановив sync=always на датасет, де зберігались
образи VM. Припущення було простим: «Це безпечніше і трохи повільніше.» Наполовину виявилось правдою.
Наступного ранку клієнти повідомили про спорадичні таймаути. Пул виглядав здоровим. CPU ок. Мережа ок. Графіки пропускної здатності ок.
Але 99-й процентиль латентності записів вибухнув. Журнали ядра нічого драматичного не показували. Журнали ZFS помилок не показували. Всі почали дивитись на рівень додатку,
бо так роблять, коли сховище не хоче зізнатись.
Куряча слідина була в zpool iostat -l: SLOG-пристрій (споживчий NVMe без захисту від втрати живлення) мав високу й нестабільну латентність під тривалим синхронним навантаженням.
Він не був «зламаним». Йому просто попросили забезпечити постійну низьку латентність комітів, і він ввічливо відмовився.
Виправлення було нудне й дороге: замінити SLOG на пристрій, призначений для стабільної латентності синхронних записів, і дзеркалити його.
Постмортем виніс одну урок, який варто витатуювати: не змінюйте синхронні семантики, не вимірявши шлях синхронізації.
Міні-історія 2: Оптимізація, що дала зворотний ефект
Внутрішня платформа підприємства тримала ZFS-пул для CI-артефактів і контейнерних образів. Переважно великі файли, багато паралельних читань
і інколи великі записи. Система «була ок», але ініціатива «збільшити throughput» вступила в гру.
Хтось знайшов стару нотатку і вирішив додати «special vdev» для метаданих, щоб пришвидшити обходи директорій і дрібні читання.
Додали пару маленьких швидких SSD як special vdev. Початкові бенчмарки були чудові. Керівництво усміхнулося. Всі забули.
Через місяці продуктивність стала дивною. Не просто повільнішою — спонтанно-спайкова. У пікові години CI збірки затримувалися на секунди.
zpool status лишався зеленим. Але zpool iostat -v -l показав огидну картину: special vdev став вузьким місцем латентності.
Ці «маленькі швидкі SSD» тепер активно писались, зношувались і інколи тротлили.
Причина зворотного ефекту не в самій фічі, а в розрахунку розміру та думці про життєвий цикл. Метадані й дрібні блоки можуть притягувати I/O.
Коли special vdev хандрить, весь пул відчуває запаморочення. Журнали ядра мали слабкі NVMe-попередження, недостатні для тривоги,
але достатні, щоб пояснити паузи, зіставлені зі сплесками латентності.
План ремедіації: замінити special vdev на більш довговічні прилади, збільшити його ємність, щоб зменшити write amplification,
і додати моніторинг саме для латентності special vdev та показників зносу. Мораль: кожна структура прискорення стає залежністю.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Фінансова компанія тримала ZFS для NFS-бекенду домашніх директорій і спільних збірочних артефактів. Нічого крутого. Жодного героїчного тюнінгу.
Але була дисципліна: місячні scrub-и, алерти на зміни zpool status і рукописний план дій, що змушував інженерів перевіряти
помилки транспорту ядра перед тим, як чіпати ZFS-налаштування.
Одного вівторка латентність підросла. Користувачі помітили. На виклику дотримались рукопису: перевірити стан пулу, події, журнали ядра.
За кілька хвилин знайшли повторювані SATA link reset на одному відсіку диска. Ще не було помилок ZFS — лише повторні спроби.
Вони замінили кабель/бекплейн у запланованому мікровікні, до того як диск почав кидати checksum-помилки.
Латентність впала до базової. Ніякого resilver. Ніякого ризику з даними. Жодного витраченого вихідного.
Практика, що їх врятувала, не була геніальною. Вона була послідовною: scrub-и для виявлення латентних проблем і кореляція журналів для раннього виявлення деградації апаратного шляху.
Нудне — недооцінене у інженерії сховищ, бо працює.
Жарт №2: Якщо хочете захопливу кар’єру у сховищах, ігноруйте свій scrub-графік; pager створить вам пригоди.
Типові помилки: симптом → корінна причина → виправлення
1) «Пул ONLINE, але латентність жахлива»
Симптом: zpool status виглядає чистим; додатки таймаутять; iostat показує високий await.
Корінна причина: Повторні спроби пристрою, скидання лінку або один повільний диск, що тягне дзеркало/RAIDZ vdev.
Виправлення: Перевірте journalctl -k на предмет скидань/таймаутів; перевірте SMART/NVMe журнали помилок. Замініть підозрілий пристрій або відновіть шлях транспорту. Не налаштовуйте ZFS, щоб компенсувати брехню апаратури.
2) «Кожні кілька секунд у нас пауза»
Симптом: Періодичні сплески латентності; NFS лаги; база даних показує затримки комітів.
Корінна причина: Txg sync займає занадто багато часу, часто через насичений пул, високу фрагментацію або повільний пристрій, що гальмує flush-и.
Виправлення: Використайте zpool iostat -l для виявлення повільного vdev і зменште конкуренцію записів. Якщо синхронно-важко, виправте латентність SLOG або перегляньте sync=always.
3) «Додав SLOG і продуктивність погіршилась»
Симптом: Після додавання лог-пристрою синхронно-важке навантаження сповільнилось.
Корінна причина: SLOG має гіршу латентність, ніж пул, або піддається тротлінгу; одиночний SLOG стає вузьким місцем.
Виправлення: Перевірте за допомогою iostat -x і zpool iostat -l. Замініть на низьколатентний пристрій з захистом від втрати живлення, бажано дзеркальний. Якщо навантаження в основному асинхронне — видаліть SLOG і не чекайте див.
4) «Контрольні суми продовжують зростати, але scrub їх ремонтує»
Симптом: CKSUM збільшується; scrub виправляє; поки що без видимих для користувачів помилок.
Корінна причина: Зазвичай проблема шляху: кабель/бекплейн/HBA (CRC-помилки), інколи — носій диска.
Виправлення: Перевірте SMART CRC-лічильники і журнали транспорту ядра. Перепосадіть/замініть кабель/бекплейн; оновіть прошивку; замініть диск, якщо індикатори носія погані. Потім прогоніть scrub і стежте за лічильниками.
5) «Resilver буде завершено за 2 години… наступні 3 дні»
Симптом: ETA resilver росте; пул повільний.
Корінна причина: Конкуренція навантаження + фрагментація пулу + повільний пристрій. Resilver змагається за I/O і може бути пригніченим або відстороненим вашими додатками.
Виправлення: Зменшіть навантаження, заплануйте resilver у непікові години, і перевірте наявність слабкого диска, що подовжує процес. Підтвердіть, що ashift і дизайн vdev не викликають патологічної write amplification.
6) «ARC hit rate впала після розгортання чогось несуміжного»
Симптом: Раптове збільшення дискових читань; зростання латентності; зміни у використанні пам’яті.
Корінна причина: Тиск пам’яті від нових сервісів, щільності контейнерів або поведінки page cache; ARC обмежений конфігурацією або витискається іншими споживачами.
Виправлення: Виміряйте використання пам’яті, не вгадуйте. Якщо є вільна RAM — підвищьте ARC cap. Якщо ні — зменшіть тиск пам’яті або перемістіть навантаження. Не додавайте L2ARC як заміну відсутній RAM, поки не розберетесь із шаблоном читань/записів.
7) «Ми підлаштували recordsize і тепер записи повільніші»
Симптом: Після зміни recordsize пропускна здатність впала, латентність зросла.
Корінна причина: Невідповідність recordsize і навантаження (наприклад, занадто великий для випадкових DB-записів, занадто малий для послідовного стримінгу).
Виправлення: Встановлюйте recordsize на рівні датасету відповідно до типу навантаження. Образи VM і бази даних часто віддають перевагу меншим блокам (наприклад, 16K), тоді як великі послідовні файли виграють від більших (128K–1M залежно від випадку). Перевіряйте на реальних I/O-трасах, а не за відчуттями.
Чек-листи / покроковий план
Чек-лист A: Коли користувачі скаржаться на «періодичне уповільнення»
- Підтвердіть, чи це латентність сховища: перевірте app-level p95/p99 і I/O wait на хостах.
- Запустіть
zpool status -x. Якщо не здоровий — поводьтесь як з інцидентом. - Запустіть
zpool statusі пошукайте scrub/resilver у процесі. - Запустіть
zpool iostat -v -l 1на 60–120 секунд. Визначте найповільніший vdev/пристрій за латентністю. - Запустіть
journalctl -kз фільтром на скидання/таймаути. Підтвердіть, чи має повільний пристрій відповідні помилки. - Перевірте SMART/NVMe стан підозрілого пристрою.
- Прийміть рішення: ізолювати (offline/replace), відремонтувати шлях (кабель/бекплейн/HBA) або зменшити конкуренцію навантаження.
Чек-лист B: Коли підозрюють синхронні записи (бази/NFS/VM)
- Перевірте властивості датасету
syncіlogbiasдля відповідних датасетів. - Підтвердіть, чи є SLOG і який він (одиночний чи дзеркальний).
- Виміряйте латентність SLOG за допомогою
iostat -xна SLOG-пристрої під час сповільнення. - Якщо латентність SLOG гірша за головний пул — не дискутуйте: замініть або видаліть його залежно від потреб синхронності.
- Якщо SLOG немає і синхронна латентність болюча — розгляньте додавання правильного дзеркального SLOG після верифікації, що навантаження дійсно синхронне.
Чек-лист C: Коли з’являються помилки, але пул «продовжує працювати»
- Збережіть вивід
zpool statusіzpool events -vдля запису інциденту. - Перевірте журнали ядра навколо тих самих часових міток на предмет проблем шляху.
- Перевірте індикатори SMART/NVMe і лічильники помилок носія.
- Виправте шлях або замініть апарат. Лише потім очищуйте помилки за допомогою
zpool clear. - Запустіть scrub після ремедіації і підтвердіть, що лічильники помилок припинили зростати.
Чек-лист D: Базова лінія, щоб виявляти регресії
- Збережіть базову
zpool iostat -v -lпід час «відомо доброго» стану. - Збережіть базові показники ARC (hit rate, розмір ARC, індикатори тиску пам’яті).
- Відстежуйте тривалість scrub і resilver (вони ранні попередження фрагментації і старіння пристроїв).
- Налаштуйте алерти на помилки транспорту ядра, а не лише на стани ZFS-пулу.
FAQ
1) Чи достатньо журналів ZFS для діагностики проблем продуктивності?
Ні. ZFS скаже вам про сигнали цілісності (помилки, збої, події), але діагностика продуктивності потребує контексту пристрою і ядра.
Завжди зіставляйте події ZFS з журналами ядра і iostat/zpool iostat.
2) Якщо zpool status чистий, чи можна виключити апарат?
Зовсім ні. Багато апаратних/транспортних проблем проявляються як повторні спроби і скидання значно раніше, ніж ZFS інкрементує лічильник.
Журнали ядра і SMART часто показують «предсимптоми».
3) Чи завжди додавання SLOG покращує продуктивність?
Тільки для синхронних записів. Для асинхронних навантажень він переважно не має значення. І повільний SLOG може зробити синхронну продуктивність гіршою.
Ставтесь до SLOG як до критичного за латентністю компонента, а не як до галочки.
4) Який найшвидший спосіб знайти один поганий диск у дзеркалі?
Використайте zpool iostat -v -l 1 і шукайте учасника з драматично вищим disk wait. Потім підтвердіть journalctl -k і SMART/NVMe журнали.
5) Чи завжди помилки контрольних сум означають, що диск вмирає?
Часто це шлях: кабель, бекплейн, HBA, прошивка. SMART CRC-помилки і скидання транспорту ядра — ваші підказки.
Помилки носія (pending/reallocated/uncorrectable) більше вказують на проблеми самого диска.
6) Чому пул сповільнюється під час scrub, якщо scrub «фоновий»?
Scrub фоновий за наміром, але не за фізикою. Він споживає реальний I/O і може підвищити латентність.
Якщо scrub спричиняє біль користувачам — плануйте його краще, обмежуйте швидкість, де можна, і переконайтесь, що пул має достатній запас продуктивності.
7) Чи варто ставити sync=disabled, щоб виправити латентність?
Це не вирішення; це торг з реальністю і сподівання, що вона не помітить. Ви ж шукаєте надписи. Якщо дані важливі — виправте шлях синхронізації (SLOG/латентність пристрою).
8) Чи завжди висока фрагментація причина уповільнень?
Ні. Фрагментація поширена, але перший підозрюваний зазвичай — латентність пристрою або деградований/перебудовуваний пул.
Фрагментація проявляється як довга тенденція: scrub/resilver ростуть, випадковий I/O дорожчає, і латентність легше спровокувати.
9) Коли треба очищувати помилки ZFS за допомогою zpool clear?
Після того, як ви виправили первинну причину і зняли докази. Очищення занадто рано стирає сліди і провокує повторні інциденти.
10) Якщо ZFS повільний, але iostat показує низький %util — що тоді?
Тоді вузьке місце може бути в іншому місці: CPU (стиснення/шифрування), тиск пам’яті, тротлінг або завислий шлях синхронізації.
Також підтвердіть, що ви вимірюєте правильні пристрої (multipath, dm-crypt шари, HBA).
Висновок: практичні наступні кроки
Аварії продуктивності ZFS зазвичай — це повільнорухомі апаратні відмови, сюрпризи зі шляхом синхронного запису або конкуренція rebuild/scrub, які ніхто не вважав виробничою подією.
Добра новина: ви можете бачити їх заздалегідь — якщо дивитесь у правильні місця і тримаєте базову лінію.
Зробіть наступне:
- Збережіть базову
zpool iostat -v -lіiostat -xпід час здорового стану, і тримайте ці числа там, де їх знайде ваше майбутнє «я». - Налаштуйте алерти на помилки транспорту ядра (скидання, таймаути) окремо від змін стану ZFS-пулу.
- Аудитуйте датасети щодо налаштувань
syncі визначте, які навантаження дійсно синхронно-важкі. - Вирішіть, чи ваш SLOG (якщо є) дійсно підходить: низька латентність, захист від втрати живлення і бажано дзеркалення для критичних середовищ.
- Тримайте scrub-и запланованими і під наглядом. Не тому, що це весело, а тому що так ви виявляєте «тиху корупцію і слабкий апарат» на ранніх стадіях.
Ваша мета — не створити ідеальну систему ZFS. Ваша мета — зробити уповільнення передбачуваними, діагностованими й виправними — перш ніж вони перетворяться на відмови з запрошенням на зустріч.