Как Karpenter заменяет Cluster Autoscaler и экономит бюджет в AWS
Каждый, кто настраивал стандартный Cluster Autoscaler в Kubernetes на AWS, знает эту головную боль. Приходится заранее создавать кучу Auto Scaling Groups под разные типы инстансов, архитектуры процессоров, зоны доступности и Spot-политики. Если поду внезапно понадобилась машина с GPU или чуть большим объемом памяти, а подходящей группы нет, под намертво зависает в статусе Pending.
В AWS решили подойти к масштабированию с другой стороны и написали Karpenter — контроллер, который управляет инстансами напрямую, минуя тяжеловесные абстракции облака.

В чем проблема со старым подходом
Классический Cluster Autoscaler разрабатывался давно. Его логика проста: если подам не хватает ресурсов, он увеличивает счетчик desired capacity в нужной ASG (Auto Scaling Group).
Из-за этого архитекторы кластеров годами строили монструозные конструкции. Например, отдельная группа узлов под обычные микросервисы, отдельная под spot-инстансы для фоновых воркеров, еще парочка для баз данных и ML-пайплайнов. Управлять этим через Terraform или CDK быстро надоедает. Масштабирование происходит медленно, ведь ASG добавляет лишний уровень задержки перед реальным запуском EC2-инстанса.
Karpenter работает иначе. Он полностью берет планирование на себя.
Как устроен Karpenter
Контроллер Karpenter написан на Go и ставится прямо в ваш кластер Kubernetes. Он слушает события планировщика kube-scheduler. Как только в кластере появляется под со статусом unschedulable, Karpenter читает его требования:
- Сколько запрошено CPU и оперативной памяти
- Нужны ли специфические метки, taint'ы или tolerations
- Какие заданы Node Affinity и правила раскидывания по зонам (Topology Spread Constraints)
Собрав все требования висящих подов, Karpenter пачкой отправляет запрос в EC2 Fleet API. Он сам подбирает минимально подходящий и самый дешевый инстанс (или комбинацию инстансов), который сразу вместит эту нагрузку.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64", "arm64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
limits:
cpu: 1000
memory: 1000Gi
Вместо привязки к конкретным семействам серверов вы просто задаете гибкие рамки. Karpenter сам решит, поднять под нагрузку пару машин m6g.xlarge на Graviton или взять c5.2xlarge.
Практические возможности
Контроллер решает сразу четыре повседневные задачи инфраструктурных инженеров:
-
Группировка и подбор узлов на лету. Больше не нужны десятки пресетов. Вы описываете один-два ресурса
NodePool, а Karpenter выбирает из сотен доступных типов инстансов в регионе именно тот, на который поды встанут с минимальным остатком неиспользуемых ресурсов. -
Быстрый старт. Karpenter заказывает виртуальные машины напрямую через EC2 API. Узлы переходят в рабочий статус за 30-45 секунд. Классический Cluster Autoscaler в связке с ASG часто тратит на этот процесс 3-5 минут.
-
Консолидация и экономия. Karpenter умеет непрерывно оптимизировать кластер. Если на ноде
r5.2xlargeосталось всего два небольших пода, контроллер может перенести их на соседние машины, а дорогую ноду выключить. Или заменить ее на компактныйr5.large. Включить консолидацию можно одной строчкойconsolidationPolicy: WhenEmptyOrUnderutilized. -
Интеллектуальная работа со Spot. При использовании spot-инстансов Karpenter слушает события из AWS EventBridge через SQS. Когда AWS сообщает о скором изъятии инстанса (за 2 минуты до выключения), Karpenter не ждет падения узла, а сразу заказывает замену и заранее выполняет
drain.
Технические нюансы и сложности
Звучит здорово, но идеальных инструментов не бывает. Перед установкой стоит учесть несколько моментов.
Для Karpenter нужны правильные IAM-роли. Ему требуется право создавать сетевые интерфейсы, тегировать ресурсы и запускать EC2-инстансы. Обычно для этого настраивают AWS Pod Identity или IAM Roles for Service Accounts (IRSA).
Сам контроллер должен где-то жить. Нельзя запускать под Karpenter на ноде, которой управляет сам Karpenter, иначе при масштабировании в ноль кластер не сможет подняться. Обычно для управляющих компонентов держат маленькую статическую группу из двух узлов или запускают Karpenter на AWS Fargate в рамках EKS.
Кроме того, если ваши поды не имеют корректно выставленных requests по памяти и процессору, контроллер не сможет точно рассчитать размер виртуальной машины.
Кому стоит внедрять
Если у вас небольшой кластер из трех серверов с постоянной нагрузкой, выигрыш от Karpenter будет минимальным. Стандартных Managed Node Groups тут вполне хватит.
Но проект раскрывается на полную мощность в трех сценариях:
- Запуск тяжелых CI/CD пайплайнов, когда раннеры требуют сотен ядер на 10 минут, а потом удаляются.
- Обработка очередей и пакетов данных с динамической нагрузкой.
- Кластеры со смешанной нагрузкой, где мирно уживаются архитектуры ARM и x86, spot и on-demand машины.
Если вы устали вручную тюнить размеры Auto Scaling Groups и хотите сократить счет за инфраструктуру в AWS, на Karpenter определенно имеет смысл переходить. Документация у проекта подробная, а миграция существующих узлов обычно проходит без простоя продакшена.
