Если сайт «подвисает», очереди растут, а загрузка CPU выглядит странно низкой — часто виноват не ваш код и не база, а CPU steal time. Это типичная история для виртуализации: ваш Linux в виртуальной машине готов выполнять задачи, но физическое CPU-время в этот момент получает кто-то другой (соседи на хосте). В результате вы видите деградацию производительности, которая почти не лечится оптимизацией приложения, потому что узкое место выше — на уровне гипервизора.
Ниже — практическая инструкция для админов: как увидеть steal в top/vmstat/mpstat, чем он отличается от iowait, как подтвердить проблему метриками и какие действия реально помогают.
Что такое CPU steal time и почему он появляется
CPU steal (steal time, обычно метрика st) — доля времени, когда виртуальный CPU вашей VM был готов исполнять задачи, но не получил физическое CPU-время: гипервизор отдал слоты исполнения другим виртуальным машинам.
Упрощённо: «ядра» в тарифе есть, но в конкретные моменты реальная вычислительная мощность становится меньше из‑за конкуренции на хост-ноде.
Типичные причины
- Noisy neighbor: соседняя VM активно грузит CPU (бэкапы, компиляция, индексации, тяжёлые запросы и т. п.).
- Переподписка CPU на ноде: суммарно vCPU продано больше, чем физических, и планировщик вынужден резать доступное время.
- Хост под давлением: обслуживание, миграции, фоновые задачи платформы, неудачное размещение по NUMA.
- Совпадение пиков: у вас и у соседей нагрузка «встретилась» в одно окно.
Steal — это не «у вас 100% CPU». Это «у вас есть работа, но CPU вам не дают». Поэтому симптомы часто выглядят как необъяснимые задержки при вроде бы умеренной загрузке.
Как steal time проявляется в реальной работе
Чаще всего steal ловят не по «процентам CPU», а по задержкам. Типовые эффекты:
- рост времени ответа веба/API без явного роста
us/sy; - рывки latency: то нормально, то резко хуже;
- увеличение очередей (backlog воркеров, очередь PHP-FPM, рост времени cron);
- таймауты в прокси/балансере из‑за внезапных пауз на бэкенде;
- нестабильные бенчмарки: одинаковый прогон то быстрый, то заметно медленнее.
Если вы используете контейнеры, обязательно держите в голове альтернативную причину — CPU throttling из-за лимитов. У нас на Fastfox есть отдельная памятка, как быстро проверять лимиты systemd и контейнеров: лимиты CPU/памяти в systemd и их симптомы.

Быстрая диагностика: top, vmstat, mpstat
Начнём с базовых инструментов, которые есть почти везде. Ваша цель — увидеть st именно в то окно, когда сервис «плывёт».
1) top: ищем %st
В top steal отображается как st в строке CPU:
top
Смотрите на:
- %st — steal time;
- %id — idle (важно: на уровне гостя CPU может выглядеть «праздным», но задержки при этом растут);
- load average — может расти, потому что runnable-задачи ждут слоты исполнения;
- динамику: разовые всплески или постоянный фон.
Практическая эвристика по st:
- 0–1% — обычно норма;
- 2–5% — уже заметно на latency‑чувствительных сервисах;
- 10%+ — почти наверняка будет больно;
- 20–30%+ — сервис может «умирать» на пиках даже при нормальном коде.
2) vmstat: st по интервалам
vmstat удобен тем, что показывает картину по секундам:
vmstat 1
В конце строки есть блок CPU: us sy id wa st. Нас интересует st.
Как читать вместе с остальными полями:
r(run queue) растёт,us/syне растут, ноstесть — похоже на дефицит CPU из-за гипервизора.wa(iowait) высокий — это уже больше про диск/сетевое хранилище, а не про steal.
3) mpstat: по всем vCPU
Для более точной картины используйте mpstat (пакет sysstat):
mpstat -P ALL 1
Это полезно, когда у вас много vCPU и steal «размазан», либо нагрузка неравномерная по ядрам.
Steal vs iowait vs «мне не хватает CPU»: как не перепутать
Фраза «тормозит — значит CPU» часто уводит в сторону. Важно различать три похожие по ощущениям истории.
1) Steal vs обычная высокая загрузка CPU
Если CPU действительно занят вашим кодом, обычно:
- растут
us/sy; - видно стабильные CPU-hungry процессы;
stоколо нуля (или незначительный).
Если же высокий steal, наблюдается «парадокс»: очереди и latency растут, а us/sy не выглядят катастрофическими — потому что гостю просто не дают исполняться.
2) Steal vs iowait
iowait (wa) — ожидание завершения ввода‑вывода: медленный диск, перегруженное хранилище, очередь fsync у базы, storage throttling.
Признаки iowait:
waвысокое,stнизкое;- много процессов в D-state;
- есть корреляция с дисковыми метриками/запросами к БД.
Признаки steal:
stзаметно растёт при просадке скорости;- очереди растут без явной «дисковой» картины;
- время выполнения CPU‑bound операций скачет.
3) Steal vs CPU throttling в контейнерах
CPU throttling из-за лимитов (cgroup quota) может давать очень похожие симптомы: воркеры «не успевают», p95/p99 растут, но st при этом может быть низким. Если у вас Docker/Kubernetes или сервисы под systemd с ограничениями — сначала проверьте лимиты и факты троттлинга (ссылка выше на разбор systemd‑лимитов поможет).
Мини-лаборатория: как подтвердить влияние steal на производительность
Чтобы перестать гадать, полезно сделать две вещи: (1) зафиксировать steal в момент деградации, (2) проверить, как ведут себя простые CPU-bound операции.
Снимок метрик по времени (5–10 минут)
Запустите параллельно (в отдельные окна/сессии):
vmstat 1
mpstat -P ALL 1
Если установлен sysstat, добавьте:
pidstat -u 1
Идея: увидеть, что процессы не выглядят «на 100% CPU» по us/sy, но сервис тормозит, а st скачет.
Простейший CPU-bound тест (аккуратно)
На проде бенчмарки делайте осторожно. Но лёгкая проверка иногда помогает: запустите кратковременную CPU‑bound команду и сравните время выполнения в разные периоды.
/usr/bin/time -p bash -c 'i=0; while [ $i -lt 20000000 ]; do i=$((i+1)); done'
Запустите 3–5 раз в «нормальное» время и 3–5 раз в момент лагов, параллельно глядя на st в vmstat. Если время выполнения гуляет в разы и это совпадает со steal — у вас сильный аргумент.
Не делайте агрессивные стресс‑тесты на рабочей базе/вебе. Наша цель — наблюдение и корреляция, а не «уложить» сервер.

Что делать, если steal высокий: пошаговый план
Дальше — практические действия. Важно разделить: что вы можете исправить внутри VM, а что требует вмешательства провайдера/платформы.
Шаг 1. Убедитесь, что это именно steal, а не ваша нагрузка
- Соберите 10–15 минут
vmstat/mpstatв момент проблемы. - Проверьте, нет ли пиков
us/syот ваших задач (cron, бэкапы, ротации, индексации). - Если пики совпадают с вашим cron — возможно, вы сами создаёте нагрузку, и это не noisy neighbor.
Шаг 2. Снизьте «взрывную» конкурентность у себя
Даже если первопричина — переподписка CPU, вы можете уменьшить ущерб от steal, сгладив пики:
- Ограничьте параллелизм воркеров/обработчиков, чтобы не создавать «шквал» runnable задач.
- Разнесите cron: тяжёлые задания не должны стартовать в одну минуту.
- Переоцените лимиты на уровне приложений: иногда меньше потоков = меньше контеншен = ниже p99.
Идея простая: когда CPU «урезают», лучше иметь управляемую очередь, чем 200 одновременно конкурирующих процессов.
Шаг 3. Проверьте, не усугубляет ли ситуацию троттлинг по cgroup
Если вы в контейнерах, убедитесь, что проблема не в CPU quota. В этом сценарии «лечится» настройкой limits/requests и профилированием приложения, а не переносом VM.
Шаг 4. Соберите данные для обращения в поддержку
Если вы уверены, что это steal/oversubscription, подготовьте факты:
- временной интервал проблемы (с точностью до минут) и часовой пояс;
- вывод
vmstat 1иmpstat -P ALL 1(несколько десятков строк) в момент деградации; - симптомы на сервисе: таймауты, рост p95/p99, рост очередей воркеров;
- подтверждение, что ваши cron/бэкапы/ротации не создавали аномальных CPU‑пиков в это время.
Так провайдеру проще сопоставить вашу жалобу с телеметрией хоста и историей загрузки ноды.
Шаг 5. Тактические и стратегические решения
Если steal — редкий всплеск, иногда достаточно пережить окно или перенести тяжёлые задачи. Но если steal — постоянный фон, это системная проблема размещения.
- Миграция на другую ноду (переезд VM на менее загруженный хост).
- Тариф с более предсказуемыми ресурсами (меньше переподписка, выше гарантии).
- Увеличение числа vCPU иногда помогает, но не всегда: если на ноде жёсткий дефицит CPU, steal может сохраниться.
- Разделение ролей: вынесите БД/очереди/критичный API на отдельную VM, чтобы деградация не «роняла» всё сразу.
Частые вопросы и грабли
Почему load average растёт, а CPU не на 100%?
Потому что load average учитывает runnable задачи (которые хотят CPU). При steal задачи готовы работать, но им не дают слоты исполнения. В итоге очередь растёт, а us/sy может выглядеть умеренно.
Может ли steal быть из-за «плохого» приложения?
Косвенно — да: если сервис делает резкие пики CPU и конкурирует сам с собой, а затем попадает в период нехватки CPU на хосте, эффект будет сильнее. Но сам steal — это характеристика планирования CPU на уровне гипервизора.
Какие сервисы наиболее чувствительны к steal?
- веб/API с требованиями к p99 latency;
- базы данных и кеши под нагрузкой;
- очереди задач, где важен предсказуемый runtime воркера;
- SSL-терминация и шифрование при высоком RPS;
- любые CPU‑bound задачи (рендер, конвертация, аналитика).
Короткий чеклист: steal time за 5 минут
- Смотрите
%stвtop. - Запустите
vmstat 1и подтвердите ростstво время лагов. - Проверьте
mpstat -P ALL 1, чтобы увидеть картину по ядрам и по интервалам. - Отделите steal от
wa(iowait) и от CPU throttling в контейнерах. - Соберите лог‑вывод и временные метки для обращения в поддержку/миграции.
Итог простой: CPU steal — один из самых неприятных и при этом хорошо диагностируемых источников нестабильной производительности в виртуализации. Чем быстрее вы научитесь замечать st и связывать его со всплесками задержек, тем меньше времени уйдёт на «оптимизацию не того места».
Если вы выбираете площадку под проекты, где важна предсказуемость latency, разумно закладывать запас по CPU и не гнаться за «максимум vCPU за минимум денег». В качестве ориентира можно начать с подбора тарифа под профиль нагрузки: как выбрать VDS по CPU и RAM под реальные задачи.
Для проектов, которым нужен отдельный контур и контроль над ресурсами, часто удобнее сразу брать VDS с подходящей конфигурацией и мониторингом, чтобы ловить steal и другие аномалии по графикам, а не по жалобам пользователей.


