Переплата за простаивающие ядра: считаем по реальным метрикам
Когда заказывали сервер, кто-то (возможно, вы сами полгода назад) взял конфигурацию «с запасом» — на случай роста трафика, будущих фич, чёрной пятницы, которая, может, случится через год. Прошло время, роста не случилось или случился в других местах, а счёт за аренду так и приходит за 8 или 16 ядер, из которых реально работает два-три. Ниже — не общие рассуждения про «оптимизацию облака», а конкретная методика: как достать из мониторинга цифры реальной загрузки CPU, honest сопоставить их с заказанным числом ядер и посчитать, во сколько вам обходится этот запас в деньгах.
Содержание
Почему «с запасом» стало нормой, а не исключением
Over-provisioning редко бывает результатом злого умысла провайдера — чаще это накопленный эффект нескольких решений, каждое из которых по отдельности выглядело разумным:
- при первом заказе закладывали ядра под пиковую нагрузку, которую видели один раз в квартал, а не под типичный день;
- после инцидента с нехваткой CPU конфигурацию апгрейдили «с запасом», чтобы больше не возвращаться к этому вопросу;
- миграция с одного проекта на другой сервер прошла, а старые сервисы, под которые изначально считали ядра, давно снесли или заменили более лёгкими;
- планировали рост пользователей/RPS, который не подтвердился, а ресурсы остались зарезервированы «на всякий случай».
Проблема в том, что решение о размере сервера почти всегда принимается один раз — в момент заказа — и дальше никто не возвращается к нему с вопросом «а изменилось ли что-то за эти месяцы». Тарифы за простаивающие ядра списываются молча, без alert’ов, потому что технически всё работает: сервер не падает, приложение отвечает. Переплата не создаёт инцидента — поэтому её и не замечают.
Отдельно стоит развеять миф: «выключенный простой» — это не то же самое, что низкая загрузка. Сервер, который включён и работает, но использует 5-10% CPU от заказанного объёма, платит по счёту так же, как если бы он был загружен на 90%. Разница только в вашем кармане, а не в счёте провайдера.
Что считать метрикой, а что — ощущением
Прежде чем открывать графики, стоит договориться о терминах, потому что именно здесь чаще всего теряется точность расчёта.
Загрузка CPU в процентах — это доля времени, которое ядро провело в состоянии «выполняет инструкции», а не в состоянии ожидания (idle). Если у вас 8 ядер и средняя загрузка по системе 25%, это не значит «используется 2 ядра» напрямую — 25% может быть равномерно размазано по всем 8 ядрам (частый случай для многопоточных сервисов) или сконцентрировано на 1-2 ядрах при простое остальных (частый случай для однопоточных приложений вроде классического Node.js-процесса без кластеризации). Разница критична: во втором случае избыточны почти все ядра, кроме одного-двух, в первом — избыточна только часть общей мощности.
Steal time — отдельная метрика на виртуальных серверах, показывающая, сколько времени ваша виртуальная машина ждала физический CPU, который в этот момент отдавали соседям по гипервизору. Высокий steal time искажает картину: ваше приложение может показывать низкую полезную загрузку не потому, что ему хватает ядер, а потому что часть выделенного времени съедает шум соседей. Подробнее о том, как отличить нехватку своих ядер от чужого потребления, разбирали в статье про steal time и соседей по гипервизору — если считаете переплату на классическом VPS с неизвестным оверселлом, эту метрику обязательно смотрите отдельно, иначе рискуете «сократить» ядра, которые вам физически нужны для компенсации соседей.
Пиковая загрузка vs средняя — это то, что чаще всего путают при принятии решения о downsize. Средняя загрузка за месяц в 15% не означает, что можно смело резать ядра втрое: если у вас есть регулярные пики (например, ночной backup или batch-обработка раз в сутки), которые кратковременно упираются в 100%, урезание CPU может привести к деградации именно в эти окна. Методика ниже строится не на среднем и не на пике, а на процентилях — это единственный подход, который одновременно честен к повседневной нагрузке и не игнорирует регулярные всплески.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак снять историю реальной загрузки: инструменты и команды
Ключевое требование методики — данные за недели или месяцы, а не снимок «прямо сейчас». top и htop в этом смысле почти бесполезны для расчёта переплаты: они показывают текущий момент, который может быть нетипичным (вы зашли на сервер как раз во время деплоя или ночного cron). Нужна история.
Если на сервере уже стоит мониторинг (Netdata, Zabbix, Prometheus+Grafana) — это самый быстрый путь, потому что история уже собирается. Как быстро развернуть такой мониторинг с нуля, если его ещё нет, описано в статьях про установку Netdata на VPS и про выбор между Zabbix и Prometheus для более серьёзного долгосрочного сбора метрик.
В Netdata нужный график — system.cpu, в разделе истории (по умолчанию хранится обычно от нескольких дней до нескольких недель в зависимости от настроек retention, для долгого хранения стоит завести экспорт в Prometheus). Через API можно вытащить агрегированные данные скриптом:
# среднее и максимум по cpu.utilization за последние 30 дней (пример запроса к Netdata REST API)
curl -s "http://localhost:19999/api/v1/data?chart=system.cpu&after=-2592000&points=720&format=json" \
| jq '.data | map(.[1]) | {avg: (add/length), max: max}'
В Zabbix/Prometheus то же самое делается через запросы к их API или прямо в Grafana — там процентили считаются встроенной функцией (quantile_over_time в PromQL).
Если мониторинга нет и разворачивать полноценный стек ради одного расчёта избыточно — на Linux почти всегда есть или легко ставится sysstat (пакет с sar), который по умолчанию в некоторых дистрибутивах уже собирает историю CPU за последние дни:
# установка, если ещё не стоит
apt install sysstat # Debian/Ubuntu
dnf install sysstat # RHEL/AlmaLinux/CentOS
# посмотреть загрузку CPU по дням за последний месяц (файлы sa01..sa31 в /var/log/sysstat или /var/log/sa)
sar -f /var/log/sysstat/sa15 -u
# средняя загрузка по каждому ядру отдельно
mpstat -P ALL 1 60
Если sysstat только что установили — исторических данных ещё нет, придётся накопить их за 2-4 недели, прежде чем считать честную переплату. Это неудобно, но принципиально: разовый замер за час не заменяет статистику за недели, потому что не покрывает недельную и месячную сезонность (будни vs выходные, начало месяца vs конец, если у сервиса есть биллинговые пики).
Метрики хостинг-провайдера. У многих провайдеров в панели управления сервером есть встроенный график загрузки CPU за исторический период (обычно от суток до нескольких месяцев) — он не требует установки ничего на сам сервер и подойдёт для быстрой прикидки, хотя обычно даёт меньше деталей (нет разбивки по процессам и по отдельным ядрам), чем Netdata или Zabbix.
Как читать график: от «сырых» данных к количеству нужных ядер
Собрав историю за 2-4 недели (лучше — за 1-3 месяца, если сервис сезонный), переходите к превращению графика в конкретное число ядер.
- Выгрузите ряд значений загрузки CPU (в процентах от общей мощности всех ядер) с разумной гранулярностью — минутные или пятиминутные точки, не реже.
- Постройте распределение, а не одно среднее число. Нужны как минимум: среднее, медиана (p50), p95 и максимум. p95 — это значение, ниже которого лежат 95% всех измерений; именно оно, а не среднее и не максимум, обычно лучший ориентир для right-sizing, потому что игнорирует единичные аномальные всплески, но не игнорирует регулярную нагрузку.
- Переведите процент в эквивалент ядер. Если у вас заказано
Nядер и p95 загрузки по системе составляетX%от суммарной мощности, эквивалент реально нужных ядер:
core_need = N × (X / 100)
Например (это иллюстрация методики, не готовый результат — у вас будут свои цифры): при 8 заказанных ядрах и p95 загрузки 30% от суммарной мощности core_need = 8 × 0.30 = 2.4 — то есть по факту 95% времени вам хватает мощности 2.4 ядра, а оставшиеся 5.6 ядра простаивают почти всегда.
- Добавьте буфер поверх p95, а не поверх заказанного количества. Правило «плюс одно ядро сверху p95, округление вверх» — разумный компромиссный подход: он оставляет запас на кратковременные пики выше p95, но не тащит за собой весь исторический over-provisioning.
- Проверьте пики отдельно. Если максимум за период уходит в 100% на несколько минут ежедневно (типичный случай — backup, индексация, batch-джобы), убедитесь, что новое, урезанное количество ядер не упирается в потолок именно в эти окна — возможно, для них стоит рассмотреть перенос задачи на менее нагруженное время, а не закладывать под них постоянную мощность.
Отдельно про многопроцессные/многопоточные приложения: если сервис однопоточный (классический пример — worker без кластеризации), общая загрузка «15% от 8 ядер» может означать «одно ядро занято на 100%+, семь простаивают». В этом случае методика по проценту от суммарной мощности вводит в заблуждение — нужно смотреть mpstat -P ALL или разбивку по ядрам в Netdata/Grafana, чтобы увидеть реальный потолок конкретного процесса, а не усреднённую по системе цифру.
Формула переплаты: от процентов к деньгам
Когда есть core_need (реально нужное число ядер по методике выше) и известна цена за ядро в вашем тарифе, переплата считается напрямую:
overpay_cores = N_ordered − core_need
overpay_money = overpay_cores × price_per_core_month
Где:
N_ordered— сколько ядер оплачивается по текущему тарифу;core_need— реально нужное число ядер по p95 + буфер (см. предыдущий раздел);price_per_core_month— цена одного ядра в месяц. Если в тарифе ядра идут «пакетом» вместе с RAM и диском и явной цены за ядро нет, можно оценить её через разницу между соседними тарифными планами провайдера (разница в цене за N+1 ядро при прочих равных — оценка стоимости одного ядра).
Если считаете за год, а не за месяц — просто умножьте overpay_money на 12 (или на фактическое число месяцев с момента последнего пересмотра конфигурации, если апгрейд был недавно).
Полезно также посчитать процент переплаты от общего счёта — эта цифра лучше воспринимается при обсуждении с руководством или командой, чем абсолютная сумма:
overpay_percent = overpay_cores / N_ordered × 100
Табличный пример структуры расчёта для нескольких серверов (цифры условные, для иллюстрации формата таблицы, а не как готовый бенчмарк):
| Сервер | Заказано ядер | p95 загрузки | core_need (округл.) | Переплата, ядер |
|---|---|---|---|---|
| api-prod-1 | 8 | ~30% | 3 | 5 |
| worker-batch | 4 | ~70% | 3 | 1 |
| db-replica | 4 | ~15% | 2 | 2 |
Такая таблица, собранная по всем серверам инфраструктуры, сразу показывает, где переплата системная (весь парк держат «с запасом»), а где точечная (один сервер реально нагружен и трогать его не стоит).
Что делать с результатом: не просто урезать наугад
Посчитанная переплата — это входные данные для решения, а не сам план действий. Несколько практических шагов, которые снижают риск при переходе на меньшую конфигурацию:
- Меняйте конфигурацию поэтапно, а не сразу «под ноль» по core_need. Если методика показала 2.4 ядра нужными, разумный первый шаг — снизить с 8 до 4, а не сразу до 3, и понаблюдать за метриками ещё пару недель на новой конфигурации.
- Держите мониторинг включённым и после даунсайза — это единственный способ поймать момент, когда реальная загрузка вырастет (новый функционал, рост трафика) раньше, чем это станет заметно по деградации отклика.
- Учитывайте сезонность бизнеса, а не только техническую сезонность нагрузки: если у вас e-commerce и торговый пик — конец года, а расчёт делаете в конце августа, не режьте ядра под сегодняшний p95, если знаете, что через несколько месяцев нагрузка типично растёт в разы.
- Раздельно считайте CPU, RAM и диск — экономия по ядрам не означает, что можно так же смело резать память или диск: у них своя логика заполнения и свои риски (например, для памяти важнее не средняя загрузка, а пиковая, потому что OOM — это падение сервиса, а не деградация производительности).
- Зафиксируйте методику как регулярную проверку, а не разовое упражнение. Раз в квартал повторный расчёт core_need по свежим метрикам избавляет от необходимости заново «спохватываться» через год, когда счёт снова незаметно вырастет за счёт новых сервисов на той же старой конфигурации.
Если после расчёта видно, что переплата системная по нескольким серверам сразу, дешевле и практичнее не резать по одному, а сразу пересмотреть план и, при необходимости, сменить конфигурацию или локацию на более подходящую по цене за ядро — с оплатой из России картой или криптой, без дополнительных сложностей с международными платежами.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько данных нужно для честного расчёта — хватит ли суток?
Нет, сутки покрывают только один цикл (обычно день/ночь), но не недельную сезонность (будни/выходные) и тем более не месячную. Минимум — 2 недели, лучше 4-6 недель или полный месячный цикл, если у сервиса есть биллинговые или отчётные пики в начале/конце месяца.
Что делать, если сервер VPS с высоким steal time — можно ли доверять его p95 загрузки?
Сначала разберитесь со steal time отдельно (см. раздел про соседей по гипервизору) — высокий steal time означает, что часть «недогрузки» может быть иллюзией: приложению физически не хватало времени CPU, а не оно реально не нуждалось в ядрах. В этом случае переходите на тариф с гарантированными (не переподписанными) ядрами и заново снимайте метрики уже там.
Почему нельзя просто смотреть на среднюю загрузку за месяц, зачем нужен p95?
Среднее сглаживает пики так же, как и провалы — сервер с равномерной загрузкой 30% и сервер, который простаивает 90% времени, но раз в день упирается в 100% на час, могут дать одинаковое среднее, но требуют разной конфигурации. p95 сохраняет чувствительность к регулярным пикам, но не даёт единичному выбросу исказить расчёт.
Стоит ли резать ядра, если приложение однопоточное и всё равно упирается в одно ядро?
В этом случае сокращение общего числа ядер сервера может быть оправдано (лишние ядра действительно не используются), но проблема производительности при этом не решится — для неё нужна не смена размера сервера, а работа с самим приложением (кластеризация процессов, асинхронность, шардирование нагрузки).
Как часто пересматривать конфигурацию после первого расчёта?
Раз в квартал — разумная периодичность для большинства проектов; для быстрорастущих или сильно сезонных сервисов имеет смысл чаще, раз в месяц, особенно после релизов, заметно меняющих профиль нагрузки.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →