Kubernetes для AI inference: что реально надо настроить
AI inference — не обычный stateless API, которому достаточно поставить три реплики и CPU limit. Здесь дорогая память GPU, тяжёлый прогрев модели, batching, очередь и цена ошибки autoscaler. Kubernetes полезен, но он не угадает эту механику за вас.
Коротко. Соберите отдельный GPU node pool, поставьте model server, закрепите точную версию модели, настройте requests/limits и scheduling, отделите readiness от скачивания весов, масштабируйтесь по длине очереди и задержке, а не только по CPU. Мерьте time to first token, tokens per second, queue time, ошибки и стоимость запроса.
Минимальная архитектура
- Gateway принимает запрос, проверяет авторизацию и лимиты.
- Router выбирает модель или профиль качества.
- Очередь сглаживает пики и даёт метрику для масштабирования.
- Model server держит веса в GPU и объединяет совместимые запросы в batch.
- Хранилище отдаёт веса и конфигурацию, но не должно скачиваться заново на каждый запрос.
- Наблюдаемость связывает пользовательский запрос, очередь и inference.
Начните с одной модели и одного понятного SLO. «Платформа для всех LLM» до первого стабильного запроса — это архитектурный косплей.
GPU-ноды и scheduling
Выделите GPU в отдельный node pool с taint, а workload допускайте через toleration и node affinity. Укажите GPU resource limit; Kubernetes не делит устройство как обычный CPU. Проверяйте совместимость драйвера, device plugin, runtime и образа model server. Обновляйте этот набор как связку, а не случайными версиями по пятницам.
resources:
requests:
cpu: "4"
memory: "24Gi"
limits:
nvidia.com/gpu: 1
tolerations:
- key: "workload"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"Память GPU — первый физический предел. Если модель не помещается с KV cache и рабочим batch, никакой HPA это не исправит. Сначала измеряйте реальное потребление на выбранной длине контекста.
DRA и выдача GPU без зоопарка аннотаций
Dynamic Resource Allocation позволяет описывать устройство и запрос к нему отдельными объектами вместо бесконечных vendor-specific аннотаций. Для AI-нагрузки это путь к более явному выбору класса GPU, памяти, topology и совместного использования. Но зрелость DRA-драйвера зависит от версии Kubernetes и поставщика устройства: сначала проверьте поддержку на своём кластере, потом меняйте production scheduling.
Сделайте инвентаризацию: какие устройства реально видит node, какой driver публикует ресурсы, какие ResourceClass/DeviceClass доступны и почему pod получил именно этот GPU. Обычный nvidia.com/gpu: 1 пока остаётся нормальным базовым вариантом. DRA нужен не ради нового YAML, а когда старой модели уже не хватает для разных ускорителей и требований.
Вес модели — часть релиза
Не ссылайтесь на плавающий latest. Зафиксируйте digest образа, идентификатор и ревизию модели, tokenizer, параметры запуска и формат квантования. Иначе два одинаковых deployment могут отвечать по-разному, а откат перестаёт быть воспроизводимым.
Вес можно запечь в image, скачать init-контейнером или положить на подготовленный volume. Первый способ даёт огромные образы, второй увеличивает cold start, третий требует жизненного цикла кэша. Выберите один и измерьте время от создания pod до готовности.
Probes без самообмана
Liveness должна отвечать, жив ли процесс, а readiness — может ли он принять новый inference. Не отдавайте ready до загрузки весов и пробного запроса. Startup probe защищает медленный прогрев от убийства liveness-проверкой. При завершении pod сначала снимите его с readiness, дайте закончить активные запросы и лишь затем убивайте процесс.
Autoscaling по полезному сигналу
CPU почти ничего не говорит о загруженности GPU inference. Полезнее pending requests, queue time, batch utilization, GPU memory и наблюдаемая задержка. Учитывайте, что новая реплика может греться минуты. Если HPA начнёт реагировать только после нарушения SLO, пользователи уже стоят в очереди.
Задайте минимальное число тёплых реплик для критичной модели, длиннее окно scale-down и явный предел очереди. При перегрузе лучше вернуть контролируемый 429 или переключить профиль, чем довести все запросы до таймаута.
Что измерять
- входную задержку и queue time;
- time to first token и полное время ответа;
- input/output tokens и tokens per second;
- размер batch, GPU utilization и память;
- cold starts, OOM и перезапуски;
- ошибки по версии модели;
- стоимость на запрос и на миллион токенов.
Обычная средняя задержка скрывает хвост. Смотрите p95 и p99 отдельно для коротких и длинных запросов. Трассировку самого AI-потока разберём в гайде по OpenTelemetry для AI-агентов.
FinOps: считать не GPU-часы, а полезный результат
Загруженный GPU ещё не означает экономичный сервис. Свяжите стоимость node pool с моделью, namespace, версией релиза и числом успешных запросов. Считайте рубли или условные единицы на тысячу запросов и на миллион выходных токенов, отдельно показывайте idle, cold start, повторные запросы и ошибки.
Проверьте четыре рычага: batching, квантизация, длина контекста и минимальное число тёплых реплик. Дешёвая конфигурация, которая нарушает SLO и заставляет пользователя повторять запрос, может оказаться дороже. Для каждой модели зафиксируйте границу качества и стоимости, а не включайте scale-to-zero по религиозным причинам.
Безопасность и данные
Не пишите полные промпты и ответы в общие логи по умолчанию. Там быстро появляются персональные данные, токены и внутренние документы. Разделите технические метаданные и содержимое, введите редактирование чувствительных полей, короткое хранение и доступ по ролям. Model server не должен иметь cluster-admin только потому, что он «AI».
Проект для портфолио
Поднимите маленькую открытую модель в локальном кластере или тестовом облаке. Покажите deployment, GPU/CPU-профиль, readiness после прогрева, очередь, dashboard с TTFT и нагрузочный тест. Потом искусственно создайте пик, OOM или медленную загрузку и опишите реакцию системы. Рабочий кейс — это не скрин pod Running, а измеримый запрос, отказ и восстановление.
Если Kubernetes пока выглядит набором YAML, начните с его базовых объектов, а сборку и выпуск оформите через GitOps.
Частые вопросы
Нужен ли Kubernetes для одной модели?
Не обязательно. Один сервер или managed endpoint часто проще. Kubernetes оправдан, когда уже нужны единые политики, несколько workloads, масштабирование и эксплуатационная команда.
Можно масштабировать по GPU utilization?
Можно использовать как один из сигналов, но очередь и задержка ближе к пользовательской проблеме.
Что важнее для портфолио?
Объяснить cold start, предел памяти, метрику масштабирования и показать измеряемое восстановление после сбоя.
Не начинайте с десяти моделей
Одна модель, один SLO, один контролируемый сбой — уже нормальный инженерный проект.
Повторить Kubernetes