Learning Platform
Глоссарий Troubleshooting
Урок 16.02 · 22 мин
Начальный
vmstatiostatsarIOmemoryobservability

vmstat и iostat — что делает CPU и диск под капотом

top показывает snapshot прямо сейчас. Но что было 5 минут назад? Какие диски нагружены? Сколько именно ops/sec идёт? Для этих вопросов есть vmstat и iostat — утилиты из пакета sysstat, выдающие time-series снимки vital metrics. Они — мост между “система медленно работает” и “вот конкретно что тормозит”.

В этом уроке: как читать вывод vmstat 1 (memory, swap, IO, system, CPU), iostat -xz 1 (per-disk метрики: r/s, w/s, await, %util), и sar — архив исторических метрик (“что было в 3:42 ночью когда упал alert”).


vmstat: системные метрики во времени

$ vmstat 2 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 2945676 124356 9821456    0    0    12    45  187  234  4  1 94  1  0
 0  0      0 2945412 124356 9821456    0    0     0   132  423  812  2  1 97  0  0
 2  1      0 2944008 124356 9821456    0    0    24   215  511  945  6  2 88  4  0
 1  0      0 2944168 124356 9821456    0    0     8    74  234  456  3  1 95  1  0
 0  0      0 2944168 124356 9821456    0    0     0    13  198  389  1  0 99  0  0

Команда vmstat 2 5 = снимок каждые 2 секунды, всего 5 раз. Без аргументов — один snapshot (averages с момента boot, не очень полезно для дебага).

Колонки:

procs:

  • r — runnable processes (waiting for CPU OR running). Если r > nproc — CPU перегружен.
  • b — blocked processes (waiting for IO, D state). Если b > 0 регулярно — IO bottleneck.

memory:

  • swpd — сколько в swap (KB).
  • free — свободная RAM.
  • buff — buffers (metadata IO).
  • cache — page cache.

swap:

  • si — swap in: страницы прочитаны из swap (kB/s). Любое значение > 0 = плохо.
  • so — swap out: страницы записаны в swap. Активный swapping — сигнал нехватки RAM.

io:

  • bi — blocks in: прочитано с диска (kB/s).
  • bo — blocks out: записано (kB/s).

system:

  • in — interrupts per second. Высокое значение — много IRQ от устройств.
  • cs — context switches per second. Очень высокое (>10000) — много контекст-свитчинга, возможно много мелких процессов или избыток threads.

cpu — то же что в top: us, sy, id, wa, st.


Что искать в vmstat: типичные паттерны

Паттерны vmstat по симптомам
r > nprocПостоянно много runnable процессов. CPU перегружен. Идти в top, профилировать через perf
b > 0 регулярноПроцессы блокированы на IO. Идти в iostat -- смотреть %util, await
si/so > 0Активный swap traffic. Памяти не хватает физически. RAM upgrade или поиск memory leak
cs >> inОчень много context switches. Слишком много threads/процессов, или активная синхронизация на mutex
us high, sy lowПолезная нагрузка приложений. Это OK -- сервер работает. Если медленно -- profile приложение
sy highМного syscalls. Strace на конкретный процесс -- понять что часто вызывается. Иногда badly-written code
wa highIO wait. iostat для деталей: какой диск, какая latency, какие процессы
st > 5%На cloud VM -- noisy neighbour или throttling. На bare-metal быть не может

vmstat -s: cumulative stats since boot

$ vmstat -s | head -20
     32985856 K total memory
     19234176 K used memory
       654321 K active memory
      8765432 K inactive memory
      3145728 K free memory
       124356 K buffer memory
      9821456 K swap cache
      8388604 K total swap
            0 K used swap
      8388604 K free swap
    345678234 non-nice user cpu ticks
      4567891 nice user cpu ticks
     78912345 system cpu ticks
   2345678901 idle cpu ticks
     12345678 IO-wait cpu ticks
            0 IRQ cpu ticks
       234567 softirq cpu ticks
            0 stolen cpu ticks
     85648456 pages paged in
    234567843 pages paged out
        12345 pages swapped in
         6789 pages swapped out
   1234567890 interrupts
    567890123 CPU context switches
   1715856234 boot time
       234567 forks

Это абсолютные счётчики с момента boot. Полезно для:

  • Понимания total work за uptime.
  • Расчёта rate: разность за период / время.
  • Анализа pages swapped in/out > 0 — система когда-то свопила.

iostat — per-disk метрики

$ iostat -xz 2
Linux 6.5.0-21-generic (server)  05/18/2026  _x86_64_  (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           4.32    0.00    1.25    8.45    0.00   85.98

Device            r/s     w/s     rkB/s     wkB/s   rrqm/s   wrqm/s  %rrqm  %wrqm r_await w_await aqu-sz rareq-sz wareq-sz  svctm  %util
nvme0n1         12.45   45.67   1234.56   4567.89     0.45     2.34   3.5    4.9    0.45    1.23   0.06    99.13   100.04   0.34   3.21
sda              5.23   23.45    523.45   1234.56     0.12     1.45   2.2    5.8    8.45   25.67   0.65    100.12   52.65   1.23  35.67

Device            r/s     w/s     rkB/s     wkB/s   ... %util
nvme0n1         15.34   89.12   ...                       4.56
sda              8.23   45.67   ...                      67.23

iostat -xz 2 — extended stats, skip zero-IO devices, каждые 2 сек.

Колонки:

  • r/s, w/s — reads / writes per second (IOPS).
  • rkB/s, wkB/s — read / write throughput (KB/s).
  • rrqm/s, wrqm/s — merged ops per second (kernel объединяет close ops).
  • %rrqm, %wrqm — доля merged.
  • r_await, w_await — среднее latency request (миллисекунды). КРИТИЧНАЯ метрика.
  • aqu-sz (average queue size) — сколько запросов в очереди.
  • rareq-sz, wareq-sz — средний размер request (KB).
  • svctm — сервис-время (deprecated, ненадёжно на современных Linux).
  • %util — доля времени, когда устройство busy. 100% = диск перегружен.

Что важно в iostat

%util — доля времени, когда диск делает работу. 100% значит диск не успевает.

# Здоровый диск:
Device            ... %util
nvme0n1               ...  3.21      <-- 3% utilization, есть запас

# Загруженный:
sda                   ... 80.45      <-- 80%, под нагрузкой, но справляется

# Перегруженный:
sdb                   ... 100.00     <-- queue растёт, latency растёт
WARNING

%util на SSD/NVMe немного лжёт. Эти устройства поддерживают параллельные операции; util считается на основе времени с >=1 active request. Так что NVMe может быть 80% util и ещё иметь capacity. Лучше смотреть await + IOPS.

r_await / w_await — latency. Это среднее время от queue до completion:

  • HDD: 5-15 ms норма для последовательных, 100+ для random.
  • SSD: 0.1-1 ms норма, 5+ ms — что-то не так.
  • NVMe: 0.05-0.5 ms норма, 2+ ms — проблема.

Если await >> typical — IO bottleneck.

aqu-sz (avg queue size) — сколько запросов ждут. Зависит от типа устройства:

  • HDD: меньше 2 норма.
  • SSD: меньше 8 норма.
  • NVMe: меньше 32 норма.

Большая очередь = устройство не справляется или хорошо параллелится workload (для NVMe).


Найти “виновного” процесса: iotop

iostat показывает per-device. Чтобы найти какой ПРОЦЕСС жрёт IO — iotop:

$ sudo iotop -o    # -o = только активные
Total DISK READ:       234.56 K/s | Total DISK WRITE:        12.34 M/s
Current DISK READ:     223.45 K/s | Current DISK WRITE:      11.23 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 1234 be/4 postgres   123.45 K/s  10.45 M/s  0.00 %    78.45 % postgres: writer
 5678 be/4 root        45.67 K/s   1.23 M/s  0.00 %    12.34 % rsync /backup
 9012 be/4 docker      67.89 K/s   543.21 K/s 0.00 %     2.45 % node app.js

В отличие от iostat (показывает диски), iotop показывает процессы. -o — только те, что делают IO. -P — агрегировать по процессу (а не threads).

Колонки:

  • DISK READ/WRITE — скорости.
  • IO> — процент времени, который процесс провёл в IO wait. Высокий = он часто блокирован.

sar — архивные метрики

sar (System Activity Reporter) — из пакета sysstat. По умолчанию собирает метрики каждые 10 минут, хранит в /var/log/sysstat/. Это бесценно для расследования: “вчера в 3:42 alert был, что происходило?”.

Активация (на Ubuntu):

sudo apt install sysstat
sudo sed -i 's/ENABLED="false"/ENABLED="true"/' /etc/default/sysstat
sudo systemctl restart sysstat

Использование:

# Сегодня CPU breakdown:
sar -u

# Конкретное время сегодня:
sar -u -s 03:30:00 -e 04:00:00

# Вчера:
sar -u -f /var/log/sysstat/sa$(date -d yesterday +%d)

# Память:
sar -r 1

# IO:
sar -b

# Per-device:
sar -d -p

# Network:
sar -n DEV 1

# Load average:
sar -q

Это значит, после инцидента в 3 утра вы утром можете сделать sar -u -s 02:30 -e 03:30 и увидеть точно, что было в момент проблемы.


Real example: расследование “ETL стал медленным после полуночи”

# 1. CPU breakdown в момент инцидента:
$ sar -u -s 00:00 -e 03:00
00:00:01     CPU     %user     %nice   %system   %iowait    %steal     %idle
00:10:01     all     12.34      0.00      3.45     65.78      0.00     18.43   <-- начало!
00:20:01     all     14.56      0.00      4.23     67.45      0.00     13.76
00:30:01     all     13.78      0.00      3.89     70.12      0.00     12.21
00:40:01     all     10.23      0.00      2.34     65.45      0.00     21.98

# 2. Какой диск отвечал:
$ sar -d -p -s 00:00 -e 03:00
00:00:01      DEV      tps     rkB/s    wkB/s    areq-sz   aqu-sz  await   %util
00:10:01      nvme0    234     45.67   2345.67     12.34     8.45    35.67   89.23  <-- очередь 8, await 35ms
00:20:01      nvme0    245     23.45   2567.89     13.45     9.23    38.12   92.45
00:30:01      nvme0    256     34.56   2789.12     14.56    10.34    40.23   94.56

# Видим: nvme был под нагрузкой в это время, await 35-40 мс при норме 0.5 мс
# Что-то пишет 2.5 МБ/с уже долго

# 3. Сетевая активность для контекста:
$ sar -n DEV -s 00:00 -e 03:00 | grep eth0

# 4. Память:
$ sar -r -s 00:00 -e 03:00

# Часто после такого: понимание что backup job шёл в полночь, конкурент диска с ETL

free -h vs vmstat -s vs /proc/meminfo

Три способа смотреть память:

# Quick:
$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        18Gi       2.7Gi       145Mi        10Gi        12Gi
Swap:          8.0Gi          0B       8.0Gi

# Snapshot detail:
$ vmstat -s | head -10
     32985856 K total memory
     19234176 K used memory
       654321 K active memory      <-- active LRU pages
      8765432 K inactive memory    <-- candidate for reclaim
      3145728 K free memory
       124356 K buffer memory
      9821456 K swap cache

# Полные детали:
$ cat /proc/meminfo | head -30
MemTotal:       32985856 kB
MemFree:         3145728 kB
MemAvailable:   12345678 kB
Buffers:          124356 kB
Cached:          9821456 kB
SwapCached:           0 kB
Active:           654321 kB
Inactive:        8765432 kB
Active(anon):     345678 kB        <-- private (heap, stack)
Inactive(anon):    98765 kB
Active(file):     308643 kB        <-- file-backed (page cache)
Inactive(file):  8666667 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       8388604 kB
SwapFree:        8388604 kB
Dirty:              5678 kB        <-- dirty pages (need writeback)
Writeback:             0 kB        <-- сейчас flushing на диск
AnonPages:        444443 kB
Mapped:            123456 kB
Shmem:             67890 kB
Slab:             567890 kB        <-- kernel data structures
SReclaimable:     345678 kB
SUnreclaim:       222212 kB
KernelStack:        8192 kB
PageTables:        12345 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    24881532 kB
Committed_AS:    1234567 kB

/proc/meminfo — источник для всех остальных утилит.


Попробуй сам

# 1. vmstat 1 -- live observation:
vmstat 1
# Ctrl-C чтобы остановить, читать колонки

# 2. iostat расширенный:
iostat -xz 1
# или (новый формат):
iostat -xz -h 1

# 3. Сразу взглянуть и swap, и memory:
vmstat -s | head -25

# 4. Что в /proc/meminfo:
cat /proc/meminfo | head -20

# 5. Активность диска прямо сейчас:
sudo iotop -o    # активные процессы

# 6. Если sysstat не стоит -- поставить:
sudo apt install sysstat
sudo systemctl enable --now sysstat
# Через 10 минут данные начнут собираться

# 7. Sar archive (если уже работает):
sar -u | head -10   # CPU за сегодня
sar -r | head -10   # memory
sar -d -p | head -20   # disks

# 8. Простой тест disk performance:
sudo hdparm -t /dev/sda    # sequential read
# Или универсально:
dd if=/dev/zero of=/tmp/test bs=1M count=1024 conv=fdatasync
rm /tmp/test

Проверка знанийKnowledge check
vmstat 1 показывает: r=2, b=8, free=300M, si=2048, so=4096 каждую секунду. wa=45%. Что происходит и как починить?
ОтветAnswer
Это severe memory pressure. Разбор по колонкам: 1. b=8 -- 8 процессов блокированы на IO. Это много, что-то висит. 2. si=2048 (kB/s), so=4096 (kB/s) -- активный swap traffic! 2 МБ читается из swap, 4 МБ записывается в swap каждую секунду. Это означает: 1) памяти физически не хватает; 2) kernel постоянно swap-в/swap-аut страницы; 3) приложения зависают на disk-latency (swap = диск). 3. free=300M -- очень мало свободной памяти. Хотя на Linux это часто OK (buff/cache reclaimable), в нашем случае si/so активны -- значит реально кончилась. 4. wa=45% -- CPU большую часть времени ждёт IO. IO здесь -- swap-операции и потенциально обычные user IO. Это 'thrashing': система больше времени тратит на swap-перемещения, чем на полезную работу. Приложения тормозят катастрофически. Диагностика: 1. free -h -- увидеть полные числа. total used free buff/cache available Если available очень маленькое и swap used > 0 -- подтверждение. 2. cat /proc/meminfo | grep -i 'commit\|anon\|swap': Committed_AS показывает, сколько обещано приложениям (даже если они не все touch). AnonPages -- сколько частной памяти (heap процессов). 3. Найти жора: ps aux --sort=-%mem | head или top, Shift+M Часто один процесс ест в разы больше чем остальные. 4. dmesg | tail: Может уже видеть 'oom-killer' активности. Или 'task X swapping heavily'. 5. cat /proc/<pid>/oom_score для подозреваемых процессов -- какой kernel убьёт первым при OOM. Острая чинка: 1. Если есть memory leak в приложении -- restart: systemctl restart <service> Освободит память. 2. Если просто overcommit -- убить наименее нужное: kill -9 <pid> Лучше systemctl stop <не-критичное>. 3. Если есть buff/cache -- echo 3 > /proc/sys/vm/drop_caches Освободит page cache (но это самопонятно, kernel и так был бы за reclaim). Долгосрочная чинка: 1. Добавить RAM физически. Single best solution. 2. Уменьшить footprint приложений: limit Java/Python heap, reduce worker count, smaller batches. 3. Использовать MemoryMax= в systemd units -- предотвращать одно приложение от поглощения всей памяти. 4. Tune /proc/sys/vm/swappiness -- 10 значит 'свопить только если совсем некуда' (по умолчанию 60). Не решает проблему, но даёт больше времени. 5. Если это short-term spikes (раз в день) -- увеличить swap (2x RAM). Если постоянно -- больше RAM единственное решение. 6. Мониторинг + alerts -- swap usage > 100MB должен alarm. 7. Если оba: проверить, не сидит ли два прожорливых сервиса на одной VM -- разнести по разным. Кстати, на serious production-системах swap часто выключают совсем (swapoff -a) -- лучше получить OOM-kill немедленно, чем долгое thrashing. Зависит от workload. Для container-orchestrators (k8s) swap обычно требуется off.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. vmstat 1 показывает b=10 регулярно. Что это значит?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5