Задача 10. HPA: почему автомасштабирование не срабатывает

HPA настроен на 70% CPU, поды загружены под завязку, но реплики не добавляются. Разбираем, что проценты считаются от requests, а не от лимитов, и что бывает, когда requests не заданы.
Опубликовано:

Задача

Настроен HorizontalPodAutoscaler:

YAML
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
Нажмите, чтобы развернуть и увидеть больше

Нагрузка выросла, приложение тормозит, kubectl top pods показывает высокое потребление CPU. Реплик по-прежнему две.

kubectl get hpa выводит в колонке TARGETS значение <unknown>/70%.

Вопрос: почему HPA не масштабирует?

Что кажется очевидным

«Метрики не собираются, надо чинить metrics-server». Направление верное, но <unknown> возникает и по другой, более коварной причине.

Как это работает на самом деле

Главное, что нужно понять про HPA: averageUtilization — это процент не от лимита и не от мощности ноды, а от requests.

Формула:

PLAINTEXT
utilization = текущее потребление CPU / requests.cpu × 100%
Нажмите, чтобы развернуть и увидеть больше

Отсюда два следствия:

1. Без requests.cpu HPA не работает вовсе. Делить не на что — метрика становится <unknown>, масштабирования нет. Это и есть самая частая причина.

2. Проценты могут превышать 100. Если requests.cpu: 100m, а под потребляет 500m, утилизация — 500%. Это нормально: requests — обещание, а не потолок (см. задачу 3).

Отсюда же неочевидный эффект: завышенные requests «прячут» нагрузку от HPA. При requests.cpu: 2 и реальном потреблении 1 утилизация — 50%, порог в 70% не достигается, и HPA не реагирует, хотя приложению плохо по другим причинам.

Как HPA принимает решение

Желаемое число реплик считается так:

PLAINTEXT
желаемые = ceil( текущие × ( текущая метрика / целевая метрика ) )
Нажмите, чтобы развернуть и увидеть больше

При 2 репликах, текущей утилизации 140% и цели 70% получится ceil(2 × 140/70) = 4 реплики.

Дополнительно действуют встроенные предохранители:

Ответ

Метрика <unknown> означает, что HPA не может вычислить утилизацию. Две причины по частоте:

  1. У контейнеров не заданы requests.cpu — нет базы для расчёта процента;
  2. Не установлен или не работает metrics-server — нет данных о потреблении.

Что с этим делать

Проверка по шагам

BASH
# 1. Есть ли метрики вообще
kubectl top pods
# Если "error: Metrics API not available" — нет metrics-server

kubectl get deployment metrics-server -n kube-system

# 2. Заданы ли requests
kubectl get deployment api -o jsonpath='{.spec.template.spec.containers[*].resources}'

# 3. Что говорит сам HPA — в событиях причина обычно названа прямо
kubectl describe hpa api
Нажмите, чтобы развернуть и увидеть больше

В describe смотрите блок Conditions: ScalingActive: False с причиной FailedGetResourceMetric — это как раз про отсутствие метрик или requests.

Настройка, которая работает

YAML
resources:
  requests:
    cpu: "200m" # обязательно для HPA по CPU
    memory: "256Mi"
  limits:
    memory: "512Mi" # CPU-лимит часто лучше не ставить
Нажмите, чтобы развернуть и увидеть больше

requests должны отражать типичное потребление под нормальной нагрузкой — тогда проценты HPA имеют смысл.

Тонкая настройка поведения

YAML
spec:
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 50 # убирать не более половины реплик за раз
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100 # можно удваивать
          periodSeconds: 30
        - type: Pods
          value: 4
          periodSeconds: 30
      selectPolicy: Max
Нажмите, чтобы развернуть и увидеть больше

Асимметрия здесь осознанная: вверх быстро, вниз осторожно. Преждевременное схлопывание при пиковой нагрузке дороже, чем лишние поды в течение пары минут.

Чего HPA не умеет


Дальше: Задача 11. Init-контейнеры и sidecar’ы.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша