← Kubernetes: рабочие нагрузки
7 мин · средне · Урок 9 из 11

HorizontalPodAutoscaler

Как HPA считает нужное число реплик, почему без resources.requests он молчит и что делает блок behavior.

Что такое HPA

metrics CPU по Pod раз в 15с HPA цель 50% правит Deployment spec.replicas создаёт Pod ×N нагрузка
Цепочка одна и та же на каждом тике: метрики, расчёт, новое число реплик.

HorizontalPodAutoscaler (HPA) - контроллер, который автоматически меняет число реплик Deployment по нагрузке. Deployment - объект, который держит нужное число одинаковых Pod. Pod - наименьшая единица запуска, внутри неё работает контейнер. Реплика - один из одинаковых Pod в наборе.

Цель HPA - держать среднее потребление ресурсов рядом с заданным процентом. Если каждая реплика ест 90% CPU при target 50%, HPA добавит реплики. Если потребление упало до 10%, убавит.

HPA живёт внутри kube-controller-manager. Раз в 15 секунд он опрашивает metrics-server, считает текущее потребление и сравнивает с целью. metrics-server - компонент, который собирает текущие метрики ресурсов. После расчёта HPA меняет spec.replicas у целевого Deployment, дальше работает обычный механизм выкатки.

Если metrics-server отвалился, HPA замирает на текущем числе реплик: метрики не приходят, считать не из чего.

HPA меняет только число реплик одного приложения (workload). Менять requests у существующих Pod умеет VerticalPodAutoscaler. Добавлять и убирать ноды умеет Cluster Autoscaler. HPA - самый частый из трёх.

Минимальный YAML

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: cpu-burner
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: cpu-burner
  minReplicas: 1
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

Та же настройка одной командой:

kubectl autoscale deploy cpu-burner --min=1 --max=5 --cpu-percent=50

Разбор полей

scaleTargetRef: объект, которым управляет HPA. Чаще Deployment, бывает StatefulSet. Указывают именно контроллер, не Pod.

minReplicas и maxReplicas: нижняя и верхняя границы числа реплик. Без maxReplicas HPA может раскатать слишком много Pod и положить кластер.

metrics: список метрик для решения. Метрик может быть несколько, HPA берёт максимум числа реплик по каждой.

target.type: Utilization задаёт цель в процентах от requests. requests: объём ресурсов, который Pod запрашивает при старте. Тип AverageValue задаёт цель в абсолютных значениях, например 200m CPU на Pod.

Формула решения

desiredReplicas = ceil(currentReplicas * currentMetricValue / targetMetricValue)

Один Pod ест 100% от requests, цель 50%. Получается ceil(1 * 100 / 50) = 2. HPA ставит 2 реплики. Если оба Pod дальше едят 100%, на следующем тике выйдет ceil(2 * 100 / 50) = 4. Потом HPA упрётся в maxReplicas и остановится.

Пересчёт идёт не строго каждые 15 секунд. У алгоритма есть окно стабилизации: HPA сглаживает колебания, чтобы не реагировать на кратковременные пики. От появления нагрузки до нового числа реплик обычно проходит около минуты.

behavior: разная скорость вверх и вниз

В autoscaling/v2 есть блок behavior:

behavior:
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
      - type: Percent
        value: 100
        periodSeconds: 30
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
      - type: Percent
        value: 10
        periodSeconds: 60

По умолчанию вверх HPA скейлит быстро, а вниз медленно. После спада нагрузки он ждёт около 5 минут и только потом убавляет реплики. Это защита от лишних движений при коротких провалах нагрузки. Лучше подержать лишний Pod, чем дёргать пользователей пересборкой.

requests обязательны

Без resources.requests HPA не работает. В колонке Targets будет стоять <unknown>/50%, и автоскейл просто молчит. Причина в том, что averageUtilization - это процент от requests, и без них делить не на что.

Связанные команды

kubectl autoscale deploy <name> --min=1 --max=5 --cpu-percent=50
kubectl get hpa
kubectl describe hpa <name>           # events с причинами решений
kubectl get hpa -A                    # все HPA в кластере
kubectl explain hpa.spec.behavior

Что часто ломается

Домашка

Теорию закрепляет задание на своём кластере: 1 шаг с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-hpa     # развернуть стартовое состояние
./run.sh verify k8s-hpa    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.