Kubernetes autoscaling: настройка HPA и VPA для подов

Kubernetes autoscaling: настройка HPA и VPA для подов мар, 12 2026

Если вы управляете Kubernetes-кластером и замечаете, что одни поды грузят процессор на 90%, а другие почти не используют ресурсы - вы не одиноки. Проблема в том, что автоскейлинг не настроен правильно. Многие думают, что достаточно включить Horizontal Pod Autoscaler (HPA) и всё само собой наладится. Но это как поставить термостат на 25 градусов и ждать, что в доме станет комфортно, даже если окна открыты. В реальности вам нужны два инструмента: HPA и Vertical Pod Autoscaler (VPA). Они работают вместе, но решают разные задачи.

Чем отличается HPA от VPA?

HPA - это про количество подов. Он смотрит на метрики: если CPU подов поднялся выше 70%, он запускает ещё экземпляры. Если нагрузка упала - убирает лишние. Просто и понятно. Но он не знает, сколько ресурсов должен иметь один под. Если вы выделили поду 4 ядра, а он реально использует 0.3, HPA будет считать, что нагрузка низкая, даже если поды реально перегружены. Это как измерять скорость автомобиля по количеству бензина в баке, а не по оборотам двигателя.

VPA - это про размер пода. Он анализирует, сколько памяти и CPU реально использовал под за последние дни, недели, и предлагает оптимальные значения для requests и limits. Он не запускает новые поды. Он меняет их конфигурацию. Но тут есть подвох: если VPA решит, что поду нужно 0.5 ядра вместо 4, он не просто перенастроит - он убьёт под и пересоздаст его с новыми параметрами. Это может привести к кратковременным остановкам сервиса, если не подготовиться.

Как работает VPA: три компонента

VPA - это не один инструмент, а три части, которые работают вместе:

  • Recommender - анализирует историю использования ресурсов. Он смотрит, сколько CPU и памяти поды тратили в течение последних дней, вычисляет 90-й и 95-й перцентили, и даёт рекомендации: «Вам нужно 0.8 ядра и 1.2 ГБ памяти».
  • Updater - если рекомендации отличаются от текущих значений, он сбрасывает поды. Это единственный компонент, который действительно перезапускает контейнеры. Он не трогает поды, если вы не включили режим Auto.
  • Admission Controller - перехватывает запросы на создание новых подов и вставляет рекомендации прямо в манифест перед тем, как под попадёт на узел. Это значит, что даже новые поды запускаются с правильными настройками, а не с теми, что вы прописали в Deployment.

Всё это работает через webhook-механизм Kubernetes. Вы можете увидеть его, выполнив команду: kubectl get mutatingwebhookconfigurations. Там будет запись типа vpa-webhook - это и есть ваш Admission Controller.

Режимы работы VPA: Off, Initial, Auto

VPA не должен быть включен сразу в режиме Auto. Это как запускать автопилот в первый раз на трассе - сначала нужно потренироваться.

  1. Off - VPA собирает данные, но ничего не меняет. Рекомендации появляются в статусе объекта VPA, но поды остаются как есть. Используйте этот режим 1-2 недели. Соберите статистику по пиковой нагрузке, ночным спадам, недельным циклам.
  2. Initial - VPA применяет рекомендации только к новым подам. Существующие поды не трогаются. Это безопасный следующий шаг. Вы можете применить рекомендации вручную к Deployment, а потом включить VPA в Initial. Так вы избежите внезапных перезапусков.
  3. Auto - VPA перезапускает и старые, и новые поды. Только когда вы уверены, что ваши сервисы выдерживают перезапуски (есть PDB, нет stateful-приложений без репликации, нет долгих транзакций), можно включать этот режим.

Большинство команд, которые делают это правильно, месяц работают в Off, потом месяц в Initial, и только потом переходят в Auto. Никаких спешек.

Три компонента VPA: Recommender, Updater и Admission Controller, визуализированные как интерактивные панели с данными и перезапуском пода.

Как VPA считает рекомендации

VPA не просто берёт среднее значение. Он использует статистику:

  • 90-й перцентиль - это рекомендуемый уровень requests. Он покрывает большинство пиковых нагрузок, не переплачивая за редкие всплески.
  • 50-й перцентиль - минимальный порог. VPA не станет предлагать меньше этого значения, даже если поды использовали меньше. Минимум по CPU - 25 милиядер, по памяти - 250 МБ.
  • 95-й перцентиль - верхний предел для limits. Это «сafety net» - если под начнёт использовать больше, он упадёт, а не будет тормозить весь узел.

Конфиденциальность растёт со временем. Если вы собрали данные только за 2 дня, VPA будет с осторожностью: рекомендации будут умножены на коэффициент 0.8. Через 14 дней - коэффициент станет 1.0, и рекомендации будут применяться как есть.

Как VPA влияет на HPA

Вот где всё ломается. Если вы включили VPA в Auto, а HPA масштабируется по CPU-использованию - вы получите цикл смерти:

  • VPA снижает requests с 2 ядер до 0.5 ядра.
  • HPA видит, что CPU-использование пода стало 80% (всё ещё много, потому что 0.5 ядра - это мало).
  • HPA запускает ещё 3 пода.
  • Новые поды тоже имеют низкие requests, и HPA снова их масштабирует.
  • Вы получаете 20 подов, каждый из которых использует 0.4 ядра. А вы думали, что нагрузка упала!

Это классическая ошибка. Решение простое: либо отключите HPA на CPU, либо используйте метрики, которые не зависят от requests. Например:

  • Количество HTTP-запросов в секунду на под
  • Глубина очереди обработки
  • Время ответа API
  • Число активных сессий

Так HPA будет масштабировать не по «загрузке процессора», а по реальному бизнес-нагрузке. А VPA будет заботиться о том, чтобы каждый под имел ровно столько ресурсов, сколько нужно.

Настройка VPA: пример конфига

Вот минимальный рабочий манифест VPA для Deployment:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Initial"  # или "Off", или "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: "my-app"
      mode: "Off"  # для этого контейнера VPA не меняет limit, только request
    - containerName: "*"
      mode: "Auto"  # для всех остальных - Auto

Здесь targetRef указывает, к какому контроллеру применяется VPA. updateMode - это режим работы. resourcePolicy позволяет гибко настраивать, какие контейнеры трогать. Например, у вас есть sidecar-контейнер для логов - его можно зафиксировать в режиме Off, чтобы VPA не трогал его ресурсы.

Три этапа безопасного внедрения VPA: Off, Initial и Auto, с акцентом на защиту сервиса через PDB.

Что ещё важно знать

  • LimitRange в неймспейсе может ограничить VPA. Если в неймспейсе стоит max CPU = 2, VPA не сможет предложить 3 ядра, даже если поды реально их используют.
  • Pod Disruption Budget (PDB) обязателен, если вы используете Auto режим. Без него VPA может убить все поды одновременно, и сервис упадёт.
  • Мониторинг - обязательно подключите Grafana и смотрите, сколько подов получили рекомендации. Если 80% подов имеют рекомендации - всё работает. Если 0% - проверьте логи VPA и убедитесь, что он видит ваши поды.
  • Не используйте VPA для StatefulSet без резервирования. Если у вас база данных или кэш, и он перезапустится с новыми ресурсами - это может привести к потере данных или кластерной нестабильности.

Что делать, если HPA начинает «беситься» после VPA

Если вы включили VPA, и HPA начал запускать по 10 подов вместо 3 - это почти всегда одна из двух причин:

  1. HPA масштабируется по CPU, а VPA снизил requests - поды теперь кажутся перегруженными.
  2. Вы не настроили метрики для HPA, и он использует CPU по умолчанию.

Решение:

  • Перейдите на метрики, не связанные с CPU - например, http_requests_per_second или queue_length.
  • Временно отключите VPA и вручную примените его рекомендации к Deployment. Затем включите VPA в режиме Off или Initial.
  • Увеличьте порог HPA с 70% до 85% - это даст больше «дыхательного пространства».

Итог: как правильно настроить автоскейлинг

Вот простой план для любого продакшн-кластера:

  1. Включите VPA в режиме Off на 1-2 недели. Смотрите, какие рекомендации он даёт.
  2. Вручную примените эти рекомендации к вашим Deployment. Убедитесь, что поды стабильно работают.
  3. Включите VPA в режиме Initial. Теперь новые поды будут запускаться с правильными ресурсами.
  4. Настройте HPA на метрики, связанные с бизнес-нагрузкой - не на CPU.
  5. Только после этого - и только для нетребовательных к стабильности сервисов - включите VPA в Auto.

Автоскейлинг - это не «включи и забудь». Это процесс. Он требует наблюдения, тестирования и постепенного внедрения. Но когда всё работает - вы платите только за то, что реально используете, а сервисы остаются быстрыми и стабильными.

Можно ли использовать HPA и VPA одновременно?

Да, и это рекомендуемый подход. HPA отвечает за количество подов, а VPA - за размер каждого пода. Они работают независимо, но дополняют друг друга. Главное - не использовать HPA на CPU-использовании, если VPA меняет requests. Лучше использовать HPA на метриках вроде HTTP-запросов или глубины очереди.

Почему VPA не меняет мои поды?

Часто это происходит из-за неправильного targetRef. Убедитесь, что VPA ссылается на Deployment, StatefulSet или DaemonSet, а не на Pod напрямую. Также проверьте, что VPA находится в том же неймспейсе, что и поды. И не забудьте: в режиме Off VPA не меняет поды - он только даёт рекомендации.

Что будет, если VPA предложит слишком маленькие ресурсы?

Если рекомендации ниже минимального порога (25 милиядер CPU, 250 МБ памяти), VPA не применит их. Он всегда выставляет минимальные значения. Если вы видите, что VPA предлагает 10 милиядер - это ошибка. Проверьте логи VPA Recommender. Возможно, данные были собраны слишком короткий срок, и алгоритм дал неточную рекомендацию.

Нужно ли перезагружать поды вручную после VPA?

Только если вы используете режим Off или Initial. В этих режимах VPA не перезапускает поды. Вы должны вручную обновить Deployment, применив рекомендации. В режиме Auto - VPA делает это сам. Но если вы включили Auto, убедитесь, что у вас есть Pod Disruption Budget, иначе сервис может упасть.

Какие метрики лучше использовать для HPA вместо CPU?

Лучше всего - метрики, которые отражают реальную нагрузку на приложение. Например: количество запросов в секунду, время ответа API, размер очереди задач, число активных пользователей. Эти метрики можно собирать через Prometheus и использовать в HPA с помощью Custom Metrics API. Это даёт точный, а не косвенный сигнал о нагрузке.