Что такое HorizontalPodAutoscaler (HPA)?
HPA — как менеджер в ресторане:
Junior уровень
Простое объяснение
HorizontalPodAutoscaler (HPA) — это автоматический контроллер Kubernetes, который меняет количество Pod’ов в зависимости от нагрузки. Много запросов → больше Pod’ов. Мало запросов → меньше Pod’ов.
Простая аналогия
HPA — как менеджер в ресторане:
- Много клиентов → открывает дополнительные кассы
- Клиентов мало → закрывает лишние кассы, экономит ресурсы
Как работает HPA?
- HPA проверяет загрузку CPU Pod’ов каждые 15 секунд
- Если CPU выше целевого значения → добавляет Pod’ы
- Если CPU ниже → удаляет Pod’ы
- Число 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?
- Metrics Server — собирает метрики CPU/Memory
- 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)
Решение:
- Readiness Probe с проверкой warmup
- Initial delay для HPA (stabilization window)
- 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
Причины:
- Metrics Server не установлен
- Нет requests в Pod spec
- Метрики ещё не собраны (подождите 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