ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Kubernetes HPA v2: CPU/Memory и custom metrics без flapping — scale up/scale down, stabilization window

Разбираем HPA v2 в Kubernetes: масштабирование по CPU/Memory через metrics-server и по custom/external метрикам через Prometheus Adapter. Покажу причины flapping и рабочие настройки behavior, stabilizationWindowSeconds и policies.
Kubernetes HPA v2: CPU/Memory и custom metrics без flapping — scale up/scale down, stabilization window

Зачем HPA v2 и почему он «дребезжит»

Horizontal Pod Autoscaler в Kubernetes решает практичную задачу: держать нагрузку на подах около целевого уровня, автоматически делая scale up и scale down. В реальности часто появляется неприятный эффект: реплики то растут, то тут же падают, потом снова растут — это называют flapping (дребезг).

В HPA v1 (по сути, только CPU) инструментов «успокоить» поведение было мало. В HPA v2 появилось поле behavior: окна стабилизации, ограничения скорости роста/снижения, выбор «более агрессивной» или «более осторожной» политики.

Дальше разберём практическую настройку HPA v2 для:

  • метрик CPU/Memory через metrics-server;
  • custom metrics (RPS, глубина очереди, lag) через Prometheus и prometheus-adapter;
  • устранения flapping: stabilizationWindowSeconds, policies, корректные requests и адекватный выбор метрик.

Как HPA принимает решение: короткая «модель в голове»

HPA периодически опрашивает API метрик и вычисляет желаемое число реплик. Для ресурсных метрик (CPU/Memory) обычно работает простая пропорция: если метрика вдвое выше таргета, то и реплик нужно примерно вдвое больше.

desiredReplicas ≈ currentReplicas × (currentMetricValue / targetMetricValue)

Затем вступают ограничения: minReplicas/maxReplicas, а в HPA v2 ещё и behavior. Если метрика шумная, поды долго стартуют, есть спайки или неверно выставлены requests — оценка будет «дёргаться», провоцируя flapping.

Важно помнить: HPA работает с метриками подов и/или объектов (через адаптер), но не понимает «бизнес-контекст». Поэтому задача администратора — подобрать метрику и правила так, чтобы изменения реплик происходили предсказуемо, с учётом задержек приложения.

Схема принятия решений HPA: источники метрик и расчёт желаемого числа реплик

CPU и Memory в HPA v2: что нужно для корректной работы

1) metrics-server — источник resource metrics

Для масштабирования по CPU/Memory HPA использует ресурсные метрики из metrics-server. Типовая быстрая проверка:

kubectl get apiservices | grep metrics
kubectl -n kube-system get deploy metrics-server
kubectl top nodes
kubectl top pods -A

Если kubectl top не показывает данные — HPA по ресурсам работать не будет (или будет в состоянии Unknown по этим метрикам).

2) Правильные requests — основа адекватного scale up/scale down

Частая причина «странного» поведения CPU-HPA — неверные resources.requests.cpu. Для таргета averageUtilization HPA смотрит на процент использования от request. Если request занижен в 5–10 раз, HPA будет видеть 300–800% утилизации и взлетать в реплики при любой нагрузке. Если request завышен — наоборот, HPA может «не видеть» рост нагрузки и не масштабироваться вовремя.

Быстро сравнить фактическое потребление и настройки requests можно так:

kubectl -n your-namespace top pods
kubectl -n your-namespace get deploy your-app -o yaml

Практика для старта: выставить requests примерно на 60–80 перцентиль steady-state потребления, а дальше уточнять по факту. Отдельно проверьте CPU limits: слишком жёсткие лимиты могут привести к троттлингу, и вы получите деградацию при «красивых» метриках.

3) Память: HPA может масштабировать, но это не «волшебная таблетка»

Масштабирование по memory технически работает, но часто даёт сюрпризы: память растёт ступенчато (GC/кэши), а OOM может случиться раньше, чем HPA успеет отреагировать. Обычно memory как триггер применяют:

  • как дополнительный сигнал, но не единственный;
  • для воркеров, где память реально коррелирует с объёмом работы;
  • вместе с адекватными лимитами и наблюдением за OOM/eviction.

Если основная боль — пики RPS/очереди, чаще правильнее идти в custom metrics.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Custom metrics: зачем они нужны и как устроены

CPU/Memory — косвенные метрики. Для веб-приложений и воркеров часто полезнее масштабироваться по тому, что напрямую отражает нагрузку и/или SLO: RPS на pod, количество активных запросов, глубина очереди, lag консьюмера.

В Kubernetes обычно встречаются два API:

  • Custom Metrics API — метрики уровня подов/неймспейса, которые HPA читает как Pods или Object.
  • External Metrics API — «внешние» метрики, не принадлежащие конкретному объекту Kubernetes (очереди, внешние сервисы).

Самый распространённый стек: Prometheus собирает метрики, prometheus-adapter публикует их в Custom/External Metrics API, HPA v2 читает и масштабирует.

Проверяем, что адаптер реально отдаёт метрики

Начните с проверки доступности API-сервисов:

kubectl get apiservices | grep -E 'custom.metrics|external.metrics'

Дальше полезно посмотреть, что вообще публикуется (для отладки правил адаптера):

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | head
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | head

И точечно проверить конкретную метрику (путь зависит от типа метрики и ресурса):

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/your-namespace/pods/*/http_requests_per_second" | head

Если здесь пусто или ошибки — HPA будет показывать Unknown и не будет масштабироваться по этой метрике.

Если ваш адаптер и мониторинг крутятся не в managed-кластере, а на своих серверах, часто удобнее держать инфраструктуру наблюдаемости отдельно на VDS: проще обновлять компоненты, контролировать ресурсы и не мешать прод-кластеру.

Практический HPA v2: CPU/Memory + custom metrics (шаблон)

Ниже пример манифеста HPA v2 с двумя ресурсными метриками и одной custom (на уровне pod). Это не «идеал для всех», но хороший старт, чтобы получить управляемое поведение и снизить flapping.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
  namespace: your-namespace
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: your-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 75
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "25"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      selectPolicy: Max
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
      - type: Pods
        value: 4
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      selectPolicy: Max
      policies:
      - type: Percent
        value: 20
        periodSeconds: 60

Как это читается:

  • По CPU целимся в 70% от requests, по памяти — 75%.
  • По custom метрике держим около 25 RPS на pod (условный пример).
  • scaleUp разрешаем агрессивнее: до +100% или +4 pod за минуту (что больше), потому что selectPolicy: Max.
  • scaleDown замедляем: окно стабилизации 5 минут и не более -20% за минуту.

Почему возникает flapping: 10 частых причин

Дребезг почти никогда не «баг в HPA», обычно это сочетание метрик, времени реакции и ограничений.

  • Неверные requests CPU/Memory: HPA считает проценты от request.
  • Шумная метрика (RPS/latency «скачет» каждую минуту) без сглаживания/усреднения.
  • Слишком быстрый scale down при коротком окне стабилизации.
  • Долгий старт подов (init, миграции, прогрев кэша): HPA добавляет ещё, пока новые не стали Ready.
  • Неудачный тип метрики: например, p99 latency как триггер без фильтрации и минимального трафика.
  • Неправильная агрегация в Prometheus: суммирование «в ноль» лейблов pod, пропуски, некорректная обработка reset counters.
  • Слишком жёсткие CPU limits: троттлинг меняет поведение приложения и динамику метрик.
  • Проблемы источника метрик: лаг metrics-server, отвал адаптера, таймауты API.
  • Ступенчатая нагрузка, когда один pod не тянет, а два уже дают «запас» и запускают быстрый откат.
  • Конкуренция контроллеров: KEDA, ручные правки replicas, cron-скейлинг, «умные» скрипты.

Иллюстрация поведения HPA: scale up и замедленный scale down с окном стабилизации

Инструменты HPA v2 против flapping: stabilization window и policies

Stabilization window: «не верь первому импульсу»

stabilizationWindowSeconds — ключевой параметр против дребезга. Он работает по-разному для scale up и scale down.

  • Для scale down окно обычно ставят больше (например, 300–600 секунд). HPA будет выбирать «более осторожное» желаемое значение из истории за окно, чтобы не рубить реплики на кратковременной просадке.
  • Для scale up часто оставляют 0 или небольшое значение: рост должен реагировать быстрее на реальную нагрузку.

Типовой рабочий паттерн: быстрый scale up, медленный scale down.

Policies: ограничиваем скорость изменения реплик

Политики позволяют задать «не более X подов» или «не более Y%» за период. Практически удобно комбинировать Percent и Pods, а выбор делать через selectPolicy:

  • selectPolicy: Max — выбрать наиболее агрессивную политику (быстрее менять реплики).
  • selectPolicy: Min — выбрать наиболее консервативную политику (медленнее).

Для защиты от flapping чаще важнее ограничить scale down: например, не больше -10…-30% в минуту и окно стабилизации 5–10 минут.

Cooldown «в голове»: учитывайте время выхода новых подов на плато

Даже с окнами стабилизации полезно прикинуть, через сколько секунд новый pod начинает реально обслуживать трафик и отдавать репрезентативные метрики. Если приложение прогревается 2–3 минуты (JIT, кэши, коннекты), то scaleDown.stabilizationWindowSeconds логично держать не меньше этого времени, а иногда и больше.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Custom metrics без сюрпризов: как выбирать метрику и запрос в Prometheus

Стабильность важнее «красоты» метрики

Для autoscaling метрика должна быть:

  • предсказуемо связана с нагрузкой (больше работы → больше метрики);
  • достаточно гладкой на горизонте опроса HPA;
  • правильно «привязана» к pod, если вы используете тип Pods и хотите удерживать нагрузку «на pod».

Плохие кандидаты как единственный триггер: p99 latency, метрики с редкими выбросами, проценты ошибок без минимального объёма трафика, метрики, которые сильнее зависят от кэша/GC, чем от нагрузки.

Prometheus-практика: rate и агрегация «до pod»

Если вы делаете custom метрику RPS, обычно нужен rate() по счётчику и агрегация до pod. Для AverageValue HPA ожидает значения на каждый pod, чтобы посчитать среднее. В адаптере это достигается правилом, которое возвращает временной ряд с лейблом pod.

Проверьте два момента:

  • что в метрике есть стабильный идентификатор pod (лейбл pod и обычно namespace);
  • что вы не агрегируете всё до одного значения на namespace, если используете тип Pods.

Если вы параллельно строите алертинг на эти метрики, полезно продумать маршрутизацию и «заглушки» на время инцидентов: как настроить routing, silence и шаблоны в Alertmanager.

Диагностика: что смотреть, когда HPA «скачет»

1) Состояние HPA и причины решений

kubectl -n your-namespace describe hpa app-hpa

В выводе особенно полезны блоки:

  • Metrics — какие значения видит HPA и какие таргеты применяет.
  • Conditions — например, AbleToScale, ScalingActive, ScalingLimited.
  • Events — причины изменений реплик и ошибки чтения метрик.

2) Проверка, что метрика соответствует ожиданиям

При flapping из-за custom metrics цель — увидеть «сырые» значения, которые HPA получает из адаптера (а не только в Grafana). Используйте kubectl get --raw для Custom/External Metrics API и сравнивайте с запросом в Prometheus.

3) Сопутствующие факторы: readiness, PDB, HPA vs rollout

Иногда дребезг — следствие того, что поды долго не проходят readiness, а HPA уже добавляет новые. Проверьте:

  • время старта и readiness-пробы;
  • PodDisruptionBudget, который ограничивает снижение реплик (и HPA начинает «пилить» попытки);
  • идёт ли параллельный rollout, меняющий число Ready-подов.

Рецепты анти-flapping (проверенная база)

Рецепт 1: «быстро вверх, медленно вниз»

Подходит для веб-приложений с пиками нагрузки:

  • scaleUp.stabilizationWindowSeconds: 0 или 30–60;
  • scaleDown.stabilizationWindowSeconds: 300 или 600;
  • scale down ограничить до 10–30% в минуту.

Рецепт 2: ограничиваем scale up, если поды дорогие

Если каждый pod тяжёлый (прогрев, миграции, долгий init), а нагрузка не «взрывная», имеет смысл ограничить рост: например, +2 pod в минуту. Это снижает риск «перестрелять» и затем получить немедленный откат.

Рецепт 3: один главный сигнал + один страховочный

Смешивать CPU, memory и custom metrics можно, но помните: HPA берёт максимум из желаемых реплик по всем метрикам. Добавление шумной метрики автоматически сделает поведение шумным.

  • Главный триггер: RPS/pod или queue depth.
  • Страховочный: CPU (чтобы поймать регрессии и неожиданные циклы).
  • Memory: только если понимаете корреляцию и риск OOM.

Частые ошибки в манифестах HPA v2

  • Использовать averageUtilization без выставленных requests (или с «на глаз» значениями).
  • Задать слишком маленький maxReplicas: HPA упирается в потолок, метрика остаётся выше target, а приложение деградирует.
  • Для custom metrics выбрать не тот тип (Pods vs Object vs External), из-за чего метрика агрегируется неправильно.
  • Не учесть лаг метрик: HPA реагирует на прошлое, поэтому резкие scale down опаснее.

Мини-чеклист перед продом

  1. Убедиться, что metrics-server работает и kubectl top отдаёт данные.
  2. Проверить requests CPU/Memory на основе наблюдений, а не «минимально возможные».
  3. Для custom metrics: проверить доступность Custom/External Metrics API и конкретный путь через kubectl get --raw.
  4. Поставить «быстро вверх, медленно вниз»: окно стабилизации для scale down и ограничения политики.
  5. Оценить время прогрева/старта подов и подстроить stabilizationWindowSeconds под реальность.
  6. После изменений наблюдать HPA Events и динамику метрик минимум сутки на реальном трафике.

Итог

HPA v2 даёт достаточно рычагов, чтобы сделать autoscaling предсказуемым: CPU/Memory через metrics-server, custom/external метрики через prometheus-adapter, а против flapping — грамотные stabilizationWindowSeconds и policies. В большинстве случаев источник проблемы не «HPA сам по себе», а шумная метрика, неверные requests или слишком агрессивный scale down.

Если параллельно выстроили мониторинг, не забудьте про контроль сроков сертификатов и предупреждения заранее: алерты по истечению SSL-сертификатов и продлению.

Поделиться статьей

Вам будет интересно

Nginx DNS в Docker/Kubernetes: resolver, valid и ipv6=off без сюрпризов OpenAI Статья написана AI (GPT 5)

Nginx DNS в Docker/Kubernetes: resolver, valid и ipv6=off без сюрпризов

Когда backend в Docker или Kubernetes меняет IP, Nginx может продолжать подключаться к «старому» адресу. Разбираем, как работает D ...
DNSSEC на практике: KSK/ZSK, DS record и безопасный rollover без SERVFAIL OpenAI Статья написана AI (GPT 5)

DNSSEC на практике: KSK/ZSK, DS record и безопасный rollover без SERVFAIL

Разбираем DNSSEC на практике: как устроены KSK/ZSK и DS record, как читать DNSKEY/RRSIG, почему при ошибках появляется SERVFAIL и ...
Linux passthrough (VFIO): включение IOMMU (VT-d/AMD-Vi), проверка и типовые проблемы OpenAI Статья написана AI (GPT 5)

Linux passthrough (VFIO): включение IOMMU (VT-d/AMD-Vi), проверка и типовые проблемы

Практический разбор IOMMU в Linux для PCI passthrough: включаем VT-d/AMD-Vi в BIOS и через grub, проверяем /proc/cmdline и dmesg, ...