Production и облако · Production and cloud · урок 2 · 13 мин

Kubernetes для моделей: GPU-ноды, autoscaling, Helm

Kubernetes for models: GPU nodes, autoscaling, Helm

ТемыDocker и KubernetesЖелезоInference и serving

Зачем

После урока ты объяснишь, как своя модель живёт в Kubernetes: как GPU попадает в кластер, почему на GPU-узлах работают только модели, откуда берутся минуты холодного старта, почему autoscaling по CPU для модели бесполезен и зачем Helm и GitOps. Это второй слой вопроса «we want to serve our own fine-tuned model — how?», который отделяет того, кто запускал модели, от того, кто читал про Kubernetes.

Как GPU попадает в кластер

Сам по себе Kubernetes про GPU не знает. На узел ставят драйвер и device plugin (модуль, который объявляет устройство) от NVIDIA. После этого узел сообщает кластеру ресурс nvidia.com/gpu, и pod может его попросить. Правила из документации kubernetes.io (08.10.2026): GPU указывают в limits; если и в requests, значения должны совпадать. GPU выдаётся целыми устройствами, дробно его не попросить.

NVIDIA GPU Operator ставит весь набор разом: драйвер, container toolkit, device plugin, метки узлов по типу GPU и мониторинг DCGM (счётчики GPU). Метки нужны, чтобы различать карты: accelerator=l40s и accelerator=t4 — разные узлы для разных моделей.

Делить одну карту можно двумя способами. MIG (Multi-Instance GPU) режет карту на изолированные части со своей памятью, это умеют только дата-центровые карты вроде A100 и H100. Time-slicing (разделение по времени) объявляет одну карту, например, как четыре ресурса, но документация NVIDIA прямо пишет: «there is no memory or fault-isolation between replicas». Годится для dev, не для двух клиентов на одной карте.

Только модели на GPU-узлах: taint плюс affinity

GPU-узел дорогой, и на нём не должен поселиться сборщик журналов. Обратно: сервер модели не должен уехать на CPU-узел. Нужны два механизма вместе.

Документация формулирует ловушку так: «Tolerations allow scheduling but don't guarantee scheduling». Toleration только разрешает pod попасть на узел, но не тянет его туда. Без affinity сервер модели может оказаться на CPU-узле и не запуститься. Фраза для интервью: «taint repels everyone else, toleration plus affinity puts the model there».

Холодный старт: посчитай, из чего он состоит

Новая копия модели на новом узле проходит четыре этапа. Скорости ниже — допущения для примера, их надо мерить на своей платформе.

Этап Пример Время
Узел появился (autoscaler создал машину) — минуты
Скачать image 12 ГБ при 200 МБ/с 12 000 / 200 60 с
Скачать веса 70 ГБ из object storage при 500 МБ/с 70 000 / 500 140 с
Загрузить в GPU и прогреть — десятки секунд

Итого 4–6 минут до readiness. Что с этим делают: веса не в image и версионируются отдельно; cache весов рядом с узлом; заранее скачанные образы; тёплый минимум копий в рабочие часы; масштабирование по расписанию перед предсказуемым пиком (утро, день зарплаты). И startup probe с бюджетом больше худшего случая (урок a7-1).

Autoscaling: почему не CPU

HPA (Horizontal Pod Autoscaler) меняет число копий по метрике. Формула из документации: desiredReplicas = ceil(currentReplicas × currentMetricValue / desiredMetricValue). Цикл — раз в 15 с, отклонения в пределах 10 % игнорируются, уменьшение копий сглаживается окном 300 с, увеличение — без окна. Пример: 4 копии, в очереди в среднем 30 запросов на pod, цель 10 → ceil(4 × 30 / 10) = 12 копий.

Почему не CPU. Сервер модели упирается в GPU и в память под KV cache (кэш ключей и значений внимания для каждого разговора), а CPU почти не растёт с нагрузкой. Масштабировать по CPU — масштабировать по шуму. Посчитаем память. На один token нужно 2 × layers × kv_heads × head_dim × bytes. Для модели с 32 слоями, 8 KV heads, head_dim 128 в FP16: 2 × 32 × 8 × 128 × 2 = 131 072 байта ≈ 128 КиБ. Разговор на 8 000 tokens ≈ 1 ГиБ. На GPU с 80 ГБ, где 70 ГБ заняли веса, остаётся около 10 ГБ — примерно 10 таких разговоров одновременно. Поэтому сигнал для масштабирования — глубина очереди, число ожидающих запросов и занятость KV cache из метрик сервера, через custom metrics HPA или KEDA (надстройка для масштабирования по событиям).

KEDA умеет scale to zero (ноль копий без нагрузки). Для GPU-сервера в рабочие часы это плохая идея: первый клиент ждёт те самые 4–6 минут. Если pod не помещается на существующие узлы, Karpenter или Cluster Autoscaler создают новый узел. Это две петли подряд — копии, потом узлы, — отсюда минуты.

Сервер модели внутри pod

vLLM — стандартный выбор: PagedAttention (KV cache страницами, без дыр в памяти), continuous batching (на каждом шаге генерации в пакет добавляются новые запросы и убираются законченные), prefix caching, API, совместимый с OpenAI, квантизация. KServe — платформа поверх Kubernetes с ресурсом InferenceService, autoscaling вплоть до нуля и canary для моделей; vLLM работает внутри как backend. TGI от Hugging Face на 08.10.2026 в maintenance mode, авторы сами советуют vLLM, SGLang или llama.cpp.

Helm и GitOps: как это всё описать

Манифестов становится десятки, и для dev, staging и prod они отличаются парой чисел. Helm упаковывает их в chart (пакет шаблонов); values — параметры среды (-f values-prod.yaml, правый файл побеждает, --set сильнее файлов); release — установленный экземпляр с историей ревизий. helm upgrade даёт новую ревизию, helm rollback RELEASE REVISION возвращает прежнюю. Типовая схема: один chart агента и три файла values.

GitOps идёт дальше: желаемое состояние кластера лежит в Git, а контроллер Argo CD сравнивает его с живым. Расхождение помечается OutOfSync. Это даёт банку три вещи: аудит (каждое изменение production — commit с автором и review), откат (revert commit) и видимый дрейф (ручная правка kubectl edit сразу видна).

Схема

Термины · Key terms

device plugin
модуль, который объявляет GPU кластеру как ресурс nvidia.com/gpu
GPU Operator
набор NVIDIA: драйвер, device plugin, метки узлов, мониторинг
MIG / time-slicing
деление GPU с изоляцией памяти / переподписка без изоляции
taint / toleration
метка, отталкивающая pods от узла / разрешение для pod
node affinity
правило, которое притягивает pod к узлам с нужной меткой
cold start
время от решения добавить копию до её готовности
HPA
автомасштабирование числа pods по метрике
KEDA
масштабирование по событиям и очередям, включая scale to zero
KV cache
память под keys и values прошлых tokens каждого разговора
continuous batching
пакет запросов, который обновляется на каждом шаге генерации
Helm chart / values / release
пакет шаблонов / параметры среды / установленный экземпляр
GitOps
Git как источник правды о состоянии кластера

Сделай сам

10 строк Python без пакетов. Посчитай KV cache на token для Qwen3-8B: 36 слоёв, 8 KV heads, head_dim 128, BF16 (2 байта). Затем: веса 8,19 млрд параметров × 2 байта; сколько ГиБ останется под KV cache на карте 22 ГиБ, если 1,5 ГиБ уходит на служебную память, и сколько tokens контекста суммарно поместится. Выведи три числа.

Обсуди с тьютором: покажи расчёт и спроси, как изменится число одновременных разговоров на 8 000 tokens, если веса квантизовать в 4 бита, а KV cache — в FP8.

Проверь себя · ответ под вопросом

1Зачем на GPU-узлах нужны и taint, и node affinity? Разве не хватит одного?
Taint отталкивает с GPU-узла всё, у чего нет toleration, — так туда не садятся посторонние pods. Toleration только разрешает модели попасть на узел, но не притягивает её. Affinity по метке GPU гарантирует, что сервер модели не уедет на CPU-узел.
2Почему HPA по 70 % CPU не годится для сервера модели?
Узкое место модели — GPU, очередь и память под KV cache, а загрузка CPU почти не меняется с ростом запросов. HPA по CPU среагирует поздно или никогда. Масштабируют по глубине очереди, ожидающим запросам или занятости KV cache.
3Из чего складываются минуты холодного старта и что из этого можно убрать?
Создание узла, скачивание image, скачивание весов и загрузка в GPU с прогревом. Веса выносят из image и кешируют рядом с узлом, образы скачивают заранее, держат тёплый минимум копий и масштабируются по расписанию перед пиком. Создание узла убирается только тёплым запасом.

Interview questions · US / UK

1We want to serve our own fine-tuned model on Kubernetes. How do you handle GPUs, cold start and autoscaling?
Strong answer: device plugin or GPU Operator exposes nvidia.com/gpu; taint the GPU pool, toleration plus affinity on the model server; cold start is node + image + weights + warm-up, so weights out of the image, cached near the node, pre-pulled images, startup probe; scale on queue depth or KV cache usage via KEDA or HPA custom metrics; warm minimum in business hours.
2Every morning at 9:00 p95 latency jumps from 3 s to 40 s for ten minutes. The model server has an HPA on 70% CPU. What do you check?
Strong answer: diagnose before fixing: queue depth and waiting requests, HPA events, pod timeline (scheduled, image pulled, weights loaded, ready), node provisioning; CPU is the wrong signal; switch to queue-based scaling, add a warm minimum and a scheduled scale-up before 9:00 because the peak is predictable.
3Why would you use Helm and Argo CD together, and what does that give a regulated company?
Strong answer: Helm templates one chart with per-environment values and keeps release revisions; Argo CD keeps the cluster equal to Git and flags OutOfSync drift; audit is git history with review, rollback is a revert, manual edits become visible; who changed the model and when is a commit.

Ключевые фразы · Say it aloud

Материалы