DEV Community

Denis Toropov
Denis Toropov

Posted on

HPA введение

Зачем это нужно: реальная ситуация

У вас есть веб-приложение — API на Java, которое отдаёт JSON. Оно крутится в Kubernetes в виде Deployment с 2 репликами.

Понедельник, 3 часа ночи. Нагрузка — 10 запросов в секунду. Каждый Pod ест 5% CPU. Всё спокойно.

Понедельник, 10 утра. Все сотрудники зашли в систему, начали работать. Нагрузка — 300 запросов в секунду. Каждый Pod ест 180% CPU (да, больше 100% — потому что CPU-лимит позволяет использовать несколько ядер). Запросы копятся, latency растёт с 50 мс до 3 секунд. Пользователи жалуются.

Что делать?

Вариант А — вручную: заходите, меняете replicas: 2 на replicas: 10, ждёте. В 11 утра нагрузка спала — забыли вернуть обратно, платите за 10 Pod'ов круглосуточно.

Вариант Б — HPA: вы один раз описываете правило «держи CPU в среднем на 50%», и Kubernetes сам:

  • в 10 утра добавляет Pod'ы до 10;
  • к обеду, когда нагрузка спала, убирает лишние обратно до 2.

Это и есть горизонтальное автомасштабирование.


Что значит «Horizontal»?

Есть два способа справиться с нагрузкой на Pod:

Способ Что делаем В Kubernetes
Вертикальный (Vertical) Даём Pod'у больше CPU/RAM VPA
Горизонтальный (Horizontal) Добавляем копии Pod'ов HPA

HPA — это про количество копий, а не про их «мощность».

Нагрузка низкая:   [Pod]                  
Нагрузка высокая:  [Pod][Pod][Pod][Pod]    ← это делает HPA
Enter fullscreen mode Exit fullscreen mode

Как это работает (простыми словами)

HPA — это контроллер внутри кластера, который просыпается каждые 15 секунд и делает одно и то же:

1. Спросить метрику   →  "средний CPU по Pod'ам = 80%"
2. Сравнить с целью    →  "я хотел 50%"
3. Посчитать реплики   →  "80 / 50 = 1.6, надо больше"
4. Обновить Deployment →  replicas: 2 → 4
5. Поспать 15 сек      →  и снова с шага 1
Enter fullscreen mode Exit fullscreen mode

Формула, которую HPA использует внутри:

желаемые реплики = текущие реплики × (текущая метрика / целевая метрика)
Enter fullscreen mode Exit fullscreen mode

Пример: 2 Pod'а, средний CPU = 80%, цель = 50%.

2 × (80 / 50) = 3.2  →  округляем вверх  →  4 Pod'а
Enter fullscreen mode Exit fullscreen mode

Обратный пример: 4 Pod'а, средний CPU = 20%, цель = 50%.

4 × (20 / 50) = 1.6  →  округляем вверх  →  2 Pod'а (упёрлись в minReplicas)
Enter fullscreen mode Exit fullscreen mode

По каким метрикам можно масштабировать?

От простого к сложному:

  1. CPU — самый частый вариант. «Держи средний CPU на 50%».
  2. Память — реже, потому что память плохо освобождается. Приложение может держать её даже под низкой нагрузкой, и HPA будет «залипать» на высоком значении.
  3. Кастомные метрики Pod'ов — например, количество запросов в секунду (RPS) через Prometheus.
  4. Внешние метрики — длина очереди в Kafka, число сообщений в RabbitMQ, метрики из облака.

Самое простое — начните с CPU. Это работает «из коробки» и покрывает 80% случаев.


Первый HPA: пошагово

Шаг 0. Что нужно

  • Работающий кластер Kubernetes.
  • Установленный metrics-server — компонент, который собирает CPU/RAM по Pod'ам.

Проверить:

kubectl top pods
Enter fullscreen mode Exit fullscreen mode

Если видите таблицу с CPU и MEMORY — всё ок. Если ошибка Metrics API not available — HPA работать не будет, сначала ставьте metrics-server.

Шаг 1. Deployment с указанными requests

Критически важно: HPA считает проценты от requests, а не от лимитов и не от реального железа. Если requests не заданы — HPA покажет <unknown> и ничего не сделает.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app:1.0
        resources:
          requests:
            cpu: "100m"      # ← вот это обязательно
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
Enter fullscreen mode Exit fullscreen mode

Здесь 100m = 0.1 ядра. То есть «этому приложению для нормальной работы нужно минимум 0.1 ядра».

Шаг 2. Сам HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app              # ← кого масштабируем
  minReplicas: 2              # ← никогда меньше 2
  maxReplicas: 10             # ← никогда больше 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50   # ← цель: средний CPU = 50% от requests
Enter fullscreen mode Exit fullscreen mode

Применить:

kubectl apply -f deployment.yaml
kubectl apply -f hpa.yaml
Enter fullscreen mode Exit fullscreen mode

Шаг 3. Проверить

kubectl get hpa
Enter fullscreen mode Exit fullscreen mode

Вывод:

NAME         REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
my-app-hpa   Deployment/my-app   12%/50%   2         10        2          30s
Enter fullscreen mode Exit fullscreen mode

Читается так: «сейчас средний CPU = 12%, цель = 50%, поэтому держим минимум — 2 Pod'а».

Нагрузите приложение — и увидите, как REPLICAS начнёт расти.

Полезная команда для наблюдения в реальном времени:

kubectl get hpa -w
Enter fullscreen mode Exit fullscreen mode

Флаг -w (watch) обновляет вывод при каждом изменении.


Три главные ошибки

1. Не заданы resources.requests
HPA не может посчитать проценты и молча ничего не делает. Всегда проверяйте kubectl describe hpa — там будет строка AbleToScale: False с причиной.

2. Нет metrics-server
kubectl top pods не работает → HPA не работает. Это первое, что нужно проверить при отладке.

3. Слишком агрессивные настройки
minReplicas: 1 + averageUtilization: 10% → приложение будет постоянно скакать вверх-вниз (это называется flapping). Начните с разумных значений: minReplicas: 2, цель 50–70%.


Что запомнить

  • HPA = автомат, который добавляет/убирает копии Pod'ов.
  • Работает по метрикам: обычно CPU.
  • Требует resources.requests и metrics-server.
  • Формула простая: текущие × (факт / цель), округление вверх.
  • Начинайте с CPU, цели 50–70%, minReplicas: 2.
  • Не путайте с:
    • VPA — меняет размер одного Pod'а;
    • Cluster Autoscaler — меняет количество узлов в кластере;
    • KEDA — масштабирует по событиям из очередей и cron.

Top comments (0)