Короткий ответ
Load average — очередь, не «проценты CPU». Сначала разберите, какой счётчик красный: %usr, %sys, %iowait, %irq, %steal. iowait лечат диск/NFS, не kill -9 PHP. steal — гипервизор, не гостевой nginx. Только после типа нагрузки ищите PID через pidstat/top. Reboot сбрасывает улики и не чинит цикл, который поднимется снова.
Хост host.example (10.0.20.10), пользователь admin. Пакет sysstat даёт mpstat/pidstat — поставьте его заранее, не в инцидент.
Симптомы и как отличить
uptimeпоказывает load 40 на 4 vCPU;- htop красный,
Stealколонка ненулевая; - приложение «висит», CPU в
topпочти нулевой — это не эта статья, это I/O lock или зависание; - после cron по ночам всплеск — смотрите cron и бэкапы.
| Метрика | Смысл | Не делайте |
|---|---|---|
| %usr | код процесса | reboot |
| %sys | ядро, syscalls, сеть | отключать firewall «навсегда» |
| %iowait | CPU ждёт диск | kill случайных PID |
| %steal | гипервизор забрал CPU | апгрейд nginx в госте |
| %soft | softirq, сеть | без ss/nstat |
Возможные причины
- Запросный шторм приложения (usr): бесконечный цикл, regex, json.
gzip/gpg/mysqldumpбезnice/ionice.- kswapd и сжатие памяти — уже RAM/swap.
- Журналы на медленном диске, journald — iowait.
- Steal на перепроданном VPS.
unattended-upgrades+needrestart+aptв рабочее время.- Редко: IRQ шторм NIC, soft lockup — граница с hang.
Диагностика
1. Ядра и load
nproc
lscpu | grep -E 'Model name|CPU\(s\)|Hypervisor'
uptime
cat /proc/loadavgСравните 1/5/15 минут: пик одной минуты vs плато 15 минут.
2. Тип CPU
mpstat -P ALL 1 5
vmstat 1 10Читайте us sy id wa st. На Ubuntu без sysstat: top и клавиша 1 по ядрам.
3. Кто ест usr/sys
pidstat -u 1 5
ps aux --sort=-pcpu | head -n 15
top -b -n 1 -o %CPU | head -n 20Для потоков: pidstat -t -p <pid> 1 3. Java без имён потоков — jstack уже в зоне приложения.
4. iowait
iostat -xz 1 5
pidstat -d 1 5
df -hВысокий await и %util на одном устройстве: тот диск. Если это / забитый логами — диск.
5. Steal и соседи
В госте:
mpstat 1 5 | awk '/Average/ {print}'
dmesg -T | grep -i steal | tailНа гипервизоре (если ваш) смотрите CPU overcommit. Внутри Ubuntu steal не вылечить systemctl restart.
6. Короткий perf (если пакет linux-tools установлен)
sudo perf top -g --delay 50Не оставляйте perf record на часы на проде без лимита размера.
systemctl status $(ps -o pid= -C nginx | head -n 1)
systemd-cgtop -n 1Решение
Сценарий A. Понятный пользовательский процесс
Ограничьте, не убивайте вслепую: systemctl set-property app.service CPUQuota=200% (временно), либо остановите job (бэкап) штатно. Для одноразового gzip — kill -TERM после подтверждения, что это тот PID.
Сценарий B. iowait из‑за логов/диска
Ротация, vacuum journal, перенос I/O. Reboot не ускоряет диск.
Сценарий C. Steal
Миграция VM, резерв CPU, меньше соседей. В госте можно только снизить нагрузку.
Сценарий D. kswapd / высокая sys при нехватке RAM
Идите в статью про RAM и OOM. Добавление «ещё PHP-FPM children» ухудшит.
Сценарий E. Нужен профиль на 30 секунд
sudo timeout 30 perf record -g -a -o /tmp/perf.data
sudo perf report --stdio | headСнимите файл в заявку, не интерпретируйте один swapper как виновника.
Как не перепутать steal, guest и «надо больше vCPU»
В KVM колонка st в vmstat/mpstat — время, которое гипервизор не дал vCPU. Внутри гостя nginx innocent. Лечение: меньше CPU overcommit, CPU pinning, миграция на другой хост. Добавление workers PHP увеличит очередь и steal.
На 24.04 systemd-cgtop показывает CPU% по unit — удобно, когда top полон потоков java. Для user-сессии admin тяжёлый rsync живёт в user-1000.slice и выглядит как «система тормозит», хотя это один человек.
Краткий профиль без perf, если linux-tools нет в политике:
cat /proc/$(pidof -s nginx)/sched
grep -H . /proc/$(pidof -s nginx)/status | grep -E 'PPid|Threads|voluntary'
ls /proc/$(pidof -s nginx)/task | wc -lДля iowait на md/RAID смотрите cat /proc/mdstat и iostat -x md0. Rebuild массива даёт высокий wait при скромном usr — reboot только прервёт rebuild.
Если load высокий ночью ровно в 6:25 — это /etc/crontab run-parts, не DDoS. Снимите pidstat в это окно и сравните с cron.
nproc в контейнере может показывать ядра хоста при cgroup CPUQuota. Смотрите cat /sys/fs/cgroup/cpu.max (cgroup v2 на Ubuntu 22.04/24.04 по умолчанию). Load 16 при quota 100% одного CPU — нормальная очередь, не «сломался scheduler».
На госте с cpu cfs quota колонка %idle в mpstat может быть высокой при огромном load: процессы runnable ждут квоты, это не iowait. Смотрите /sys/fs/cgroup/cpu.stat поле nr_throttled. Если throttled растёт — увеличивать quota или снижать concurrency, не reboot.
Как проверить, что проблема устранена
uptime
mpstat 1 5
pidstat -u 1 3
ssh -o ConnectTimeout=5 admin@10.0.20.10 trueLoad 15-минутный падает медленно — смотрите 1-минутный и %idle. Функциональный запрос к приложению должен уложиться в обычный SLA.
Если не помогло
- CPU низкий, всё равно «висит»: сервер зависает, locks, D-state.
- После kill нагрузка на другом PID — оркестратор поднимает реплики, чините причину трафика.
soft lockupв dmesg — hang/NMI, не «просто CPU».- Нагрузка только в IRQ:
cat /proc/interrupts, очередь NIC, не apt.
Профилактика
- Базовый
sysstat(sar), экспорт node-exporter: cpu/iowait/steal отдельно. CPUAccounting=yesна тяжёлых unit.- Окна бэкапа не в пик пользовательской нагрузки.
- Лимиты cgroup в юнитах, не надежда на «диск большой».
FAQ
Load 100 при 4 ядрах — это 2500% CPU?
Нет. Load — длина очереди.runnable+uninterruptible. При iowait очередь растёт без 100% usr.
Нужен ли nice -n 19 всем cron?
Для тяжёлых job — да, плюс ionice -c3. Не nice'айте sshd.
Почему htop показывает 400%?
Сумма по потокам. Делите на nproc.
Можно ли отключить SMT против нагрузки?
Не как лечение инцидента. Это решение про латентность/безопасность на железе, не про runaway PHP.
perf запрещён политикой?
Тогда pidstat, /proc/<pid>/stack, bpftrace если разрешён. Reboot всё ещё не диагностика.