Ви підключаєтеся по SSH до сервера Ubuntu 24.04, який «палає»: середнє навантаження двозначне, сервіси втрачають таймаути, а в каналі інцидентів збираються скріншоти top з… по суті нульовим використанням CPU. Графіки не нагадують штурм процесора. Проте система явно працює неправильно.
Ласкаво просимо в пастку iowait: машина не «зайнята обчисленнями», вона зайнята очікуванням. І Linux охоче повідомить, що очікування — це «не використовується CPU», тоді як користувачі сприйматимуть це як «все ламиться».
Що означає високе навантаження + низький CPU
Середнє навантаження в Linux — це не «використання CPU». Це кількість задач, які або:
- Запущені (на CPU, стан
R) - В неблокованому сні (зазвичай очікування вводу/виводу, стан
D)
Коли сховище сповільнюється, потоки накопичуються в стані D. Вони не споживають цикли CPU, тому використання CPU виглядає низьким. Але вони все одно додають до середнього навантаження, тому що готові виконувати роботу… щойно ядро завершить їх I/O.
Ця невідповідність пояснює, чому ви бачите:
- Високе середнє навантаження
- Низьке користувацьке/системне використання CPU
- Високий відсоток iowait (іноді), плюс підвищена затримка диска
- Безліч заблокованих потоків (стан D) і таймаути повсюди
Ще одне: «iowait» — не ресурс, який можна «витратити». Це симптом. Він каже, що CPU простояли, бо задачи чекають на I/O. Не боріться із симптомом; знайдіть очікування.
Жарт №1: Якщо ваше середнє навантаження високе, а CPU низьке, вітаємо — ви побудували дуже дорогий зал очікування.
Факти & історія ви, що знадобляться під час інциденту
- Середнє навантаження передує Linux. Воно походить із Unix 1970-х; концепція вважала «Runnable» за бажання CPU, задовго до сучасних стеків зберігання та розподілених систем.
- Linux рахує неблокований сон у навантаження. Саме тому I/O-затримки збільшують середнє навантаження, навіть якщо CPU не завантажені.
- «iowait» — це атрибуція простою CPU. CPU не зайняті; планувальник каже: «Я б виконав роботу, але вона заблокована на I/O.»
- NVMe зробив затримку видимою, не непотрібною. Швидші пристрої знижують середню затримку, але хвостова затримка (p95/p99) все одно руйнує черги й навантаження, коли пристрої або прошивка поводяться неправильно.
- Writeback може перетворити читання на проблему. Пороги брудних сторінок і обмеження запису можуть блокувати не пов’язані задачі, коли ядро вирішує виконати flush.
- Блокове сховище в хмарі часто має поведінку «burst». Ви можете «вичерпати продуктивність» навіть при достатній ємності, і це виглядає саме як iowait.
- Файлові системи по-різному торгують узгодженістю за продуктивність. Режими журналювання ext4, поведінка алокації XFS і групи транзакцій ZFS створюють різні підписи затримок.
- RAID-контролери все ще брешуть. Деякі кеші підтверджують запис раніше, а потім відчувають затримки при скиданні через проблеми батарей/конденсаторів або зміни політики writeback.
- Linux став кращим в спостережуваності. Інструменти на кшталт
iostat -x,pidstat -dі трасування на базі BPF ускладнили маскування проблем зберігання за «CPU виглядає добре».
Швидкий план діагностики (перший/другий/третій)
Це короткий список дій під час гучного пейджера і коли мозок робить ту цікаву річ, де забуває, як працюють комп’ютери.
Перший: підтвердьте, що це не CPU
- Перевірте середнє навантаження, розподіл CPU і чергу виконання проти заблокованих задач.
- Зверніть увагу на процеси в стані D і високий iowait.
Другий: підтвердьте затримку і черги на сховищі
- Чи зайнятий пристрій (
%util)? - Чи висока затримка (
await,r_await,w_await)? - Чи глибока черга (
aqu-sz)?
Третій: ідентифікуйте навантаження й шар
- Які PID виконують I/O? Які файлові системи? Які точки монтування?
- Це локальний диск, mdraid, LVM, dm-crypt, ZFS, NFS, iSCSI чи хмарний том?
- Це throttling writeback, конкуренція журналу чи проблема базового пристрою?
Після виконання цих трьох кроків можна припинити дебати й почати виправлення.
Підтвердження iowait і заблокованої роботи: команди, що знімають суперечки
Нижче — практичні завдання, які можна виконати на Ubuntu 24.04. Кожне містить: команду, реалістичний вивід, що це означає, і рішення, яке з цього випливає.
Завдання 1: Зробіть знімок місця події (середнє навантаження + розподіл CPU)
cr0x@server:~$ uptime
14:22:08 up 36 days, 6:11, 2 users, load average: 18.42, 17.90, 16.77
Значення: Середнє навантаження дуже високе для більшості серверів. Воно не пояснює причину.
Рішення: Негайно перевірте, чи це черга виконання (CPU) або заблоковані задачі (I/O).
Завдання 2: Використовуйте top як дорослий (дивіться на wa, а не тільки %CPU)
cr0x@server:~$ top -b -n 1 | head -n 15
top - 14:22:13 up 36 days, 6:11, 2 users, load average: 18.42, 17.90, 16.77
Tasks: 612 total, 9 running, 168 sleeping, 0 stopped, 435 zombie
%Cpu(s): 3.1 us, 1.2 sy, 0.0 ni, 63.9 id, 31.6 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 64221.1 total, 1234.8 free, 40211.4 used, 22774.9 buff/cache
MiB Swap: 8192.0 total, 8100.0 free, 92.0 used. 18920.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18412 postgres 20 0 4267120 2.1g 12536 D 1.3 3.4 12:48.21 postgres
19344 www-data 20 0 621432 31420 8920 D 0.7 0.0 0:38.02 php-fpm
2228 root 20 0 0 0 0 I 0.3 0.0 9:12.33 kworker/u16:2
Значення: wa близько 30% — явний знак: CPU очікують на I/O. Також помітні процеси в стані D.
Рішення: Перемкніться з «хто використовує CPU?» на «хто блокується на I/O?»
Завдання 3: Виміряйте чергу виконання проти заблокованих задач (vmstat)
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
7 38 94208 126412 81200 23110240 0 0 812 9440 3221 6110 4 1 63 32 0
5 41 94208 125980 81200 23109988 0 0 640 10320 3199 5902 3 1 62 34 0
8 44 94208 124992 81200 23109012 0 0 712 11088 3340 6408 3 1 60 36 0
6 39 94208 125220 81200 23108211 0 0 540 9720 3101 6055 3 1 64 32 0
7 45 94208 125104 81200 23107010 0 0 690 10840 3368 6530 4 1 61 34 0
Значення: Стовпець b (blocked) величезний порівняно з r (runnable). Класичний тиск I/O wait.
Рішення: Перейдіть до метрик затримки та черг на рівні пристрою.
Завдання 4: Підтвердіть насичення диска і затримку (iostat -x)
cr0x@server:~$ iostat -x 1 3
Linux 6.8.0-41-generic (server) 12/28/2025 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
3.2 0.0 1.3 31.4 0.0 64.1
Device r/s w/s rKB/s wKB/s rrqm/s wrqm/s r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
nvme0n1 22.0 340.0 1800.0 93200.0 0.1 12.0 9.80 144.20 52.10 81.8 274.1 2.1 99.2
dm-0 21.8 338.9 1792.0 93140.0 0.0 0.0 10.10 146.90 52.30 82.2 274.9 0.0 0.0
Значення: %util ≈99% вказує на насичення або постійну зайнятість пристрою. w_await ≈144ms — болісно для транзакцій. aqu-sz ≈52 означає глибоку чергу: запити накопичуються.
Рішення: Визначте, хто пише і чому; вирішіть, чи обмежити навантаження, перенести його або виправити шлях до сховища.
Завдання 5: Знайдіть процеси, що виконують I/O (pidstat -d)
cr0x@server:~$ pidstat -d 1 5
Linux 6.8.0-41-generic (server) 12/28/2025 _x86_64_ (16 CPU)
14:22:41 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
14:22:42 999 18412 0.00 18240.00 2400.00 11234 postgres
14:22:42 33 19344 0.00 1220.00 180.00 1320 php-fpm
14:22:42 0 1451 0.00 9800.00 0.00 2100 systemd-journald
14:22:42 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
14:22:43 999 18412 0.00 19010.00 2600.00 11620 postgres
14:22:43 0 1451 0.00 9400.00 0.00 2050 systemd-journald
Значення: postgres і journald — основні записувачі, і iodelay високий (час очікування на I/O). kB_ccwr/s вказує на writeback/кешовані записи, які потім треба скинути.
Рішення: Дослідіть шаблони бази даних та журналювання; розгляньте обмеження швидкості логів, зміну місця зберігання логів, налаштування контрольних точок БД або переміщення WAL.
Завдання 6: Підтвердіть велику кількість задач у стані D (ps)
cr0x@server:~$ ps -eo state,pid,comm,wchan:32 --sort=state | head -n 20
D 18412 postgres io_schedule
D 19344 php-fpm io_schedule
D 20488 nginx io_schedule
D 20501 nginx io_schedule
D 20512 nginx io_schedule
D 22110 rsyslogd io_schedule
R 9123 top -
R 9130 ps -
S 1451 systemd-journald ep_poll
S 1680 sshd do_select
Значення: Кілька процесів додатків заблоковані в io_schedule. Вони чекають завершення I/O.
Рішення: Розглядайте це як інцидент шляху зберігання, поки не доведено інше.
Завдання 7: Зіставте I/O з файловими системами та опціями монтування (findmnt)
cr0x@server:~$ findmnt -D
SOURCE FSTYPE OPTIONS TARGET
/dev/dm-0 ext4 rw,relatime,errors=remount-ro /
/dev/nvme0n1p2 ext4 rw,relatime /var/lib/postgresql
tmpfs tmpfs rw,nosuid,nodev /run
tmpfs tmpfs rw,nosuid,nodev /dev/shm
Значення: Дані Postgres на /dev/nvme0n1p2, root на dm-0. Якщо iostat показує насичення nvme0n1, це співпадає.
Рішення: Зосередьтеся спершу на NVMe-пристрої та шаблоні записів бази даних.
Завдання 8: Перевірте тиск на файловій системі (df, іноди та симптоми журналу)
cr0x@server:~$ df -hT /var/lib/postgresql
Filesystem Type Size Used Avail Use% Mounted on
/dev/nvme0n1p2 ext4 1.8T 1.6T 120G 94% /var/lib/postgresql
Значення: 94% використання не означає миттєвого провалу, але це відома ризикова зона: складніше алокувати, зростає фрагментація, і деякі файлові системи гірше поводяться поблизу повного диска.
Рішення: Плануйте звільнення місця або розширення файлової системи. Тим часом продовжуйте — це саме по собі не пояснює 150ms write await, але сприяє проблемі.
Завдання 9: Перевірте журнали ядра на скиди/тайм-аути диска
cr0x@server:~$ sudo journalctl -k -n 30 --no-pager
Dec 28 14:18:02 server kernel: nvme nvme0: I/O 672 QID 4 timeout, completion polled
Dec 28 14:18:02 server kernel: nvme nvme0: Abort status: 0x371
Dec 28 14:18:03 server kernel: nvme nvme0: resetting controller
Dec 28 14:18:06 server kernel: nvme nvme0: controller reset complete
Dec 28 14:18:11 server kernel: EXT4-fs (nvme0n1p2): Delayed block allocation failed for inode 262401 at logical offset 918234
Dec 28 14:18:12 server kernel: blk_update_request: I/O error, dev nvme0n1, sector 1819238480 op 0x1:(WRITE) flags 0x0 phys_seg 1 prio class 0
Значення: Скидання контролера та I/O-помилки. Це не «додаток повільний». Це «сховище хворе». Також помилки алокації ext4 вказують на тиск та/або базові помилки.
Рішення: Ескалюйте питання здоров’я апаратури/хмарного тому негайно; почніть пом’якшення (фейловер, режим тільки для читання, зменшення записів) під час розслідування.
Завдання 10: Перевірте SMART/NVMe сигнали здоров’я
cr0x@server:~$ sudo nvme smart-log /dev/nvme0 | head -n 20
Smart Log for NVME device:nvme0 namespace-id:ffffffff
critical_warning : 0x00
temperature : 63 C
available_spare : 100%
available_spare_threshold : 10%
percentage_used : 89%
data_units_read : 12,349,221
data_units_written : 81,442,109
host_read_commands : 902,112,441
host_write_commands : 5,110,992,120
controller_busy_time : 145,221
power_cycles : 33
power_on_hours : 14,880
unsafe_shutdowns : 7
media_errors : 18
num_err_log_entries : 18
Значення: percentage_used 89% і ненульові media_errors — сильна підозра, що диск старіє або виходить з ладу. Одна лише це не остаточний вирок, але в поєднанні зі скидами/таймаутами — це вагомий доказ.
Рішення: Замініть/евакуюйте пристрій (або перемістіть навантаження), замість того щоб підлаштовуватися під помираючий диск.
Завдання 11: Перевірте, чи тиск пам’яті не викликає writeback-шторм
cr0x@server:~$ cat /proc/meminfo | egrep 'Dirty|Writeback|MemFree|MemAvailable|Buffers|Cached'
MemFree: 126412 kB
MemAvailable: 19374132 kB
Buffers: 83192 kB
Cached: 22640480 kB
Dirty: 1562040 kB
Writeback: 81220 kB
Значення: Брудні дані ≈1.5GB; не критично на машині з 64GB. MemAvailable в нормі. Тому це менш ймовірно «пам’ять змушує жорсткий writeback», більше ймовірно — «висока затримка пристрою».
Рішення: Не робіть поспішних змін sysctl для writeback. Спочатку виправте шлях до сховища.
Завдання 12: Шукайте прямі докази черг блочного шару
cr0x@server:~$ cat /sys/block/nvme0n1/queue/nr_requests
1023
Значення: Черга пристрою дозволяє багато одночасних запитів. Це може бути корисно для пропускної здатності, але шкідливо для затримки, якщо пристрій вже перевантажений (теорія черг — не річ на інтуїції).
Рішення: Якщо послуга чутлива до затримки, розгляньте зниження паралелізму на рівні додатка або БД; не змінюйте налаштування ядра навмання без вимірів впливу.
Завдання 13: Перевірте планувальник I/O та стек multipath/dm
cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber bfq
Значення: NVMe зазвичай використовує none (без традиційного планувальника) з multiqueue. Це нормально. Якщо бачили складний стек (dm-crypt, dm-thin, multipath), врахуйте це в моделі причин.
Рішення: Якщо це хмара/віртуалізоване сховище, перевірте ліміти віртуального шару; зміна планувальника не вирішить виснаження burst-кредитів або бекендового throttling.
Завдання 14: Корелюйте з sar, щоб зрозуміти, хронічне це чи гостре
cr0x@server:~$ sar -u 1 3
Linux 6.8.0-41-generic (server) 12/28/2025 _x86_64_ (16 CPU)
14:23:41 CPU %user %nice %system %iowait %steal %idle
14:23:42 all 3.05 0.00 1.22 32.10 0.00 63.63
14:23:43 all 2.88 0.00 1.11 30.84 0.00 65.17
14:23:44 all 3.18 0.00 1.30 31.66 0.00 63.86
Average: all 3.04 0.00 1.21 31.53 0.00 64.22
Значення: iowait стабільно високий у цьому вікні. Якщо є історичні дані sar, порівняйте з «нормою» і встановіть час початку проблеми.
Рішення: Якщо почалося після зміни (деплой, оновлення ядра, міграція сховища) — відкотіть або ізолюйте. Якщо поступово — підозрюйте вичерпання потужностей або зношення.
Завдання 15: Якщо це мережеве сховище, перевірте очевидне (тип монтування і RPC-статистика)
cr0x@server:~$ mount | egrep 'type nfs|type cifs' || true
cr0x@server:~$ nfsstat -c 1 2
Client rpc stats:
calls retrans authrefrsh
12433 118 0
Client nfs v4:
null read write commit open
0 812 9340 220 14
Значення: Повторні відправлення (retransmits) вказують на мережеву або серверну затримку. Для NFS iowait може бути «диском», але фактично це «мережа + віддалений диск + черги сервера».
Рішення: Якщо retrans зростає, розглядайте інцидент як розподілене сховище: перевірте відмови мережі, навантаження NFS-сервера та затримки бекенду.
Завдання 16: Підтвердіть, чи systemd/journald посилює біль
cr0x@server:~$ sudo journalctl --disk-usage
Archived and active journals take up 6.7G in the file system.
Значення: Великі журнали плюс гомінкі сервіси можуть генерувати стійкий потік записів. Зазвичай цього недостатньо, щоб самостійно наситити NVMe, але під час інциденту це може посилити проблему.
Рішення: Під час пом’якшення зменшіть вербозність логів або пересилайте логи кудись іще. Не видаляйте журнали навмання під час інциденту, якщо ви не погодили компроміс.
Виявлення вузького місця: диск, файловa система, контролер, мережеве сховище чи ядро
Крок 1: Не довіряйте одній метриці — корелюйте три
Щоб упевнено назвати інцидент iowait-ним, вам потрібен трикутник доказів:
- Доказ планувальника: високе середнє навантаження + багато процесів в стані D (
ps,vmstat) - Атрибуція CPU: значний iowait (
top,sar -u) - Доказ пристрою: висока затримка + черги (
iostat -x)
Якщо всі три збігаються, припиніть сперечатися з графіками. Починайте виправляти шлях до сховища.
Крок 2: Вирішіть, чи це проблема пропускної здатності чи затримки
Це важливо, бо фікс різний:
- Проблема затримки: await високі, черга висока, %util може бути високим. Додатки таймаутять; БД сумні; веб-запити накопичуються.
- Потолок пропускної здатності: await помірні, але ви тиснете величезний постійний I/O. Користувачі бачать повільні пакетні завдання, не обов’язково таймаути.
Для інциденту «високе навантаження, низький CPU» зазвичай це затримка й черги.
Крок 3: З’ясуйте, чи це читання, запис чи flush
iostat -x розділяє r_await та w_await. Це важливо, бо:
- Спайки w_await часто корелюють з комітами журналу, шаблонами WAL/fsync, політикою кеша контролера або throttling хмарного тому.
- Спайки r_await вказують на невлучання кеша, посилення випадкового I/O або пристрій, що не витримує робочого набору.
Крок 4: Визначте шар, що додає болю
В Ubuntu стек I/O може включати: файлова система → LVM → dm-crypt → mdraid → пристрій, плюс опціонально мережеве сховище. Кожен шар може помножувати затримку під навантаженням.
Швидкі способи зіставити:
lsblk -fпоказує шарування device-mapper.dmsetup ls --treeробить це явним.multipath -ll(якщо використовується) показує стан шляхів.
cr0x@server:~$ lsblk -o NAME,TYPE,FSTYPE,SIZE,MOUNTPOINT
NAME TYPE FSTYPE SIZE MOUNTPOINT
nvme0n1 disk 1.8T
├─nvme0n1p1 part vfat 512M /boot/efi
├─nvme0n1p2 part ext4 1.6T /var/lib/postgresql
└─nvme0n1p3 part crypto 200G
└─dm-0 crypt ext4 200G /
Значення: Root зашифрований через dm-crypt; дані БД — plain ext4 на розділі 2.
Рішення: Якщо том БД — «гарячий» пристрій, не відволікайтеся на тюнінг dm-crypt для root.
Крок 5: Зрозумійте режим «D state не вмирає»
Коли потоки застрягають в неблокованому сні, їх не завжди можна вбити. Ядро чекає завершення I/O; сигнали не допомагають. Якщо базовий пристрій або шлях заблокований, процеси можуть залишатися в стані до відновлення пристрою — або до перезавантаження.
Ось чому «просто перезапустіть сервіс» іноді нічого не змінює. Старі процеси все ще заблоковані, нові теж блокуються, і тепер ви додали ще більше хаосу.
Жарт №2: Надсилання SIGKILL процесу в стані D — це як кричати на індикатор завантаження: емоційно приємно, операційно марно.
Крок 6: Одна цитата, що керуватиме вашою поведінкою під час інциденту
Ідея (парафраз): «Усе ламається, завжди — проектуйте й експлуатуйте як ніби відмови нормальні.»
iowait-інциденти здаються загадковими, бо вони «не про CPU». Але це нормально: диски зависають, мережі рипають, контролери скидаються, хмарні томи тротляться. Будуйте виявлення та runbook-и під такі випадки.
Три корпоративні міні-історії (такі, що запам’ятовуються)
Міні-історія 1: Інцидент через неправильне припущення
У них був платіжний сервіс на Ubuntu, CPU-графіки були нормальні, і раптовий стрибок середнього навантаження спровокував тривоги «масштабування». On-call вирішив, що це сплеск трафіку, і додав два інстанси. Навантаження залишилося високим. Запити все одно таймаутили.
Потім вони зробили класичну річ: grep по логам додатка, знайшли «database connection timeout» і оголосили базу «повільною». Перезапустили БД. Це не допомогло. Гірше: перезапуск тривав довго, бо процес БД був застряглий у стані D, чекаючи диска, і хуки завершення зависли.
Нарешті хтось запустив iostat -x і побачив write await у сотні мілісекунд і %util на максимумі. Сховище було хмарним блочним томом. Воно не було переповнене за місцем; воно вичерпало гарантовані IOPS через зміну конфігурації кілька тижнів тому, плюс сплеск записів audit-логів, що з’їв burst.
Неправильне припущення було тонким: «високе навантаження означає обчислювальний тиск». Вони діяли як при CPU, і масштабування не допомогло, коли кожен інстанс стикався з тими ж обмеженнями сховища (спільний бекенд) або тим же шаблоном навантаження (амліфікація записів).
Вирішили: відкотити зміну логування, зменшити частоту записів і тимчасово перемістити WAL/логи на швидший рівень сховища. Тільки після цього система почала поводитися. Постмортем був різким: були алерти на насичення CPU, але не було алертів на затримку диска. Пейджер кричав, а дашборди шепотіли.
Міні-історія 2: Оптимізація, що зіграла злий жарт
Команда платформи захотіла швидших деплоїв. Вони перемістили шари контейнерних образів і кеші збірки на спільний NFS, щоб «зменшити дублювання» і «спростити бекапи». Було красиво на діаграмі. Усі аплодували. Але прийшов перший великий релізний день.
Ноди показували високе навантаження, але top не показував використання CPU. Поди падали на readiness. Інженери ганялися за плануванням Kubernetes, DNS і «гучними сусідами» по CPU. Тим часом бекенд NFS виконував синхронні записи для операцій, багатих на метадані, і отримав удар тисяч дрібних файлових операцій.
Оптимізація зіграла злий жарт, бо сконцентрувала випадковий метаданний I/O. Мережевий шлях сховища підсилював хвостову затримку: кеші клієнта, черги сервера, бекенд-диск і час від часу повторні відправлення, коли мережа була навантажена. Кожен шар «в порядку» в середньому. Разом вони створили фабрику затримок.
Відновлення було не хитрим: повернути кеші збірки на локальні NVMe на кожному вузлі і використовувати спільний NFS як репозиторій артефактів, а не як scratchpad. «Заощадження» на ємності було сплачено інцидентним часом, втраченою довірою розробників і великою кількістю марного масштабування CPU.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Компанія запускала конвеєр аналітики клієнтів на кількох великих хостах Ubuntu. Нічого фантастичного: пакетні завдання, база даних і черга повідомлень. SRE мала одну неефектну звичку: щотижня фіксувати базові показники затримки для кожного пристрою — зведення iostat -x, пікові await і примітку, як виглядає «норма».
Одного дня середнє навантаження підросло, а команда додатку повідомила «CPU нормальний». On-call відкрив документ базової лінії і одразу побачив невідповідність: нормальний w_await — одиниці мілісекунд; зараз — сотні. Жодних дискусій. Не «можливо код». Це було сховище, поки не доведено інше.
Вони перевірили журнали ядра і знайшли випадкові скиди контролера. Недостатньо, щоб впасти, але досить, щоб зламати затримку. Оскільки був базовий профайл, вони не втратили годину на доведення «ненормальності». Вони вже знали.
Пом’якшення було також нудним: фейловер БД на стендбай на іншому обладнанні, відпалювання batch-воркерів і планування вікна техобслуговування для заміни підозрілого пристрою. Звіт по інциденту не був захопливим. Ось у чому суть. Хороші операції часто виглядають так, ніби хтось відмовляється двічі дивуватися тією ж відмовою.
Поширені помилки: симптом → корінна причина → виправлення
Тут команди втрачають час. Трюк — розглядати симптоми як підказки, а не як діагнози.
1) Симптом: Високе середнє навантаження, низький CPU, багато таймаутів
Корінна причина: заблоковані потоки в стані D через затримки або помилки сховища.
Виправлення: Підтвердити vmstat/ps/iostat -x. Пом’якшити, зменшивши запис, перемістивши гарячі шляхи (WAL/логи) на швидше сховище або зробивши фейловер. Дослідити здоров’я пристрою і журнали ядра.
2) Симптом: iowait низький, але навантаження високе і додатки зависають
Корінна причина: load включає стан D; відсоток iowait може вводити в оману на багатоядерних системах або коли заблоковані задачі не відображені належним чином.
Виправлення: Порахуйте задачі в стані D напряму (ps) і перевірте метрики блочного шару (iostat -x). Не орієнтуйтеся тільки на iowait.
3) Симптом: %util 100%, але пропускна здатність не висока
Корінна причина: пристрій зайнятий повільними операціями (висока затримка), часто випадковими записами, навантаженням fsync або повторними спробами через помилки.
Виправлення: Визначте шаблон I/O (iostat -x, pidstat -d). Зменшіть частоту fsync, де безпечно, перенесіть WAL, або виправте апаратні/хмарні обмеження.
4) Симптом: Все погіршується після «тюнінгу» writeback ядра
Корінна причина: підвищення брудних відсотків збільшує сплески; flush-шторм стають більшими і болючішими, коли пристрій не встигає.
Виправлення: Поверніть за замовчуванням, якщо немає виміряного підґрунтя. Надавайте перевагу згладженню на рівні додатка (пакетування записів, обмеження швидкості) над ризикованим тюнінгом ядра.
5) Симптом: Перезапуски сервісів не допомагають; завершення висить
Корінна причина: процеси застрягли в стані D, чекаючи завершення I/O; вони не помруть, поки I/O не повернеться.
Виправлення: Виправте базовий збій сховища або перезавантажте як крайній захід після впевненості, що це не погіршить відновлення (особливо при помилках сховища). Для БД краще фейловер, ніж перезавантаження первинної ноди.
6) Симптом: Тільки одна точка монтування повільна, інші в порядку
Корінна причина: конкретний том/пристрій насичений або має помилки; не «весь хост».
Виправлення: Зіставте монтування з пристроями (findmnt, lsblk). Перемістіть навантаження, змініть квоти або виправте/замініть пристрій.
7) Симптом: Пульсуюча повільність у передбачувані інтервали
Корінна причина: контрольні точки, коміти журналу, txg sync у ZFS, ротація логів або періодичні знімки резервних копій.
Виправлення: Вирівняйте графіки, зменшіть паралелізм, рознесіть завдання, акуратно налаштуйте контрольні точки БД і по можливості ізолюйте логи/WAL від даних.
8) Симптом: Високий iowait на VM, але диски «виглядають добре» в гість-ОС
Корінна причина: contention на хості, throttling або ефекти «гучного сусіда»; метрики всередині гостя показують симптом, а не причину.
Виправлення: Перевірте метрики гіпервізора/хмари і ліміти томів. Інструменти в гості показують симптоми; причина може бути поза VM.
Чек-листи / покроковий план
Чек-лист A: 10-хвилинна триаж (робіть це перед будь-якими змінами)
- Зафіксуйте
uptime, знімокtopіvmstat 1 5. - Запустіть
iostat -x 1 3і збережіть вивід. - Складіть список топ I/O процесів через
pidstat -d 1 5. - Порахуйте задачі в стані D:
ps -eo state | grep -c '^D'. - Перевірте журнали ядра на помилки зберігання:
journalctl -k -n 100. - Зіставте монтування з пристроями:
findmnt -Dіlsblk. - Перевірте вільне місце й іноди на «гарячих» монтуваннях:
df -hT,df -i.
Чек-лист B: Варіанти пом’якшення (обирайте найменш ризикований, що працює)
- Швидко зменште запис: знизьте рівень логування, призупиніть пакетні завдання, уповільніть інгест.
- Захистіть базу даних: якщо WAL/контрольні точки — біль, перемістіть WAL на швидший/виділений пристрій або зробіть фейловер.
- Ізолюйте «шумні» процеси: зупиніть або обмежте головного записувача I/O (обережно — не вбивайте єдине, що гарантує цілісність даних).
- Перемістіть трафік: відведіть ноду з балансувальників, переведіть на здорові репліки.
- Крайній захід: перезавантаження тільки після підтвердження, що це не погіршить відновлення (особливо при помилках сховища).
Чек-лист C: Робота над корінною причиною (після стабілізації)
- Визначте, чи латентність домінує у читаннях чи записах (
iostat -x). - Корелюйте з деплойами/змінами (
journalctl, ваш лог змін). - Підтвердіть здоров’я апаратури/томів (NVMe SMART, RAID-журнали, події хмарних томів).
- Перевірте поведінку файлової системи поблизу заповнення, режим журналювання і опції монтування.
- Оцініть зміни шаблону I/O додатка (нове логування, індекси, vacuum, compaction).
- Додайте алерти: затримка диска
await, глибина черги, кількість D-state задач, заповнення файлової системи й частота помилок ядра.
FAQ
1) Чому середнє навантаження росте, якщо CPU простий?
Бо Linux включає в load задачі в неблокованому сні (D), зазвичай ті, що чекають на I/O. Вони не використовують CPU, але «не просуваються», тому рахуються у навантаженні.
2) Чи завжди високе iowait погано?
Ні. Високий iowait під час відомої пакетної операції читання/запису може бути прийнятним, якщо сервіси, чутливі до затримки, ізольовані. Це погано, коли корелюється з таймаутами користувача і зростанням кількості D-state процесів.
3) Чому іноді iowait низький, хоча проблема в сховищі?
iowait — це атрибуція простою CPU, а не прямий вимір затримки диска. На багатоядерних системах кілька заблокованих потоків можуть не змінити загальний відсоток. Також вибірка й інструменти можуть ховати короткі сплески. Рахуйте задачі в стані D і вимірюйте затримку пристрою прямо.
4) Яка найшвидша одна команда, щоб довести, що це сховище?
iostat -x 1 3. Якщо ви бачите високі await, глибоку aqu-sz і високий %util на релевантному пристрої — маєте реальні докази. Поєднайте з D-state процесами для остаточного висновку.
5) Чи означає високий %util, що диск на максимальній пропускній здатності?
Не обов’язково. Це може означати, що пристрій зайнятий обслуговуванням повільних операцій (висока затримка) або обробляє повтори/помилки. Пропускна здатність може бути посередньою, а %util при цьому максимальним.
6) Як відрізнити, що проблема в диску чи в файловій системі/журналі?
Якщо «голе» пристрій показує високу затримку — починайте з нього. Якщо ж «голе» пристрій в нормі, але конкретне монтування повільне, дивіться на поведінку файлової системи: конкуренція журналу, проблеми при заповненні, опції монтування і шаблони fsync додатка.
7) Чому процеси в стані D ігнорують kill -9?
Бо вони застрягли в неблокованому очікуванні ядра, зазвичай на завершення I/O. Сигнал в очікуванні, але процес не може його обробити, поки виклик ядра не повернеться.
8) Якщо це VM у хмарі, що підозрювати в першу чергу?
Ліміти продуктивності томів, вичерпання burst-кредитів, ефекти «гучного сусіда» і contention на хості. Інструменти в гості показують симптом; причина може бути зовні VM.
9) Чи може свопінг спричинити такий самий шаблон?
Так. Інтенсивний свопінг створює навантаження I/O і заблоковані задачі. Але зазвичай ви побачите активність свопу в vmstat (si/so) і зменшення MemAvailable. Не здогадуйтеся — міряйте.
10) Які алерти додати, щоб не дивуватися знову?
Щонайменше: per-device await (читання/запис), глибина черги (aqu-sz), кількість D-state задач, заповнення файлової системи і частота помилок ядра. CPU сам по собі — брехун у цій історії.
Висновок: наступні кроки, що справді змінюють ситуацію
Коли Ubuntu 24.04 показує високе навантаження, але «ніщо не використовує CPU», розглядайте це як проблему заблокованої роботи, поки не доведено інше. Підтвердіть підрахунком D-state задач, vmstat і iostat -x. Як тільки ви бачите підвищену затримку і черги, припиніть тикати CPU і почніть працювати зі шляхом зберігання: здоров’я пристрою, скиди контролера, ліміти томів, тиск файлової системи і конкретні процеси, що породжують записи.
Практичні наступні кроки:
- Включіть швидкий план діагностики у ваш on-call runbook дослівно.
- Додайте алерти на затримку диска і заблоковані задачі, а не тільки CPU і load.
- Зафіксуйте базові «нормальні»
awaitі глибину черг для критичних хостів. - Розділяйте логи/WAL, чутливі до затримки, від масових даних де можливо.
- Якщо журнали ядра показують тайм-аути/скиди: припиніть тюнінг і почніть міграцію/заміну сховища. Не вирішите цю проблему sysctl-ами — фізика сильніша.