Що таке HorizontalPodAutoscaler
HPA — це адміністратор ресторану у п'ятницю ввечері:
🟢 Junior Level
30-секундна відповідь
HorizontalPodAutoscaler (HPA) — це вбудований контролер Kubernetes, який автоматично регулює кількість реплік подів у Deployment або StatefulSet залежно від поточного навантаження на застосунок.
- Як це працює: HPA кожні 15 секунд опитує
Metrics Server, вимірює середню утилізацію ресурсів (наприклад, завантаження процесора CPU) і порівнює її з цільовим порогом (Target). - Сплеск трафіку: навантаження на CPU зросло вище цільового $\to$ HPA збільшує кількість подів (Scale Up), розподіляючи навантаження.
- Спад трафіку: вночі користувачі не активні, CPU знизився $\to$ HPA плавно зменшує кількість подів до мінімуму (Scale Down), заощаджуючи серверні потужності.
Наочна аналогія з життя
HPA — це адміністратор ресторану у п’ятницю ввечері:
- Якщо столики переповнені й офіціанти бігають у милі (завантаження CPU > 70%), адміністратор викликає на зміну додаткових офіціантів із резерву.
- Коли опівночі гості розходяться (завантаження CPU < 20%), зайвих офіціантів відпускають додому, щоб заклад не оплачував їм години простою.
Базовий маніфест HPA (API autoscaling/v2)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: payment-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: payment-service
minReplicas: 2 # Мінімальна квота для High Availability
maxReplicas: 10 # Захист від перевитрати бюджету
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # Тримати середнє завантаження CPU близько 60%
[!IMPORTANT] Дві фундаментальні вимоги для роботи HPA:
- У кластері має бути встановлений і запущений
Metrics Server.- У маніфесті пода ОБОВ’ЯЗКОВО мають бути задані
resources.requests.cpu, оскільки відсоток завантаження обчислюється строго від значенняrequests!
🟡 Middle Level
Формула розрахунку реплік та поріг толерантності (Tolerance)
Контролер HPA обчислює необхідну кількість реплік за математичною формулою:
\[\mathbf{DesiredReplicas} = \left\lceil \mathbf{CurrentReplicas} \times \left( \frac{\mathbf{CurrentMetricValue}}{\mathbf{TargetMetricValue}} \right) \right\rceil\]Захисний поріг толерантності (10% Tolerance)
Щоб контролер не смикав поди туди-сюди через коливання в 1–2%:
- У K8s вбудовано параметр
horizontal-pod-autoscaler-tolerance(за замовчуванням0.1, тобто 10%). -
Якщо співвідношення $\left \frac{\text{Current}}{\text{Target}} - 1.0 \right \le 0.1$, HPA взагалі нічого не робить! - Приклад: якщо цільовий CPU = 60%, а поточний коливається між 55% і 65%, HPA не масштабує систему.
4 типи підтримуваних метрик в autoscaling/v2
| Тип метрики | Джерело даних | Приклад використання |
|---|---|---|
Resource |
Metrics Server (cgroups) | Стандартний cpu або memory контейнера. |
Pods |
Prometheus Adapter | Метрики застосунку, агреговані за подами (наприклад, HTTP RPS на под). |
Object |
Prometheus Adapter / K8s API | Метрика стороннього K8s об’єкта (глибина черги на Ingress). |
External |
Зовнішні провайдери (Datadog/CloudWatch) | Глибина черги Amazon SQS, довжина черги RabbitMQ. |
Тонке налаштування швидкості: Блок behavior
Для запобігання ефекту «брязкання» (Flapping) налаштовують вікна стабілізації:
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # Масштабуватися вгору негайно
policies:
- type: Percent
value: 100 # Максимум подвоювати поди за один крок
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300 # Чекати 5 хвилин спаду перед видаленням!
policies:
- type: Pods
value: 1 # Видаляти не більше 1 пода раз на 60 секунд
periodSeconds: 60
🔴 Senior Level
Правило вирішення множинних метрик (Multi-Metric HPA)
Якщо в HPA оголошено кілька метрик (наприклад, CPU + RPS + Latency):
metrics:
- type: Resource
resource: { name: cpu, target: { type: Utilization, averageUtilization: 60 } } # Розрахунок: 4 поди
- type: Pods
pods: { metric: { name: http_requests_per_second }, target: { averageValue: "100" } } # Розрахунок: 8 подів
Алгоритм вибору: HPA обчислює кількість реплік для кожної метрики незалежно і вибирає МАКСИМАЛЬНЕ значення (MAX) з усіх отриманих результатів. У даному прикладі буде встановлено 8 подів.
Проблема «Хибного овершутингу» в Java (JIT Warmup Trap)
У реальних production-кластерах із Java Spring Boot спостерігається небезпечний феномен:
- Трафік зріс $\to$ HPA додає 2 нових поди.
- Нові JVM поди запускаються. На фазі старту компілятор C2 JIT починає агресивно оптимізувати методи, спричиняючи короткочасний стрибок CPU до 100% на 30–45 секунд.
- HPA опитує Metrics Server, бачить 100% CPU на нових подах і вважає, що навантаження все ще надвисоке.
- HPA додає ще 4 поди $\to$ вони теж спричиняють 100% JIT-навантаження $\to$ HPA полетить у
maxReplicas(ефект лавини). Архітектурне рішення:- Налаштування
startupProbeзі збільшеним часом, щоб под не вважався готовим до завершення базової ініціалізації. - Використання
behavior.scaleUp.stabilizationWindowSeconds: 60або політик обмеження приросту. - Перехід на GraalVM Native Image або технологію CRaC (Coordinated Restore at Checkpoint) у Java 21.
- Налаштування
Архітектура KEDA (Kubernetes Event-Driven Autoscaling)
Коли метрик Prometheus недостатньо, стандартом де-факто стає KEDA:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: kafka-consumer-scaler
spec:
scaleTargetRef:
name: payment-consumer
minReplicaCount: 0 # Повна підтримка Scale to Zero!
maxReplicaCount: 20
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: payment-processors
topic: payments
lagThreshold: "100" # Додавати под на кожні 100 повідомлень лагу
Під капотом KEDA автоматично створює нативний HPA та реєструє свій External Metrics API сервер, приховуючи складність роботи з Prometheus Adapter.
4 Tricky Questions
1. Як працює вбудований поріг толерантності HPA (10% Tolerance), і чому HPA не робить дій, якщо CPU зріс з 50% до 54% при target = 50%?
Відповідь:
Для запобігання постійному смиканню подів через незначні коливання навантаження контролер HPA використовує формулу перевірки толерантності:
\(\left| \frac{\text{CurrentMetricValue}}{\text{TargetMetricValue}} - 1.0 \right| \le \text{tolerance}\)
За замовчуванням прапорець --horizontal-pod-autoscaler-tolerance дорівнює 0.1 (10%).
У даному випадку: $54 / 50 = 1.08$.
Величина відхилення: $|1.08 - 1.0| = 0.08$ (8%), що строго менше порогу в 10% (0.1).
Оскільки відхилення не перевищило поріг толерантності, контролер HPA повністю ігнорує цю зміну і зберігає поточну кількість реплік незмінною.
2. Чому у виводі команди kubectl get hpa у стовпчику TARGETS відображається статус <unknown>/60%, і які 3 причини викликають цей стан?
Відповідь:
Статус <unknown> означає, що контролер HPA не може прочитати метрики утилізації подів із Kubernetes Resource Metrics API (v1beta1.metrics.k8s.io).
Три головні причини:
- Відсутність
resources.requests: у шаблоні контейнера Deployment не заданіrequests.cpu. Без них HPA фізично не може обчислити відсоток використання. - Metrics Server не встановлений або впав: у кластері відсутній або аварійно завершився под
metrics-server(або він запущений без прапорця--kubelet-insecure-tlsу тестових кластерах). - Холодний старт подів: поди щойно запустилися, і Metrics Server ще не встиг зібрати перший інтервал агрегації (зазвичай потрібно почекати 30–60 секунд).
3. Якщо в HPA задано 3 метрики: CPU (вимагає 4 поди), Memory (вимагає 6 подів) та Custom RPS (вимагає 8 подів), яку підсумкову кількість реплік виставить контролер?
Відповідь:
Контролер виставить 8 подів.
Відповідно до специфікації Kubernetes autoscaling/v2, при оголошенні кількох метрик у блоці metrics контролер HPA здійснює незалежний розрахунок необхідної кількості реплік для кожного правила окремо, а потім застосовує функцію max() до отриманих результатів:
\(\text{Replicas} = \max(\text{Replicas}_{\text{CPU}}, \text{Replicas}_{\text{Memory}}, \text{Replicas}_{\text{RPS}}) = \max(4, 6, 8) = 8\)
Це зроблено для забезпечення надійності: система орієнтується на найбільш перевантажений ресурс, гарантуючи дотримання SLA.
4. У чому небезпека масштабування Deployment за допомогою kubectl scale --replicas=5, якщо для цього ж Deployment паралельно активний об’єкт HPA?
Відповідь: Виникне конфлікт імперативного та декларативного керування:
- Команда
kubectl scaleпримусово оновить полеspec.replicas: 5у Deployment. - Проте через 15 секунд прокинеться цикл узгодження HPA (
Reconciliation Loop). - Контролер HPA оцінить поточне реальне навантаження на поди. Якщо навантаження низьке й відповідає 2 реплікам, HPA миттєво перезапише значення
spec.replicasназад на 2, примусово видаливши 3 щойно створені поди. Правило: при активному HPA ручне масштабування черезkubectl scaleне має сенсу; необхідно змінювати межіminReplicasтаmaxReplicasу самому об’єкті HPA.
🎯 Шпаргалка для інтерв’ю
Головне про HPA
- Суть: контролер автоматичного горизонтального масштабування подів.
- Інтервал опитування: кожні 15 секунд через Metrics API.
- Обов’язкові вимоги:
Metrics Serverу кластері таresources.requestsу маніфесті пода. - Формула: $\text{Desired} = \lceil \text{Current} \times (\text{CurrentMetric} / \text{TargetMetric}) \rceil$.
- Множинні метрики: завжди обирається
MAX()з усіх розрахунків. - Java Golden Rule: уникати масштабування за пам’яттю; масштабувати строго за CPU або RPS.
- Стабілізація (Behavior): scaleUp швидкий (0–15s), scaleDown повільний (300s).
Типи метрик HPA
| Тип | Джерело | Застосування |
| :— | :— | :— |
| Resource | cgroups контейнера | CPU, Memory |
| Pods | Prometheus Adapter | HTTP RPS, P99 Latency |
| Object | K8s ресурси | Ingress connections, Queue size |
| External | Хмарні API / Datadog | Kafka Lag (KEDA), AWS SQS |
Червоні прапорці на співбесіді (Чого говорити не можна)
- ❌ «HPA розраховує відсоток завантаження CPU від значення resources.limits» — відсоток завжди рахується строго від
resources.requests. - ❌ «Якщо для Deployment налаштований HPA, я можу в будь-який момент смасштабувати його командою kubectl scale» — HPA через 15 секунд перезапише кількість реплік назад.
- ❌ «HPA вміє масштабувати сервіс з 0 подів при надходженні трафіку» — стандартний HPA не вміє Scale to Zero; для цього потрібен KEDA або Knative.