kai.kzLab

Высокий load average в Linux: что он показывает на самом деле и как найти причину

Команда KAI Lab · · 9 мин чтения

Load average в Linux — это среднее число задач, которые выполняются или ждут процессор (состояние R), плюс задач в непрерываемом ожидании, чаще всего диска (состояние D), за 1, 5 и 15 минут. Высокое значение — ещё не диагноз: сравните его с числом ядер (nproc) и посмотрите в top или vmstat, чем заняты процессоры — работой (us, sy) или ожиданием ввода-вывода (wa).

Отсюда главная ошибка новичка: увидеть load 11 и решить, что «процессор не вывозит». На сервере из примера ниже процессоры простаивают больше чем на 80%, а тормозит всё из-за диска. Разберём, как отличить одно от другого за пять минут.

Что такое load average на самом деле

Три числа в uptime и top берутся из /proc/loadavg. Документация ядра описывает их как число задач в очереди на выполнение (R) или в ожидании дискового ввода-вывода (D), усреднённое за 1, 5 и 15 минут.

Три детали, без которых цифры легко понять неправильно:

  • Это не проценты и не нормировано на ядра. В man uptime прямо сказано: load 1 на одноядерной машине означает, что она была занята всё время, а на четырёхъядерной — что простаивала 75% времени.
  • Считаются потоки, а не процессы. Java-сервис с сотней потоков, которые застряли на диске, добавит к load сотню.
  • Это не среднее арифметическое. Ядро считает экспоненциально сглаженное значение. Брендан Грегг показал на опыте: если на простаивающей машине запустить один поток, который крутится в цикле, «минутный» load через минуту дойдёт только примерно до 0,62.

Почему в Linux в load попадает ожидание диска? Это решение 1993 года: Маттиас Урлихс прислал патч, потому что процессы, которые ждут медленного свопа или диска, тоже нагружают систему. Изменение вошло в Linux 0.99 patchlevel 14. С тех пор load average в Linux — нагрузка на систему целиком, а не только на процессор, и в других ОС он может считаться иначе.

Симптом → команда → что смотреть

СимптомКомандаЧто смотреть
Load выше числа ядерnproc, uptimeво сколько раз load больше числа ядер и растёт ли он: минутное значение против 15-минутного
Подозрение на CPUtop, клавиша Pus и sy в строке %Cpu(s), процессы с большим %CPU
CPU простаивает, а load высокийvmstat 1r — очередь к процессору, b — ждут ввода-вывода, wa — простой в ожидании диска
Подозрение на дискiostat -x 5%util, r_await и w_await, aqu-sz
Кто нагружает дискpidstat -d 5процессы с большими kB_rd/s и kB_wr/s
Процессы «висят»ps -eo state,pid,user,commстроки с состоянием D
Виртуалка тормозит без видимой нагрузкиvmstat 1st — время, которое забрал гипервизор
Нужна точная картина ожиданийcat /proc/pressure/iosome avg10 — доля времени, когда задачи ждали ввода-вывода

Шаг 1. Сравните с числом ядер

$ uptime
 03:14:07 up 23 days,  5:17,  1 user,  load average: 11.37, 10.92, 7.85
$ nproc
4
$ cat /proc/loadavg
11.37 10.92 7.85 1/423 91544

Load почти втрое выше числа ядер, и он растёт: минутное значение больше 15-минутного, значит проблема началась недавно и не прошла. Если бы было наоборот — 3, 7, 11, — нагрузка уже спадала бы.

Четвёртое поле /proc/loadavg — 1/423: прямо сейчас в состоянии «готов выполняться» одна задача из 423. При load 11 это подсказка: основную часть load дают не очередь к процессору, а задачи в D.

Шаг 2. top: работа или ожидание

$ top
top - 03:14:07 up 23 days,  5:17,  1 user,  load average: 11.37, 10.92, 7.85
Tasks: 191 total,   1 running, 190 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.6 us,  2.3 sy,  0.0 ni, 12.3 id, 82.7 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :   7937.6 total,    402.6 free,   1568.3 used,   5966.7 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   6071.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  81234 backup    20   0   15432   4120   2984 D   2.3   0.1   0:41.17 rsync
  90312 postgres  20   0  223440  61512  58436 D   1.0   0.8   0:12.40 postgres
    412 root      20   0       0      0      0 D   0.3   0.0   3:02.51 jbd2/vda1-8
   2187 app       20   0 3542116 912344  21480 S   0.7  11.2  82:14.03 java

Строка %Cpu(s) отвечает на главный вопрос. Пользовательский код (us) и ядро (sy) вместе занимают меньше 5%. Зато wa — 82,7%: процессорам нечего делать, пока не закончится ввод-вывод. В столбце S у верхних процессов D — непрерываемое ожидание.

Если бы картина была другой — us под 90%, wa около нуля, — это настоящая нехватка процессора. Тогда в top нажмите P, чтобы отсортировать по %CPU, и разбирайтесь с верхним процессом.

Шаг 3. vmstat: очередь к процессору или к диску

$ 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
 0  0      0 412304  81220 6027816    0    0    35   212  310  590  2  1 96  1  0
 1 13      0 409880  81228 6029544    0    0   412 41236 2984 5710  2  2 13 83  0
 0 14      0 410512  81236 6031012    0    0   388 39880 2901 5602  3  2 12 83  0
 1 14      0 408992  81240 6032384    0    0   520 40412 3012 5840  3  3 11 83  0
 0 13      0 407420  81252 6034120    0    0   402 39120 2890 5588  2  2 13 83  0

Первая строка — средние с момента загрузки, смотрите со второй. Столбец r — задачи, которые выполняются или ждут процессор: 0–1. Столбец b — заблокированные в ожидании ввода-вывода: 13–14. Это и есть наш load. Запись на диск (bo) — около 40 МБ/с, в свопе (si, so) нули, значит память ни при чём.

Как читать vmstat быстро:

  • r стабильно больше числа ядер — не хватает процессора;
  • растёт b и wa — упёрлись в диск или сетевое хранилище;
  • ненулевые si и so — система свопится, это проблема памяти, а диск страдает как следствие;
  • заметный st на виртуалке — гипервизор отдаёт ваши такты соседям. Внутри машины это не лечится: к провайдеру или на другой тип инстанса.

Шаг 4. iostat: упёрлись ли в диск

$ iostat -xy 5 1
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.61    0.00    2.35   82.72    0.00   12.32

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda             12.40    196.00     0.00   0.00   12.35    15.81  806.20  40212.80    37.00   4.39   96.40    49.88    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00   77.87 100.00

Флаг -y пропускает отчёт со средними с момента загрузки. Что здесь важно:

  • w_await 96 мс — столько в среднем ждёт каждая запись, включая время в очереди. Для SSD нормальные значения — единицы миллисекунд;
  • aqu-sz около 78 — средняя длина очереди запросов к устройству;
  • %util 100 — устройство было занято всё время.

С %util осторожно. В man iostat оговорено: для устройств, которые обслуживают запросы параллельно, — RAID и современных SSD — 100% не означает предел. Смотрите на рост await и очереди: если запросы ждут всё дольше, диск не справляется.

Шаг 5. Кто именно ждёт и кто пишет

Процессы в состоянии D:

$ ps -eo state,pid,user,comm | awk '$1 == "D"'
D     412 root     jbd2/vda1-8
D   81234 backup   rsync
D   90312 postgres postgres
D   90318 postgres postgres

jbd2 — поток журнала ext4, он ждёт вместе со всеми. Чтобы увидеть и потоки, добавьте флаг -L. А кто создаёт нагрузку, покажет pidstat -d:

$ pidstat -d 5 1
03:15:07      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
03:15:12        0       412      0.00    302.40      0.00       0  jbd2/vda1-8
03:15:12       34     81234      0.00  33917.60      0.00       0  rsync
03:15:12      113     90312    184.80   5992.00      0.00       0  postgres

Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
Average:        0       412      0.00    302.40      0.00       0  jbd2/vda1-8
Average:       34     81234      0.00  33917.60      0.00       0  rsync
Average:      113     90312    184.80   5992.00      0.00       0  postgres

Картина сложилась: ночной бэкап через rsync пишет около 33 МБ/с на тот же диск, где живёт база. Облачный диск упёрся в свой лимит, запросы PostgreSQL встали в общую очередь, и приложение тормозит вместе с ними. Столбец iodelay покажет нули, пока в ядре не включён учёт задержек (kernel.task_delayacct), — это нормально.

Отдельный случай: процессы в D, а iostat показывает спокойный диск. Тогда проверьте сетевые хранилища. Если NFS-сервер перестал отвечать, в dmesg будет строка вида nfs: server 10.0.0.5 not responding, still trying, а процессы, которые туда обращаются, повиснут в D и поднимут load.

Что делать, когда причина найдена

Нагрузку создаёт фоновая задача. Перенесите её на время, когда сервис меньше нагружен, или на другой диск. Задачу, запущенную через systemd, можно ограничить по скорости записи — это работает через cgroup v2:

# /etc/systemd/system/backup.service.d/io.conf
[Service]
IOWriteBandwidthMax=/dev/vda 15M
CPUQuota=50%

После правки — sudo systemctl daemon-reload. ionice -c3 тоже бывает полезен, но приоритеты ввода-вывода поддерживают только планировщики bfq и mq-deadline. Текущий виден в /sys/block/vda/queue/scheduler; с планировщиком none ionice ничего не изменит.

Процессору правда не хватает. Найдите процесс в top, выясните, нормальная ли это нагрузка. Если нормальная — масштабируйтесь или ищите медленный код. Если нет — это баг, который надо чинить, а не маскировать дополнительными ядрами.

Свопится. Load и диск здесь следствие, а причина — память. Смотрите, кто её съел, и проверяйте лимиты. Про то, как ядро убивает процессы при нехватке памяти, — в статье OOMKilled и код 137.

Диск просто заполнен. Переполненная файловая система тоже даёт странные задержки и ошибки записи; порядок диагностики — в статье закончилось место на диске.

PSI: что показывает точнее load average

С Linux 4.20 в ядре есть Pressure Stall Information — доля времени, которую задачи потеряли в ожидании процессора, памяти или ввода-вывода:

$ cat /proc/pressure/io
some avg10=78.41 avg60=74.02 avg300=51.33 total=1830447711
full avg10=61.20 avg60=58.77 avg300=40.16 total=1422118093
$ cat /proc/pressure/cpu
some avg10=1.12 avg60=0.98 avg300=0.87 total=402211934
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

some — доля времени, когда хотя бы одна задача ждала ресурс; full — когда ждали все активные задачи одновременно. Здесь за последние 10 секунд задачи ждали ввода-вывода 78% времени, а процессора — около 1%. Ответ тот же, что дали top, vmstat и iostat, но одной командой и уже в процентах.

Нужен ли алерт на load average

Будить человека из-за одного load average — плохая идея. Load 20 на 32 ядрах — обычный рабочий день, а load 3 на двух ядрах при зависшем NFS — авария. Алерт должен срабатывать на то, что чувствуют пользователи: задержки и ошибки. А load, wa и PSI — это то, что открывает дежурный, когда алерт уже пришёл. Как выбирать такие сигналы, — в статье SLO, SLI и бюджет ошибок.

Вопрос «что такое load average и почему он высокий при простаивающем процессоре» — классика собеседований по Linux. Ответ из этой статьи укладывается в минуту: R плюс D, сравнить с ядрами, посмотреть wa.

Во втором месяце симулятора DevOps KAI Lab есть тикет «Сервер файлов загружен на 350%»: пользователи жалуются, что фото товаров грузятся по десять секунд, и причину нужно найти по процессам на живом сервере, а не перезагрузкой. Консоль отвечает реальными выводами команд, поэтому порядок из этой статьи там можно пройти руками.

Частые вопросы

Какой load average считается нормальным? Универсального порога нет. Ориентир — число ядер из nproc: load стабильно выше этого числа говорит, что задачам приходится ждать. Но важнее, чего именно они ждут: процессора или диска.

Почему load average высокий, а процессор свободен? В Linux load учитывает задачи в состоянии D — обычно они ждут диск или сетевое хранилище. Проверьте wa в top, столбец b в vmstat и iostat -x.

Что такое iowait? Доля времени, когда процессор простаивал, а в системе был незавершённый запрос к диску. Высокий wa не значит, что процессор занят, — наоборот, он ждёт.

Показывает ли load average загрузку CPU в процентах? Нет. Это среднее число задач, а не процент. Load 4 на четырёх ядрах — полная занятость, на одном ядре — очередь из трёх задач сверх того, что процессор успевает выполнить.

Почему минутное значение не падает сразу после того, как нагрузка ушла? Load average — экспоненциально сглаженная величина, а не среднее за последнюю минуту. После всплеска значения снижаются плавно, и 15-минутное держится дольше всех.

Источники

Читать дальше