
Если вы запускаете GPU-нагрузки (графические ускорители) на Kubernetes — vLLM, Triton, обучающие задачи или более новые стеки агентного инференса, — вы наверняка сталкивались со знакомой проблемой: стандартный автоскейлинг по-прежнему мыслит в категориях CPU и памяти, а GPU, который реально делает работу, остается невидимым. Из-за этого простаивает дорогая емкость ускорителей, растет задержка инференса и расходуется лишняя энергия — ровно там, где компании пытаются ответственно масштабировать LLM и Agentic Ops (подходы к эксплуатации Agentic-систем).
VK Cloud перевела статью автора, который хотел бы, чтобы KEDA масштабировался по сигналам, которые важны для GPU-нагрузок: утилизации, памяти, температуре и энергопотреблению. На практике это не только вопрос стоимости. Это еще и вопрос GreenOps (экологичный подход к эксплуатации с минимизацией углеродного следа): впустую потраченные GPU-циклы напрямую превращаются в потраченную энергию и более высокие выбросы категории Scope 3 (косвенные выбросы в цепочке создания стоимости).
Оказалось, что это сложнее, чем кажется. Дальше повествование идет от его лица
Проблема
KEDA собирается с CGO_ENABLED=0. NVIDIA Management Library (NVML) — стандартный способ читать метрики GPU — требует CGO (механизм Go для вызова кода на C). Поэтому GPU-скейлер нельзя просто добавить в ядро KEDA так же, как добавляют скейлер для Prometheus или Kafka.
А еще оператор KEDA работает как единый deployment. Вызовы NVML локальны: они читают метрики с GPU на той же ноде. Запросить GPU 0 на ноды-A из пода на ноду-B не получится.
Так что нативный скейлер для KEDA отпадает. Мне нужно что-то, что запускается на каждой GPU-ноде и отдает метрики по сети.
Архитектура
Чтобы решить эту задачу, можно собрать кастомный DaemonSet (мою референсную реализацию смотрите здесь: keda-gpu-scaler), который работает на GPU-ноде. В этой архитектуре каждый под:
Вызывает NVML через go-nvml, чтобы прочитать локальные метрики GPU.
Отдает их по gRPC через интерфейс ExternalScaler от KEDA.
Оператор KEDA подключается к скейлеру и управляет решениями HPA.

Это тот же паттерн, который Kubernetes использует для device plugins и metrics server: агент на каждой ноде собирает локальные данные оборудования.
По каким метрикам можно масштабировать
Скейлер отдает по каждому GPU такие метрики:
gpu_utilization — процент утилизации SM (Streaming Multiprocessor, вычислительное ядро GPU);
memory_utilization — утилизация контроллера памяти;
memory_used_percent — использование VRAM (видеопамять GPU) в процентах;
temperature — температура кристалла GPU в градусах Цельсия;
power_draw — текущее энергопотребление в ваттах.
Для multi-GPU ноды вы выбираете агрегацию: max, min, avg или sum — либо нацеливаетесь на конкретный индекс GPU.
Готовые профили
Чаще всего запускают один из нескольких типов GPU-нагрузок, поэтому я добавил профили с разумными значениями по умолчанию:
triggers: - type: external metadata: scalerAddress: "keda-gpu-scaler.gpu-scaler.svc.cluster.local:6000" profile: "vllm-inference"
Профиль | Метрика | Цель | Активация | Сценарий |
vllm-inference | memory_used_percent | 80% | 5% | Обслуживание LLM, scale-to-zero |
triton-inference | gpu_utilization | 75% | 10% | Обслуживание моделей Triton |
training | gpu_utilization | 90% | 0% | Обучающие задачи, без scale-to-zero |
batch | memory_used_percent | 70% | 1% | Пакетный инференс, агрессивное уменьшение масштаба |
Любое значение можно переопределить или вообще пропустить профили и задать metricType, targetValue, activationThreshold напрямую.
Быстрый старт
Установка через Helm
helm install gpu-scaler deploy/helm/keda-gpu-scaler \ --namespace gpu-scaler --create-namespace
Chart разворачивает DaemonSet, который нацеливается на ноде с nvidia.com/gpu.present=true и толерирует taint nvidia.com/gpu. По умолчанию он использует NVIDIA container runtime — если в вашем кластере его нет, установите nvmlHostMounts.enabled=true, чтобы примонтировать файлы устройств напрямую.
Создание ScaledObject
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: vllm-gpu-scaler spec: scaleTargetRef: name: vllm-deployment minReplicaCount: 0 maxReplicaCount: 8 triggers: - type: external metadata: scalerAddress: "keda-gpu-scaler.gpu-scaler.svc.cluster.local:6000" profile: "vllm-inference"
Вот и всё. Теперь KEDA будет масштабировать ваш vLLM deployment по использованию памяти GPU, включая scale-to-zero (уменьшение до нуля реплик) при простое.
Тестирование без GPU
У скейлера есть режим мок-коллектора для тестирования. Набор e2e-тестов поднимает реальный gRPC-сервер с фейковыми данными GPU и прогоняет весь поток IsActive → GetMetricSpec → GetMetrics. 11 тестов покрывают профили, пути ошибок, стриминг, режимы агрегации. Все запускаются в CI без какого-либо GPU-оборудования.
go test -v -tags=e2e -race ./tests/e2e/
Что дальше
Создание кастомных external скейлеров — мощный способ расширить экосистему CNCF. Это показывает, как graduated-проект вроде KEDA остается гибким: инженеры собирают кастомные DaemonSet под более новые паттерны AI-инфраструктуры и не вгоняют каждую нагрузку в одну и ту же абстракцию.
Сниппеты кода выше и репозиторий — это open-source референсная реализация архитектуры. Если вы запускаете GPU-нагрузки на Kubernetes и хотите автоскейлинг, который нативно понимает метрики GPU, начните с интерфейса ExternalScaler от KEDA — это отличная отправная точка.
GitHub: keda-gpu-scaler