Главная боль новичка в том, что "диск тормозит" - это ощущение, а не цифра. Чтобы из ощущения получить факт, нужен инструмент, который покажет: сколько операций в секунду диск тянет, сколько данных гоняет и - самое важное - сколько миллисекунд каждый запрос ждёт ответа. Этот инструмент - iostat. В этом уроке разберём его по косточкам: что такое iostat util, что значит await, как по двум-трём колонкам понять, узкое место у тебя диск или нет, и куда копать дальше, когда iostat уже сказал своё слово.
Откуда брать iostat и как его запускать
iostat не входит в базовую поставку большинства систем, он живёт в пакете sysstat. Ставим:
Код: Выделить всё
# Ubuntu / Debian / Astra Linux
sudo apt install sysstat
# RHEL / Fedora / RED OS / ALT
sudo dnf install sysstat
Запускать iostat без аргументов почти бесполезно: он покажет средние значения с момента загрузки системы. Это как спросить "какая была средняя скорость машины за всю её жизнь" - цифра есть, толку ноль. Нам нужна картина прямо сейчас, в динамике. Поэтому рабочая команда такая:
Код: Выделить всё
iostat -xz 1

Чтение вывода iostat по колонкам - самое главное
Вот типичный кусок вывода для устройства sda (HDD под нагрузкой). Не пугайся, сейчас пройдёмся по каждой цифре. Реальный вывод sysstat 12.x шире, я оставил ключевые колонки:
Код: Выделить всё
Device r/s w/s rkB/s wkB/s rareq-sz wareq-sz aqu-sz r_await w_await %util
sda 12.0 340.0 480.0 46000.0 40.0 135.3 18.50 8.30 72.40 99.20
- r/s и w/s - это IOPS, число операций чтения и записи в секунду (уже после слияния смежных запросов ядром). Здесь 12 чтений и 340 записей. Это интенсивность, "сколько раз в секунду диск дёргают".
- rkB/s и wkB/s - пропускная способность, сколько килобайт в секунду читается и пишется. 46 МБ/с записи - для одиночного HDD это уже близко к потолку при не-последовательной записи.
- rareq-sz и wareq-sz - средний размер одного запроса в килобайтах. Тут запись по 135 КБ - это крупные запросы, похоже на потоковую/последовательную нагрузку. Маленькие значения (4-16 КБ) - признак случайного мелкоблочного ввода-вывода (типичная база данных). По этой колонке ты сразу понимаешь характер нагрузки.
- r_await и w_await - вот оно, сердце диагностики. Это среднее время в миллисекундах от момента, как запрос попал в очередь, до момента, как диск его выполнил и вернул ответ. То есть полное время ожидания глазами приложения, включая стояние в очереди. w_await тут 72 мс - это очень много. Приложение, которое пишет на этот диск, на каждую запись ждёт по 72 мс. В старых версиях была одна общая колонка await - она и сейчас есть в неразбитом выводе, но r_await/w_await информативнее, потому что чтение и запись могут вести себя совершенно по-разному.
- aqu-sz (в старых версиях называлась avgqu-sz) - средняя длина очереди: число запросов в очереди планировщика плюс уже отданные устройству, но ещё не завершённые. Грубо - сколько запросов в среднем "висит в работе" одновременно. 18.5 - очередь забита, диск захлёбывается. Эту цифру удобно сопоставлять с типом устройства: для одного HDD aqu-sz больше 1-2 уже означает, что запросы стоят и ждут.
- %util - доля времени интервала, в течение которого к устройству был отдан хотя бы один запрос. 99.2% значит, что устройство почти всё время было чем-то занято. Запомни формулировку "хотя бы один запрос" - дальше она нас спасёт от грубой ошибки.
Теперь про нормы, потому что без них цифры мёртвые. Ориентир по await (актуально на 2026):
- HDD (обычный жёсткий диск): норма await - единицы и десятки миллисекунд. 5-15 мс при умеренной нагрузке - ок. Сотни мс - диск перегружен, очередь стоит колом.
- SATA SSD: норма - доли миллисекунды и единицы мс. Если SATA SSD стабильно даёт await 10+ мс, что-то не так: либо он деградирует/умирает, либо нагрузка дикая, либо упёрлись в шину SATA.
- NVMe: здесь счёт идёт на десятки и сотни микросекунд, то есть await обычно заметно меньше 1 мс. Стабильно несколько миллисекунд - уже повод присмотреться (проверь тепловой троттлинг, заполненность, версию прошивки).
Самое распространённое заблуждение, на котором горят даже опытные админы: "%util равен 100, значит диск - узкое место". Для старого HDD это было правдой: блин один, головка одна, он физически делает одну операцию за раз. 100% занятости = упёрлись в потолок.
Но SSD и особенно NVMe умеют обрабатывать много запросов параллельно - десятки и сотни одновременно (у NVMe сотни аппаратных очередей по тысячам команд). А %util по своей механике считает просто "был ли в устройстве хотя бы один запрос в этот момент времени". Он не знает, сколько ещё запросов диск мог бы взять сверху. Поэтому NVMe легко показывает %util 100%, а на деле используется процентов на десять от реальной мощности. Это не баг iostat, а фундаментальное ограничение метрики на multi-queue устройствах - о нём давно предупреждают и Brendan Gregg, и Marc Brooker. Для таких дисков %util - индикатор "диск не спит", но НЕ индикатор насыщения. Та же ловушка касается RAID-массивов и device-mapper (LVM, mpath): там %util агрегированного устройства тоже почти бессмыслен.
Куда смотреть вместо %util на SSD/NVMe? На связку await, w_await/r_await и aqu-sz. Если очередь (aqu-sz) растёт, а await вместе с ней ползёт вверх - вот это настоящее насыщение: запросы копятся быстрее, чем диск успевает их разгребать. Если же aqu-sz маленькая (меньше 1-2) и await низкий, то %util 100% можно смело игнорировать - диску ещё далеко до предела. Практический приём: гони на устройство всё больше нагрузки и следи, на каком aqu-sz await начинает резко расти - вот эта точка перегиба и есть реальный потолок твоего диска по latency.
Связь iowait и await - не путай их
Новички часто видят в top или vmstat показатель iowait (он же %wa или wa) и думают, что это и есть "загрузка диска". Это не так. iowait linux - это доля времени, когда процессор простаивал, потому что ждал завершения операций ввода-вывода и при этом ему было больше нечего делать. Это метрика CPU, а не диска.
Высокий iowait - сигнал "процессор часто скучает в ожидании диска". Но он коварен: на машине с быстрым многоядерным CPU iowait может быть низким даже при адском диске, потому что свободным ядрам есть чем заняться - iowait усредняется по всем ядрам. И наоборот, на однопоточной задаче iowait взлетит до небес. Поэтому iowait - это намёк "копай в сторону диска", а конкретику про нагрузку на диск в Linux даёт именно iostat и его await. На 2026 есть более честный сигнал давления ввода-вывода - PSI (Pressure Stall Information), он считает реальное "залипание" задач из-за I/O независимо от числа ядер:
Код: Выделить всё
cat /proc/pressure/io
# some avg10=23.5 avg60=18.2 avg300=9.8 total=...
Когда iostat не хватает: переходим на eBPF (актуально на 2026)
iostat даёт усреднённые по секунде цифры. Но средний await 2 мс может скрывать редкие выбросы в 200 мс, которые и портят жизнь приложению (хвост распределения, p99). Здесь iostat слеп. На 2026 стандарт де-факто для глубокого разбора латентности диска - инструменты на eBPF из пакетов bcc (bpfcc-tools) и bpftrace. Они почти бесплатны по накладным расходам, потому что считают гистограммы прямо в ядре.
Код: Выделить всё
# гистограмма задержек блочного I/O (по Ctrl-C)
sudo biolatency-bpfcc
# то же одной строкой через bpftrace
sudo biolatency.bt
# кто именно генерит I/O: процесс, операция, размер, latency
sudo biosnoop-bpfcc
Типичные грабли и заблуждения
- Смотрят на первый блок вывода iostat. Он усреднён с загрузки и к текущей ситуации отношения не имеет. Всегда читай со второго блока.
- Меряют диск по %util на NVMe/SSD/RAID. Разобрали выше - на параллельных устройствах это пустышка для оценки насыщения. Смотри await + aqu-sz.
- Ищут колонку svctm. Её нет с sysstat 12.0, она удалена как недостоверная на multi-queue. Совет из старых статей устарел.
- Путают пропускную способность и IOPS. Бэкап одним большим потоком даёт огромные kB/s при низком r/s и большом wareq-sz - это норма. База с мелкими случайными запросами даёт высокий r/s при скромных kB/s и маленьком rareq-sz - тоже норма. Под разную нагрузку - разные узкие места.
- Забывают, что await включает ожидание в очереди. Большой await при большой aqu-sz часто значит не "диск медленный", а "вы шлёте на него больше, чем он тянет". Иногда лечится не заменой диска, а уменьшением параллелизма в приложении или числа воркеров.
- Доверяют среднему await и не видят хвоста. Средняя в норме, а p99 ужасный - это и есть случай для biolatency.
- Сначала узнай тип своего диска: - ROTA=1 это HDD, ROTA=0 это SSD/NVMe, TRAN покажет nvme/sata.
Код: Выделить всё
lsblk -d -o NAME,ROTA,TRAN,MODEL - Открой два терминала. В первом запусти и оставь крутиться.
Код: Выделить всё
iostat -xz 1 - Во втором создай нагрузку на запись мимо кэша (осторожно, файл займёт место, потом удали):
Код: Выделить всё
dd if=/dev/zero of=/tmp/iotest.bin bs=1M count=4096 oflag=direct - Смотри в iostat: как подскочили wkB/s, w_await, aqu-sz и %util на твоём диске. Запиши w_await до и во время нагрузки, сравни с нормой для своего типа диска.
- Бонус для тех, у кого есть eBPF: параллельно запусти и посмотри на гистограмму задержек за время теста - есть ли хвост.
Код: Выделить всё
sudo biolatency-bpfcc 5 1 - Удали файл:
Код: Выделить всё
rm /tmp/iotest.bin
- Какая колонка iostat - главный сигнал задержки, в каких единицах она измеряется и что в неё входит, кроме времени самого диска?
- Почему %util не годится как индикатор насыщения для NVMe, SSD и RAID, и на что смотреть вместо него?
- Чем iowait в top отличается от await в iostat, и какой более честный показатель давления I/O появился в современных ядрах?
- Что показывает biolatency и в каком случае iostat его не заменит?
Рабочая команда - iostat -xz 1, читаем со второго блока. await (а лучше r_await/w_await) - это время ожидания запроса глазами приложения, главный показатель здоровья диска: единицы-десятки мс для HDD, доли мс для SATA SSD, ещё меньше для NVMe. %util честен только для старых HDD; на SSD/NVMe/RAID вместо него смотри связку await плюс aqu-sz - растут вместе, вот это насыщение. iowait в top и /proc/pressure/io - повод запустить iostat, а не диагноз сам по себе. А когда нужна правда про хвост задержек и виновника - это уже работа для eBPF: biolatency и biosnoop.