Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Рейтинг: 70.1% · 9 голосов
Kubernetes для разработчиков: поды, деплойменты, сервисы, ingress, конфиги и отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
anton_k8s
Сообщения: 55
Зарегистрирован: 12 май 2026, 03:23

Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Сообщение anton_k8s »

Оглавление курса (48)
  1. Зачем нужен Kubernetes и из чего состоит кластер
  2. Поднимаем локальный кластер: minikube и kind
  3. Поды: базовая единица запуска
  4. Deployment и ReplicaSet: управляем репликами
  5. Service: сетевой доступ к подам
  6. ConfigMap и Secret: выносим конфигурацию
  7. Ingress: пускаем трафик снаружи
  8. Хранилище: Volumes и PersistentVolumeClaim
  9. Namespaces, requests и limits
  10. Health checks: liveness и readiness пробы
  11. Отладка: почему под не стартует
  12. Helm: пакетный менеджер для Kubernetes
  13. Базовая безопасность: RBAC и доступы
  14. Job и CronJob: разовые и периодические задачи
  15. StatefulSet и DaemonSet: stateful-нагрузки и системные агенты
  16. Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints
  17. Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler (вы здесь)
  18. Наблюдаемость: логи, метрики, events, обзор Prometheus и Grafana
  19. Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов
  20. Архитектура control plane: api-server, etcd, scheduler
  21. Узел кластера: kubelet, kube-proxy и container runtime
  22. Декларативная модель: reconciliation, контроллеры, CRD
  23. kubectl профессионально: get, describe, explain, jsonpath
  24. Под глубже: init, sidecar, lifecycle hooks и QoS
  25. Метки, селекторы и организация ресурсов
  26. Сервисы и kube-proxy глубже: типы, IPVS, EndpointSlices
  27. Ingress, ingress-контроллеры и Gateway API
  28. Секреты в кластере: шифрование, External Secrets, Vault
  29. Хранилище глубже: PV, StorageClass, CSI и StatefulSet
  30. Сеть кластера: CNI, NetworkPolicy и CoreDNS
  31. Планировщик: affinity, taints, topology spread
  32. Ресурсы, QoS и вытеснение: requests, limits, eviction
  33. Helm глубже: шаблоны, хуки, зависимости, OCI
  34. Kustomize и управление конфигурацией без шаблонов
  35. RBAC и аутентификация глубже
  36. Admission и Pod Security: контроль на входе
  37. Policy as code: Kyverno и OPA Gatekeeper
  38. GitOps: Argo CD и Flux
  39. Операторы и CRD: расширяем Kubernetes
  40. Сервис-меш: Istio, Linkerd и когда он нужен
  41. Эксплуатация кластера: апгрейд, узлы, бэкап etcd
  42. Где запускать кластер: managed, self-hosted, k3s, Deckhouse
  43. Траблшутинг кластера: Pending, CrashLoop, узлы NotReady
  44. Стоимость и эффективность кластера: FinOps
  45. CI/CD в Kubernetes: сборка, деплой, прогрессивные релизы
  46. Лучшие практики и антипаттерны Kubernetes
  47. Сквозной проект и путь дальше: от манифеста до прода
  48. Деплой приложений через Argo CD: Application, sync и App-of-Apps
Зачем нужно автомасштабирование kubernetes и какую боль оно лечит

Представь типичный понедельник. В девять утра на сервис обрушивается трафик, поды захлебываются, latency растет, алерты звенят. Дежурный руками докручивает replicas, тушит пожар. К обеду нагрузка падает, но реплики так и висят на пике, ты жжешь деньги впустую. К вечеру акция, снова всплеск, и снова никто не успел. Это ручное управление мощностью, и оно проигрывает всегда: человек реагирует за минуты, нагрузка меняется за секунды.

Автомасштабирование kubernetes решает ровно это - отдает решение о количестве реплик и узлов машине, которая смотрит на метрики и крутит ручки сама. Но тут важно сразу разложить кашу по полочкам, потому что в кластере живут три принципиально разных уровня масштабирования, и их постоянно путают.
  • HPA (Horizontal Pod Autoscaler) - меняет ЧИСЛО подов. Больше нагрузки - больше копий.
  • VPA (Vertical Pod Autoscaler) - меняет РАЗМЕР пода, его requests и limits по CPU и памяти.
  • Cluster Autoscaler / Karpenter - меняет число УЗЛОВ. Подам некуда влезть - добавь железо.
Аналогия из жизни ресторана. HPA - это посадить больше официантов в зал, когда гостей много. VPA - дать каждому официанту тележку побольше, чтобы носил больше тарелок за раз. Cluster Autoscaler - пристроить к ресторану новый зал, когда официанты уже стоят в проходах и сесть некуда. Три ручки, три задачи, и работают они вместе, а не вместо друг друга.

Изображение

HPA: горизонтальное масштабирование подов и его механика

Kubernetes hpa - это контроллер в control plane, который раз в 15 секунд (флаг --horizontal-pod-autoscaler-sync-period у kube-controller-manager) просыпается, читает текущие метрики целевого Deployment и считает, сколько реплик нужно. Формула в основе одна и простая:

Код: Выделить всё

desiredReplicas = ceil(currentReplicas * (currentMetric / targetMetric))
Если у тебя 4 пода и средняя загрузка CPU 80% при цели 50%, то ceil(4 * 80/50) = ceil(6.4) = 7 реплик. Все. Никакой магии, обычная пропорция с округлением вверх.

Откуда HPA берет метрики CPU и памяти? Из metrics-server. Это отдельный компонент, который НЕ ставится по умолчанию в ванильном кластере (в Yandex Managed Kubernetes и большинстве облаков он уже есть из коробки). metrics-server собирает данные с kubelet каждого узла через Summary API и отдает их через metrics.k8s.io. Проверяется так:

Код: Выделить всё

kubectl top pods -n production
NAME                       CPU(cores)   MEMORY(bytes)
api-7d9c8f5b4-2xk9p        342m         512Mi
api-7d9c8f5b4-7nq4l        298m         480Mi
Если kubectl top отвечает "error: Metrics API not available" - HPA работать не будет, у тебя просто нет источника данных. Это грабли номер один.

Современный манифест использует apiVersion autoscaling/v2. Старый autoscaling/v1 умел только CPU и его пора забыть. Вот реальный пример с несколькими метриками сразу:

Код: Выделить всё

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 3
  maxReplicas: 30
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 75
Когда метрик несколько, HPA считает желаемые реплики по каждой и берет максимум. Логика защитная: если хоть по одному ресурсу тесно, нужно масштабироваться.

Критически важная связь: requests и HPA. averageUtilization это процент от requests, а не от лимита и не от физического ядра. Если в поде

Код: Выделить всё

resources.requests.cpu: 500m
, то 60% утилизации это 300m реального потребления. А если requests не указан вообще? Тогда HPA не может вычислить процент, метрика становится "unknown", и масштабирование по CPU/памяти просто не работает. Запомни железно: нет requests - нет HPA по Utilization. Это вторые по частоте грабли.

Поведение scaleUp и scaleDown: как победить флаппинг

Голая формула склонна к дерганью - метрика прыгнула, HPA добавил подов, метрика просела, он их убрал, и так по кругу. Это флаппинг, и он бьет по стабильности. В autoscaling/v2 для этого есть секция behavior с раздельной настройкой разгона и торможения.

Код: Выделить всё

  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30
      - type: Pods
        value: 4
        periodSeconds: 30
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
Разбираем по полям. stabilizationWindowSeconds - окно сглаживания: HPA смотрит на рекомендации за последние N секунд и для scaleDown берет максимум из них, чтобы не схлопнуться на случайной просадке. Для scaleUp здесь стоит 0 - разгоняемся мгновенно, реагируем на всплеск без задержки. Для scaleDown 300 секунд - пять минут трафик должен реально держаться низким, прежде чем гасим реплики. Это правильная асимметрия: вверх быстро, вниз осторожно.

policies - ограничители скорости. scaleUp разрешает либо +100% (удвоение), либо +4 пода за 30 секунд, и selectPolicy: Max берет более агрессивный вариант. scaleDown срезает не больше 50% реплик за минуту. На практике именно policies, а не окна стабилизации, защищают downstream-системы: представь, что HPA одномоментно поднял с 5 до 50 подов, и все 50 ломанулись в одну базу открывать соединения. Policies растягивают это во времени и спасают БД от лавины.

Что происходит реально, смотрим в describe:

Код: Выделить всё

kubectl describe hpa api-hpa -n production
...
Metrics:                ( current / target )
  resource cpu          72% (360m) / 60%
Events:
  Type    Reason             Message
  Normal  SuccessfulRescale  New size: 8; reason: cpu resource utilization above target
Поле "current / target" - твоя главная диагностика. Видишь 72% при цели 60% - HPA законно растет. Видишь "unknown" - вернись к разделу про requests и metrics-server.

Кастомные и внешние метрики: масштабируемся по бизнесу

CPU и память это часто плохой прокси для реальной нагрузки. Веб-сервер может стоять на 30% CPU, но захлебываться от тысячи запросов в секунду. Для таких случаев HPA умеет два других типа метрик.

Pods/Object метрики (type: Pods, type: Object) - кастомные метрики из приложения, например RPS или длина внутренней очереди, отданные через адаптер custom.metrics.k8s.io (обычно prometheus-adapter). External метрики (type: External) - что-то снаружи кластера: глубина очереди в RabbitMQ, лаг консьюмера Kafka, число сообщений в Yandex Message Queue. Пример масштабирования по RPS из Прометея:

Код: Выделить всё

  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "100"
Здесь AverageValue это абсолютное значение на под, а не процент. Цель - держать ~100 RPS на каждую реплику. Удобно и понятно бизнесу. Но настройка адаптера это отдельная история, и часто проще взять KEDA, о которой ниже.

VPA: вертикальное масштабирование и подбор requests

HPA добавляет копии, но что если под изначально неправильно нарезан - ему дали 2 ядра, а он ест 200m, или дали 256Mi, а он стабильно ловит OOMKilled? Тут нужен Vertical Pod Autoscaler. Он не из коробки, ставится отдельно (helm-чарт или манифесты из репозитория autoscaler), и состоит из трех частей: Recommender (считает идеальные requests по истории), Updater (решает, какие поды пересоздать) и Admission Controller (подменяет requests при создании пода).

Код: Выделить всё

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: worker-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  updatePolicy:
    updateMode: "Off"
Главное поле - updateMode. Режимов несколько: Off - VPA только считает и пишет рекомендации, ничего не трогает (самый безопасный, с него начинают). Initial - выставляет requests только при создании новых подов. Auto и Recreate - убивает живые поды и пересоздает с новыми requests. Смотрим рекомендации:

Код: Выделить всё

kubectl describe vpa worker-vpa
...
  Recommendation:
    Container Recommendations:
      Container Name:  worker
      Lower Bound:     cpu: 250m, memory: 262144k
      Target:          cpu: 410m, memory: 393216k
      Upper Bound:     cpu: 800m, memory: 786432k
Target - то, что VPA рекомендует поставить в requests. Даже в режиме Off это золото: запускаешь на пару недель, собираешь реальные цифры, руками правишь манифесты. Это лучший способ перестать гадать с requests.

Главная грабля VPA: его НЕЛЬЗЯ ставить на тот же Deployment с тем же ресурсом, что и HPA. Если HPA масштабирует по CPU и VPA в режиме Auto тоже крутит CPU requests, они начинают воевать - VPA меняет базу, от которой HPA считает проценты, и оба сходят с ума. Безопасная комбинация: HPA по кастомной метрике (RPS) плюс VPA по памяти. Или VPA только в режиме Off как советчик.

Cluster Autoscaler и Karpenter: масштабирование узлов

HPA нарастил реплики, но если в кластере нет места, новые поды зависают в статусе Pending. Кто добавит узлы? Cluster Autoscaler. Он следит за подами, которые не могут быть запланированы (unschedulable), и просит у облака новый узел через группу автомасштабирования (в Yandex Managed Kubernetes это группа узлов с автоскейлингом). Когда узел простаивает и его поды можно переселить, CA его гасит.

Код: Выделить всё

kubectl get pods
NAME                     READY   STATUS    AGE
api-7d9c8f5b4-9wm2x      0/1     Pending   42s

kubectl describe pod api-7d9c8f5b4-9wm2x
Events:
  Warning  FailedScheduling   0/6 nodes available: insufficient cpu
  Normal   TriggeredScaleUp   pod triggered scale-up: group nodes-prod 6->7
Видишь TriggeredScaleUp - CA увидел Pending и заказал узел. Минус классического CA: он привязан к заранее заданным группам с фиксированным типом инстанса и реагирует минутами.

Karpenter - это эволюция 2026 года. Вместо групп узлов он смотрит на суммарные потребности всех Pending-подов и подбирает оптимальный инстанс под них прямо на лету, провижинит за десятки секунд, а не минуты, и сам консолидирует нагрузку, переселяя поды на более плотные/дешевые узлы. Описывается через NodePool (apiVersion karpenter.sh/v1):

Код: Выделить всё

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
consolidationPolicy: WhenEmptyOrUnderutilized заставляет Karpenter активно ужимать кластер, упаковывая поды плотнее. Это прямая экономия. Karpenter родом из AWS, но идея node-management через CRD уже расходится по экосистеме; в РФ на части облаков пока живет классический Cluster Autoscaler, и это нормально работающий вариант.

KEDA: event-driven autoscaling и масштабирование до нуля

HPA по своей природе не умеет опуститься до нуля реплик - minReplicas минимум 1, иначе ему нечего мерить. А для воркера, который раз в час разгребает очередь, держать постоянно один под это деньги на ветер. Тут выходит KEDA (Kubernetes Event-Driven Autoscaling).

KEDA - это надстройка над HPA. Она НЕ заменяет HPA, а кормит его: KEDA создает под капотом обычный HPA и подсовывает ему external-метрики из 70+ источников - длина очереди RabbitMQ, лаг Kafka, число сообщений в SQS или Yandex Message Queue, ответ HTTP-эндпоинта, даже cron-расписание. И главное - KEDA умеет масштаб до нуля и обратно: нет событий - 0 подов, пришло сообщение - поднимает первый под.

Код: Выделить всё

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: consumer-scaler
spec:
  scaleTargetRef:
    name: consumer
  minReplicaCount: 0
  maxReplicaCount: 50
  cooldownPeriod: 120
  triggers:
  - type: kafka
    metadata:
      bootstrapServers: kafka:9092
      consumerGroup: orders
      topic: orders
      lagThreshold: "100"
Разбор. minReplicaCount: 0 - вот оно, scale to zero. lagThreshold: "100" - KEDA целится держать лаг консьюмера около 100 сообщений на под; растет очередь - растут поды. cooldownPeriod - сколько ждать после последнего события перед уходом в ноль. Связка на проде выглядит так: KEDA по лагу Kafka поднимает поды -> подам нет места -> Cluster Autoscaler или Karpenter докидывает узлы. Два уровня работают цепочкой. Запомни разделение: KEDA/HPA решают сколько подов, CA/Karpenter решают есть ли под них узлы.

Типичные грабли и антипаттерны
  • Нет requests в подах. HPA по CPU/памяти молча не работает, метрика "unknown". Cluster Autoscaler тоже считает вместимость узла по requests - без них он не понимает, сколько подов влезает. requests это фундамент всего автоскейлинга.
  • Нет metrics-server. kubectl top падает, HPA слеп. Проверяй первым делом.
  • Флаппинг. Реплики дергаются туда-сюда. Лечится behavior: окно стабилизации на scaleDown и policies на обоих направлениях.
  • HPA и VPA на одном ресурсе. Воюют за CPU requests. Разводи их по разным метрикам или держи VPA в режиме Off.
  • Уперлись в лимиты. maxReplicas слишком мал, или у группы узлов/квоты облака потолок, или нет свободных IP в подсети. HPA хочет 30 подов, а кластер дает 12, и ты этого не видишь, пока не посмотришь Events. Потолки есть везде - в HPA, в node group, в облачной квоте.
  • Медленный старт пода. Если приложение прогревается 2 минуты, мгновенный scaleUp не спасет от всплеска - реплики еще не готовы. Думай про readinessProbe и прогрев заранее.
  • Масштаб по среднему CPU при неравномерной нагрузке. Один под на 100%, три на 10%, среднее 32% - HPA спокоен, а первому поду плохо. Иногда нужны кастомные метрики, а не CPU.
Мини-лаба: подними HPA руками и устрой ему нагрузку

Повтори на тестовом кластере (подойдет k3s или minikube).
  • Убедись, что есть metrics-server:

    Код: Выделить всё

    kubectl top nodes
    . Если нет в k3s/minikube - доставь.
  • Создай нагрузочный Deployment с обязательными requests:

    Код: Выделить всё

    kubectl create deployment php-apache --image=registry.k8s.io/hpa-example
    , затем добавь в манифест resources.requests.cpu: 200m и expose как Service.
  • Навесь HPA:

    Код: Выделить всё

    kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
    .
  • Запусти генератор нагрузки в отдельном поде:

    Код: Выделить всё

    kubectl run -it load --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://php-apache; done"
    .
  • Во втором терминале наблюдай:

    Код: Выделить всё

    kubectl get hpa php-apache --watch
    . Смотри, как TARGETS растет выше 50% и REPLICAS ползет вверх.
  • Убей генератор нагрузки и засеки по часам, через сколько HPA опустит реплики - почувствуй окно стабилизации scaleDown своими руками.
  • Бонус: повесь на тот же Deployment VPA в режиме Off и через describe сравни его Target-рекомендацию с тем, что ты задал в requests.
Контрольные вопросы
  • Почему HPA по CPU не заработает, если в подах не указан resources.requests.cpu, и от чего вообще считается averageUtilization?
  • Чем отличаются scaleUp и scaleDown в секции behavior и зачем для них задают разные stabilizationWindowSeconds?
  • В чем принципиальная разница между HPA, VPA и Cluster Autoscaler, и какие два из них нельзя бездумно вешать на один ресурс?
  • Что умеет KEDA такого, чего не умеет голый HPA, и как KEDA связана с Cluster Autoscaler в продакшене?
Итог

Автомасштабирование это три независимых уровня: HPA крутит число подов по метрикам, VPA подбирает их размер и requests, Cluster Autoscaler или Karpenter добавляют узлы под выросшие поды. KEDA расширяет HPA до событийных метрик и масштаба до нуля. Все держится на корректных requests и живом metrics-server, а от флаппинга спасает грамотная асимметрия scaleUp/scaleDown. Настрой их вместе, и понедельничный пожар погасит машина, пока ты пьешь кофе.
👍4 ❤️2 🔥1 😄 🤔
✔ Лучший ответ сформирован автоматически — michi123
anton_k8s писал(а):каждый apply сбрасывает реплики на цифру из файла, и на пике сервис схлопывается прожили это в проде. argo каждые три минуты возвращал replicas: 2 поверх hpa, который раскручивал до десяти, полдня ловили волны 503 пока не посмотрели историю replicaset. и осторожнее с удалением поля: при первом client-side apply после этого деплоймент может схлопнуться до одной реплики, мы…
Перейти к ответу →
Аватара пользователя
michi123
Сообщения: 1
Зарегистрирован: 11 май 2026, 20:35

Re: Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Сообщение michi123 »

✔ Лучший ответ — сформирован автоматически
anton_k8s писал(а):каждый apply сбрасывает реплики на цифру из файла, и на пике сервис схлопывается
прожили это в проде. argo каждые три минуты возвращал replicas: 2 поверх hpa, который раскручивал до десяти, полдня ловили волны 503 пока не посмотрели историю replicaset. и осторожнее с удалением поля: при первом client-side apply после этого деплоймент может схлопнуться до одной реплики, мы переезжали через server-side apply
👍2 ❤️1 🔥 😄 🤔1
Аватара пользователя
SvelteGuru
Сообщения: 2
Зарегистрирован: 28 май 2026, 08:43

Re: Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Сообщение SvelteGuru »

масштабировал go сервис по памяти, реплики только растут и не падают, лол. перевел на rps через prometheus-adapter и живет ровно. память как сигнал это ловушка, тут все верно написано
👍2 ❤️1 🔥1 😄 🤔
Аватара пользователя
PyPro
Сообщения: 2
Зарегистрирован: 21 май 2026, 14:45

Re: Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Сообщение PyPro »

anton_k8s писал(а):в 2026 проще взять KEDA
плюсую, воркеры у нас скейлятся по лагу консьюмер-группы в кафке. по cpu это не работало вообще: консьюмер ест 5 процентов проца, а лаг растет миллионами. одно но, scale to zero для медленных джоб больно, первое сообщение после простоя ждет холодного старта секунд тридцать
👍1 ❤️ 🔥1 😄 🤔2
Аватара пользователя
moro
Сообщения: 1
Зарегистрирован: 19 май 2026, 16:30

Re: Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Сообщение moro »

а кто-нибудь в яндексовом managed кубере ускорял выдачу нод? группа с автоскейлом разворачивает ноду минуты по две, на резком пике не спасает. сделал overprovisioning как в уроке, pause под на два ядра с отрицательным priorityClass, работает, но ощущение что костыль
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints
Следующая глава →
Наблюдаемость: логи, метрики, events, обзор Prometheus и Grafana

Все главы курса «Kubernetes: оркестрация контейнеров от основ до продакшена»

Поделиться темой: ✈ Telegram VK
  • Похожие темы
Похожие запросы: как сделать бэкап docker volume и восстановить данныеkubernetes hpa автомасштабирование по метрикамdocker volume и bind mount в чем разница и где хранятся данные

Вернуться в «Kubernetes на практике»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость