Что такое CPU steal time на VPS и как его проверить
Узнайте, как интерпретировать показатель st в выводе команды vmstat. Разберитесь, как отличить нехватку ресурсов вашего сервера от влияния шумных соседей на хосте виртуализации.
Что на самом деле измеряет CPU steal time
CPU steal time — это доля времени, в течение которого ваш виртуальный процессор был готов к выполнению задач, но гипервизор отдал физическое ядро другому гостю. Работа была поставлена в очередь. Ядро было занято чем-то другим. Linux учитывает эти циклы отдельно и отображает их как st. Именно так вы отличаете ситуацию «мой сервер занят» от ситуации «мой сервер ждет своей очереди».
Эта разница — единственная причина существования данного счетчика. Время, которое ваши процессы проводят на процессоре, отображается как us (user) или sy (system). Время, в течение которого задача заблокирована ожиданием дисковых операций, отображается как wa (I/O wait). vCPU (виртуальный процессор), который готов к работе, находится в очереди выполнения, не имеет активных операций ввода-вывода, но при этом не исполняется, отображается как st. Ничто внутри вашего сервера не может изменить это состояние, так как решение о планировании принимается на уровень ниже — на хосте.
Это прямое следствие того, как VPS делит одну физическую машину между множеством гостей. Обычная причина — «сосед»: другой гость на том же узле создает высокую нагрузку, поэтому хост распределяет ядра между вами. Существует вторая причина, которую часто упускают из виду. Многие провайдеры ограничивают производительность общего vCPU долей физического ядра, и на ряде гипервизоров это принудительное ограничение учитывается внутри гостевой системы как steal. Таким образом, высокое значение st говорит вам лишь о том, что ядро не было предоставлено вам. Оно не всегда указывает на то, кто именно его занял.
Откуда берется значение steal
Ваше ядро не может самостоятельно измерить steal, так как оно не «видит» хост. Эту информацию предоставляет гипервизор. В KVM хост записывает счетчик для каждого vCPU на страницу, общую с гостевой системой, а гостевая ОС суммирует эти данные, если ядро собрано с параметром CONFIG_PARAVIRT_TIME_ACCOUNTING (это стандарт для ядер всех дистрибутивов). Xen передает те же данные через область runstate. Итоговое значение попадает в пространство пользователя только из одного источника:
head -1 /proc/statСтрока cpu содержит десять счетчиков в тиках USER_HZ с момента загрузки в следующем порядке: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Steal — это восьмое значение после метки. Все инструменты, перечисленные ниже, vmstat, top, mpstat, а также любой Prometheus exporter, считывают это поле и преобразуют два замера в процентное соотношение.
Одно следствие важнее остальных. Если гипервизор не экспортирует счетчик, поле навсегда остается нулевым, и все основанные на нем инструменты будут показывать спокойное 0.0, даже если хост перегружен. KVM и Xen экспортируют эти данные. Гостевые системы на VMware и Hyper-V обычно показывают ноль. Проверьте платформу, прежде чем доверять нулевому значению:
systemd-detect-virtЭта команда выводит имя платформы, например kvm, xen, vmware или microsoft, а на «железе» (bare metal) — none. Внутри контейнера она сообщает среду выполнения, например lxc, docker или podman, что дает информацию о контейнере, а не о физической машине под ним. На kvm ноль — это реальное доказательство того, что хост предоставляет вам достаточно ресурсов. На платформе, которая не заполняет это поле, ноль не является доказательством, и о нехватке ресурсов приходится судить по времени выполнения реальных задач.
Как проверить время ожидания CPU (steal time) на VPS?
vmstat входит в состав пакета procps. Эта утилита присутствует почти в каждом образе Ubuntu и Debian для VPS, но может отсутствовать в минимальных образах контейнеров, поэтому установите её перед использованием.
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version выводит строку вида vmstat from procps-ng 4.0.4. Если команда сработала, значит, инструмент установлен и вы получаете данные напрямую из счетчиков ядра. 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 gu
1 0 0 3216484 98304 1284360 0 0 4 18 62 110 3 1 96 0 0 0
2 0 0 3216232 98304 1284360 0 0 0 0 248 431 6 2 84 0 8 0Найдите столбец st в блоке cpu справа. В актуальных сборках procps-ng после него выводится столбец gu для времени гостевой системы KVM, поэтому st теперь находится на предпоследнем месте, а не на последнем. Ориентируйтесь на заголовок столбца, так как его положение менялось в разных версиях.
Две привычки помогут получить достоверные данные. Первая строка данных — это среднее значение с момента загрузки, поэтому игнорируйте её и смотрите на последующие строки. Один замер не является показателем, так как steal time возникает скачками: запустите vmstat 1 60 и наблюдайте за показаниями в течение полной минуты, прежде чем делать выводы.
top выводит то же значение в строке сводки %Cpu(s), в поле, помеченном как st:
%Cpu(s): 6.2 us, 2.1 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.3 si, 7.5 stДля получения детализации по ядрам добавьте sysstat:
sudo apt-get install -y sysstat
mpstat -P ALL 1 5mpstat выводит по одной строке на каждый CPU со столбцом %steal, который показывает, затронут ли каждый vCPU или только один. Для истории, необходимой при обращении в техническую поддержку, сохраняйте результаты в файл, а не просто смотрите на экран:
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.logЗапустите эту команду через cron в часы, когда наблюдаются проблемы. Файл с результатами позволит не просто сказать провайдеру «вчера ночью всё работало медленно», а предоставить точные данные за конкретный десятиминутный интервал.
Что означают показатели steal?
- Стабильный
0.0. Система исправна или платформа вовсе не сообщает о steal. Перед тем как делать выводы, подтвердите это с помощьюsystemd-detect-virt. - Кратковременные всплески на несколько процентов. Это нормально для любого общего узла (shared node). Возможно, сосед по серверу запустил сборку проекта или хост выполняет резервное копирование.
- Постоянный уровень от 1 до 5 процентов на тарифе с общими ресурсами. Ожидаемое поведение. Стоимость тарифа отражает использование общего CPU.
- Постоянный уровень от 5 до 10 процентов. Замедление, которое можно измерить. Начните фиксировать данные и сравните показатели в одни и те же часы в течение нескольких дней.
- Более 10 процентов в течение нескольких часов. Узел переподписан (oversubscribed) для вашей нагрузки. Этот уровень оправдывает создание тикета в поддержку или переезд на другой сервер.
Рассматривайте эти диапазоны как ориентир, а не как спецификацию, поскольку ни один провайдер не дает гарантий по steal на тарифах с общими ресурсами. Сопоставляйте эти цифры с тем, что именно вы запускаете. Ночное пакетное задание может пережить 15 процентов steal без последствий. Сервис, чувствительный к задержкам, покажет проблему в метрике p99 задолго до того, как средние значения станут критическими, поэтому нагрузки, чувствительные к задержкам, такие как торговые боты должны работать на выделенных ядрах.
Во сколько вам обходится steal time?
Арифметика проста. Если доля s времени процессора занята, задача, требующая фиксированного объема процессорного времени, выполняется в 1 / (1 - s) раз дольше по настенным часам. Для задачи, которой требуется 60 секунд процессорного времени:
The data behind this chart
[
{
"steal_percent": 0,
"wall_clock_seconds": "60.0"
},
{
"steal_percent": 3,
"wall_clock_seconds": "61.9"
},
{
"steal_percent": 8,
"wall_clock_seconds": "65.2"
},
{
"steal_percent": 15,
"wall_clock_seconds": "70.6"
},
{
"steal_percent": 25,
"wall_clock_seconds": "80.0"
},
{
"steal_percent": 40,
"wall_clock_seconds": "100.0"
}
]При 3 процентах, что является обычным показателем для тарифов с разделяемыми ресурсами, задача выполняется за 61.9 секунд вместо 60.0. Из-за этого никто не открывает тикет. При 8 процентах это уже 65.2 секунд. При 40 процентах той же задаче требуется 100.0 секунд, и очередь, которая раньше успевала обрабатываться, начинает расти.
Это расчетные значения, а не результаты измерений. Модель предполагает наличие одного исполняемого потока и равномерное распределение steal в течение интервала. Реальные сервисы часто работают хуже, чем показывает эта кривая, так как украденный квант времени может прийтись на середину запроса, и задержку будут вынуждены оплачивать все процессы, ожидающие завершения этого запроса. Чтобы получить собственные показатели, а не расчетные данные, проведите бенчмарк VPS в часы низкой нагрузки и повторите его в часы пик, фиксируя st для обоих периодов.
Это steal или что-то другое?
Показатель steal легко спутать с другими симптомами. Анализируйте счетчики вместе, в одной строке vmstat.
stвысокий, аrиusостаются низкими: хост не выделяет вам процессорное время. Это и есть steal.rзначительно превышает количество ваших vCPU, при этомusвысокий, аstблизок к нулю: вы выполняете больше задач, чем могут обработать ваши CPU. Сравнитеrс выводомnproc. Это ваша собственная избыточная нагрузка, а не влияние «соседа».waвысокий, аstблизок к нулю: задачи заблокированы операциями ввода-вывода (I/O), что является другой проблемой и требует иного решения.- Load average высокий, а
stиusнизкие: показатель нагрузки также учитывает задачи в состоянии ожидания (uninterruptible), поэтому обычно это указывает на зависшее устройство или недоступный сетевой диск, а не на проблемы с CPU.
Тарифы с возможностью кратковременного повышения производительности (burstable) заслуживают отдельного упоминания. Они предоставляют баланс кредитов, который накапливается во время простоя и расходуется при нагрузке; когда кредиты заканчиваются, провайдер ограничивает вас базовым уровнем производительности. На некоторых платформах такое ограничение отображается как steal. На других оно незаметно изнутри системы, и вы просто получаете меньше циклов процессора в секунду. Изучите описание тарифа, прежде чем делать вывод о вине «соседа» по серверу.
Почему контейнер не показывает steal time
Steal — это характеристика виртуальной машины, а не контейнера, работающего внутри неё. Docker-контейнер на вашем VPS использует общие ресурсы /proc хоста, поэтому значение st, считанное внутри него, отражает steal самого VPS, что и требуется для мониторинга. Контейнерная виртуализация, предоставляемая как VPS, работает иначе. При использовании lxcfs значение /proc/stat внутри контейнера синтезируется на основе данных cgroup, и steal всегда равен нулю. Система мониторинга, собирающая метрики только изнутри, может показывать стабильный ноль, в то время как физический сервер испытывает нехватку ресурсов.
Внутри контейнера аналогичный смысл имеет троттлинг по CPU-квоте. В cgroup v2:
cat /sys/fs/cgroup/cpu.statnr_throttled подсчитывает периоды, в течение которых группа достигла лимита CPU, а throttled_usec суммирует время, в течение которого процесс был заморожен. Рост nr_throttled означает, что ваш процесс был готов к выполнению, но не выполнялся — это то же самое ощущение, что и при steal, но вызванное установленным вами ограничением. Проверьте свои лимиты, прежде чем винить хост, особенно если вы запускаете сервисы в Docker на VPS с ограничениями CPU в файле compose. Многоуровневая виртуализация добавляет еще одно место, где может теряться время, так как виртуальная машина внутри вашего VPS «платит» и за steal хоста, и за собственную задержку планировщика. Учитывайте это, если вы используете вложенную виртуализацию на VPS.
Что делать при постоянном steal
Никакие настройки внутри гостевой системы не устраняют steal, так как планировщик, принимающий решение, работает вне гостя. Обновление ядра также не меняет ситуацию: планировщик с учетом кэша, добавленный в ядро Linux 7.2, перераспределяет задачи между ядрами, которые вам уже выделили, и не может вернуть циклы, которые уже занял сосед. Существует четыре реальных шага.
Сначала соберите доказательства. Зафиксируйте временные метки в UTC, длительность каждого эпизода, частоту повторений и то, показывает ли mpstat, что затронут один vCPU или все сразу. Неделя записанных данных ценнее, чем один скриншот.
Откройте тикет с этими данными. Задайте два прямых вопроса: переподписан ли этот узел в данные промежутки времени и можно ли перенести мой экземпляр. Вставьте вывод vmstat и точное время. Провайдеры реагируют на воспроизводимые интервалы, а на тикет с жалобой «сервер тормозит» вы получите ответ с просьбой предоставить данные. Объем работы, который вы можете переложить на поддержку, — одно из практических различий между управляемым и неуправляемым VPS.
Запросите миграцию. Перенос гостя на менее загруженный узел — стандартная процедура для провайдера, обычно требующая лишь короткой перезагрузки. Это бесплатное решение, которое помогает в типичном случае, когда на одном узле случайно оказалось несколько «тяжелых» соседей одновременно.
Устраните конкуренцию за ресурсы покупкой. Тарифы с выделенными vCPU резервируют физические ядра для вашего экземпляра, поэтому счетчик будет равен нулю и останется таким. Это стоит дороже каждый месяц, но является честным ответом для нагрузки, которая не может переносить вариативность. Если этого недостаточно или вы хотите получить в единоличное пользование еще и пропускную способность памяти, следующий шаг — выделенный сервер вместо VPS.
Пока вы ожидаете решения, уменьшите влияние steal. Запускайте меньше рабочих потоков, чем у вас есть vCPU, так как потоки, которые не могут получить ядро, лишь увеличивают количество переключений контекста. Перенесите пакетную обработку на часы, когда узел менее загружен, о чем теперь говорят ваши собственные логи. Затем проведите замеры снова с той же командой в те же часы, чтобы иметь возможность утверждать, помогло ли изменение, вместо того чтобы гадать.
FAQ
Какое значение CPU steal time считается нормальным для VPS?
На тарифах с разделяемыми ресурсами кратковременные всплески и стабильное значение до 5 процентов являются нормой, так как разделяемый CPU означает, что хост распределяет физические ядра между гостевыми системами. Стабильно высокие показатели в течение нескольких часов — это ненормально, и по этому поводу стоит создать тикет. На тарифах с выделенными vCPU ожидаемое значение составляет 0.0, поэтому любые другие показатели являются неисправностью, о которой следует сообщить. Оценивайте число исходя из вашей нагрузки: ночное пакетное задание может пережить steal, который недопустим для чувствительного к задержкам API.
Исправит ли переход на более дорогой тариф высокий steal time?
Сам по себе — нет. Большее количество vCPU на том же разделяемом узле означает, что больше виртуальных процессоров конкурируют за те же перегруженные физические ядра, и процентное значение может остаться прежним. Устранить steal можно только выделением ресурсов CPU или переездом на менее загруженный узел. Большая доля на загруженной машине — это всё ещё доля на загруженной машине.
Почему на моей VPS значение steal time равно 0, хотя она явно работает медленно?
Есть две основные причины. Гипервизор может вообще не передавать этот счётчик, что типично для платформ VMware и Hyper-V, поэтому поле остаётся нулевым независимо от действий хоста. Выполните systemd-detect-virt, чтобы узнать, на какой платформе вы работаете. В противном случае узкое место находится в другом: проверьте wa на наличие ожиданий ввода-вывода, сравните r с nproc для выявления собственной перегрузки и изучите /sys/fs/cgroup/cpu.stat внутри контейнеров на предмет ограничения квот.
Могу ли я уменьшить steal time изнутри сервера?
Вы не можете изменить планировщик хоста изнутри гостевой системы. Вы можете лишь уменьшить влияние этого фактора. Запускайте меньше рабочих потоков, чем у вас есть vCPU, чтобы меньше задач находилось в очереди выполнения в ожидании ядра, которое не освобождается. Перенесите пакетные задания на часы, когда узел менее загружен. Кэшируйте результаты, чтобы меньше запросов требовали процессорного времени. Изменения, которые действительно устраняют steal — миграция на другой узел или выделенные ядра — находятся на стороне провайдера.