Питання 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’а

Приклад:

  • Бажана CPU: 50%
  • Поточна CPU: 100%
  • Поточні репліки: 2
  • Результат: ceil[2 × (100/50)] = 4 репліки

Джерела метрик

Тип Звідки Приклад
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 за замовчуванням (консервативний)

stabilization window — період «остивання» після масштабування. Запобігає 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