Вопрос 15 · Раздел 14

Что такое HorizontalPodAutoscaler (HPA)?

HPA — как менеджер в ресторане:

Версии по языкам: English Russian Ukrainian

Junior уровень

Простое объяснение

HorizontalPodAutoscaler (HPA) — это автоматический контроллер Kubernetes, который меняет количество Pod’ов в зависимости от нагрузки. Много запросов → больше Pod’ов. Мало запросов → меньше Pod’ов.

Простая аналогия

HPA — как менеджер в ресторане:

  • Много клиентов → открывает дополнительные кассы
  • Клиентов мало → закрывает лишние кассы, экономит ресурсы

Как работает HPA?

  1. HPA проверяет загрузку CPU Pod’ов каждые 15 секунд
  2. Если CPU выше целевого значения → добавляет Pod’ы
  3. Если CPU ниже → удаляет Pod’ы
  4. Число Pod’ов остаётся в границах min/max

Простой пример

# Автоматически поддерживать CPU ~50%, от 2 до 10 Pod'ов
kubectl autoscale deployment myapp --cpu-percent=50 --min=2 --max=10

Или через YAML:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

Что нужно для работы HPA?

  1. Metrics Server — собирает метрики CPU/Memory
  2. Requests в Pod’е — HPA считает процент от Request, не от Limit
resources:
  requests:
    cpu: "500m"    # Обязательно!

Что запомнить Junior-разработчику

  • HPA автоматически меняет число Pod’ов
  • Работает по CPU (или другим метрикам)
  • Требует Metrics Server и Resources Requests
  • Задавайте min/max реплики для контроля
  • HPA не масштабирует ниже minReplicas

Middle уровень

Формула HPA

desiredReplicas = ceil[currentReplicas × (currentMetricValue / desiredMetricValue)]

// desiredReplicas = ceil(currentReplicas * (currentMetric / desiredMetric)) // Пример: ceil(2 * (300m / 200m)) = ceil(2 * 1.5) = ceil(3.0) = 3 Pod’а

Пример:

  • Desired CPU: 50%
  • Current CPU: 100%
  • Current replicas: 2
  • Result: ceil[2 × (100/50)] = 4 replicas

Источники метрик

Тип Откуда Пример
Resource Metrics Server CPU, Memory
Pods Prometheus Adapter RPS, latency
Object Prometheus Adapter Requests per queue
External Внешние системы AWS SQS queue length

Memory-based scaling: почему это плохая идея

Java приложения не всегда возвращают память ОС сразу после GC. Это приводит к:

  • HPA видит высокий memory usage
  • Добавляет Pod’ы бесконечно
  • Ресурсы тратятся зря

Рекомендация: Масштабируйте по CPU или бизнес-метрикам, не по памяти.

Behavior: настройка скорости масштабирования

behavior:
  scaleUp:
    stabilizationWindowSeconds: 60
    policies:
    - type: Pods
      value: 4
      periodSeconds: 60
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Pods
      value: 1
      periodSeconds: 120

Scale Down медленнее Scale Up — это защищает от преждевременного удаления Pod’ов.

Конфликт HPA и VPA

Не используйте HPA и VPA одновременно для CPU:

  • HPA добавляет Pod’ы при высоком CPU
  • VPA увеличивает CPU на Pod
  • Они “борются” → нестабильность

Что запомнить Middle-разработчику

  • HPA формула: желаемые реплики = текущие × (текущая метрика / желаемая)
  • Масштабирование по памяти — антипаттерн для Java
  • Behavior контролирует скорость scale up/down
  • Не используйте HPA + VPA для одной метрики
  • maxReplicas защищает бюджет от внезапных всплесков

Senior уровень

HPA как система управления ёмкостью

HPA — это не просто “авто скейлинг”, а инструмент балансировки между SLA и cost optimization.

Алгоритм HPA v2: детальный анализ

Цикл принятия решений:

Every 15 seconds (syncPeriod):
1. Fetch metrics for all targeted pods
2. Calculate desired replicas per metric
3. Take MAX across all metrics
4. Apply behavior policies (scale up/down limits)
5. Enforce min/max bounds
6. Patch Deployment spec.replicas

Stabilization Window:

  • При Scale Up: 60s по умолчанию (быстрая реакция)
  • При Scale Down: 300s по умолчанию (консервативный)

stabilizationWindow — период «остывания» после масштабирования. Предотвращает flapping (быстрое масштабирование вверх-вниз при колебаниях нагрузки).

Это предотвращает “thrashing” — постоянное добавление/удаление Pod’ов.

Multi-metric HPA

metrics:
- type: Resource
  resource:
    name: cpu
    target:
      type: Utilization
      averageUtilization: 70
- type: Pods
  pods:
    metric:
      name: http_requests_per_second
    target:
      type: AverageValue
      averageValue: "100"

HPA выбирает MAX из расчётов по каждой метрике.

Prometheus Adapter для Custom Metrics

# Prometheus rule
- record: http_requests_per_second
  expr: rate(http_requests_total[5m])

# Prometheus Adapter config
rules:
- seriesQuery: 'http_requests_per_second{namespace!="",pod!=""}'
  resources:
    overrides:
      namespace: {resource: "namespace"}
      pod: {resource: "pod"}
  name:
    matches: "^(.*)"
    as: "${1}"
  metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)

HPA и Java-приложения: специфика

JIT Warmup:

  • Новые Pod’ы имеют “холодный” JIT
  • Первые запросы обрабатываются медленнее
  • CPU может временно подскочить → HPA добавит ещё Pod’ы (over-shooting)

Решение:

  1. Readiness Probe с проверкой warmup
  2. Initial delay для HPA (stabilization window)
  3. Startup Probe для долгого warmup

G1 GC и CPU:

  • G1 GC использует CPU для concurrent marking
  • HPA может интерпретировать это как нагрузку
  • Настройте -XX:ConcGCThreads и -XX:ParallelGCThreads

Scaling на основе очередей (KEDA)

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaling
spec:
  scaleTargetRef:
    name: worker-deployment
  minReplicaCount: 1
  maxReplicaCount: 50
  triggers:
  - type: rabbitmq
    metadata:
      queueName: tasks
      queueLength: "10"
      activationQueueLength: "5"

KEDA создаёт HPA с custom metrics.

Troubleshooting

HPA показывает <unknown>:

kubectl get hpa
# NAME         REFERENCE           TARGETS   MINPODS   MAXPODS
# myapp-hpa    Deployment/myapp    <unknown> 2         10

Причины:

  1. Metrics Server не установлен
  2. Нет requests в Pod spec
  3. Метрики ещё не собраны (подождите 1-2 минуты)

HPA не масштабирует:

kubectl describe hpa myapp-hpa
# Warning: FailedGetResourceMetric  unable to fetch metrics

Cost optimization через HPA

# Ограничение бюджета
maxReplicas: 20  # не больше 20 Pod'ов = контроль затрат

# Медленный scale down
scaleDown:
  stabilizationWindowSeconds: 600  # 10 минут

Резюме для Senior

  • HPA — основной инструмент горизонтального масштабирования.
  • Алгоритм: MAX(desired replicas per metric), с behavior policies.
  • Всегда задавайте разумный maxReplicas для контроля бюджета.
  • Behavior (stabilization window) предотвращает thrashing.
  • Базируйте скейлинг на CPU или кастомных бизнес-метриках, не на памяти.
  • KEDA для event-driven масштабирования (очереди, стримы).
  • Java специфика: JIT warmup, GC overhead — учитывайте при настройке.
  • HPA + VPA конфликтуют по CPU — используйте раздельно.

🎯 Шпаргалка для интервью

Обязательно знать:

  • HPA автоматически масштабирует число Pod’ов по CPU, memory, custom или external метрикам
  • Формула: desiredReplicas = ceil[current × (currentMetric / desiredMetric)]
  • Требует Metrics Server и Resources Requests (считает % от requests, не limits)
  • Behavior: stabilization window (scale up 60s, scale down 300s по умолчанию)
  • HPA выбирает MAX из расчётов по всем метрикам
  • Масштабирование по памяти — антипаттерн для Java (JVM GC, lazy memory return)
  • KEDA — event-driven HPA (Kafka, RabbitMQ, SQS); scale-to-zero с Knative

Частые уточняющие вопросы:

  • «Почему HPA показывает <unknown> — Metrics Server не установлен, нет requests, или метрики ещё не собраны
  • «Java JIT warmup и HPA?» — Новые Pod’ы «холодные», CPU подскакивает → HPA over-shooting; используйте startupProbe
  • «HPA + VPA вместе?» — Нет по одной метрике; VPA в режиме Off для рекомендаций
  • «Зачем maxReplicas?» — Защита бюджета от внезапных всплесков нагрузки

Красные флаги (НЕ говорить):

  • «Масштабирую Java по memory usage» (JVM не возвращает память сразу после GC)
  • «HPA без requests» (не работает, <unknown>)
  • «Ставлю periodSeconds=1 для быстрой реакции» (thrashing, лишняя нагрузка)
  • «HPA заменяет Cluster Autoscaler» (HPA → Pod’ы, CA → Node; разные уровни)

Связанные темы:

  • [[Как происходит масштабирование в Kubernetes]] — все виды масштабирования
  • [[Зачем нужны health checks]] — startupProbe для Java warmup
  • [[Как мониторить приложения в Kubernetes]] — custom metrics для HPA