
Итак, вы обучили модель и она показывает ожидаемые результаты. Теперь осталось выкатить её на контур, однако для этого необходим ряд компонентов: нужна маршрутизация трафика, непосредственно инференс. Желателен autoscaling модели, передача чувствительных данных, например креды до хранилища моделей. Ну и мониторинг не помешал бы.
Каждый компонент – это отдельный Helm-чарт, отдельные CRD и отдельная документация. В итоге, вместо быстрого тестирования модели и гипотез, приходится заниматься YAML-инжинирингом и громко ругаться благим матом.
Всем привет, на связи Пётр, инженер компании Nixys. В этой статье я покажу, как собрать полноценный inference-контур из пяти Kubernetes-операторов в одном values.yaml размером в 120 строк, используя nxs-universal-chart.
Общая архитектура
Наш контур будет состоять из пяти слоёв:
|
Слой |
Технология |
Компоненты |
Функция |
NUC subchart |
|
Serving |
InferenceService |
Развёртывает модель, обеспечивает V2 Inference Protocol |
||
|
Networking |
Gateway VirtualService |
Маршрутизирует внешний трафик к предиктору, mTLS |
||
|
Runtime |
Service |
Serverless runtime, scale-to-zero, revision management |
||
|
Secrets |
VaultConnection |
Доставляет S3-креды для загрузки модели из Vault |
||
|
Monitoring |
ServiceMonitor Rules |
Метрики инференса, алерт на latency |
Обзор технологий: пять слоёв inference-контура
Прежде чем переходить к конфигурации, давайте кратко разберём каждую технологию и зачем она нужна.
Istio – service mesh для управления трафиком
Istio – open-source service mesh, который прозрачно интегрируется с Kubernetes через sidecar-прокси (Envoy). Каждый pod в mesh получает sidecar-контейнер, через который проходит весь входящий и исходящий трафик. Это позволяет реализовать mTLS-шифрование между сервисами, гранулярную маршрутизацию (canary, A/B, blue-green) и observability — без изменения кода приложения. Однако, в нашем примере мы не будем затрагивать функции service mesh, оставив это для следующих статей и будем использовать только Istio Gateway.
В нашем inference-контуре Istio отвечает за три задачи. Во-первых, Gateway определяет точку входа для внешнего трафика и терминирует TLS. Во-вторых, VirtualService и DestinationRule описывают правила маршрутизации к предиктору, что даёт возможность реализовать canary-деплой новых версий модели (например, 90% трафика на v1, 10% на v2). В-третьих, AuthorizationPolicy ограничивает доступ к API инференса: только эндпоинты /v1/models/* открыты для внешних клиентов, а метрики и admin-панели остаются закрытыми.
Альтернативой для более лёгких сценариев может быть Gateway API (поддерживается NUC через субчарт nuc-native-gateway). Однако для inference-контуров Istio остаётся стандартом де-факто, поскольку KServe исторически построен на его базе.
KServe – платформа ML-инференса
KServe – платформа для развёртывания ML-моделей на Kubernetes. Ключевой абстракцией является InferenceService: с ее помощью мы можем указать формат модели и путь к артефакту, а KServe автоматически развернут serving-runtime, настроит сеть, реализует autoscaling и обеспечит поддержку V2 Inference Protocol.
KServe поддерживает два основных сценария. Для predictive inference (sklearn, XGBoost, PyTorch, TensorFlow) используется InferenceService, как в нашем примере. Для generative inference (LLM) в KServe v0.16 появился LLMInferenceService с поддержкой vLLM и llm-d для оптимизированного обслуживания больших языковых моделей с KV-cache offloading, prefix caching и распределённым scheduling.
Также стоит упомянуть о двух режимах развертывания: Standart, в котором мы оперируем стандартными ресурсами Kubernetes, такими как Deployment и serverless режим Knative, который использует Knative для обеспечения автоматического масштабирования на основе объема запросов. По сравнению с Knative режимом, который зависит от Knative для автомасштабирования, в Standard режим KEDA может быть установлен опционально, чтобы обеспечить автоматизацию на основе любых пользовательских метрик.
Сама документация рекомендует использовать стандартный режим для генеративного инференса, так как он предоставляет полный контроль за распределением ресурсов для моделей и более предсказуемое масштабирование для ресурсоемких рабочих нагрузок. Однако, мы будем использовать в этой статье Knative режим из-за его функции scale-to-zero.
Knative Serving – serverless на Kubernetes
Knative Serving – платформа для запуска serverless-workloads в Kubernetes. Главная суперсила – это scale-to-zero: когда запросов к модели нет, все поды удаляются полностью. Когда приходит новый запрос, компонент Activator буферизирует его, сигнализирует об этом autoscaler-у, тот поднимает pod. Весь процесс – от нуля до обработки запроса – занимает от нескольких секунд (CPU-модели) до минуты (GPU с загрузкой весов).
Для inference-контура это критическая экономия: GPU-ноды стоят дорого, и держать их 24/7 для модели с 10 запросами в час – расточительство. Knative масштабирует поды на основе concurrency (количество одновременных запросов) или RPS, что лучше подходит для inference-нагрузок, чем стандартный HPA на основе CPU/memory.
KServe использует Knative как движок автоскейлинга «под капотом» – при создании InferenceService автоматически создаётся Knative Service. Через nuc-knative мы дополнительно можем создать собственный Knative Service для кастомного runtime (pre/post-processing, ensemble-логика), работающего рядом с основным предиктором.
VaultSecretOperator – управление секретами
Vault – индустриальный стандарт управления секретами, шифрованием и identity-based доступом. Мы используем его практически на всех проектах и пока что не видим альтернатив. В связке с ним мы используем Vault Secrets Operator (VSO) – официальный Kubernetes-оператор от Hashicorp, который синхронизирует секреты из Vault в Kubernetes Secrets автоматически.
В нашем inference-контуре Vault решает конкретную задачу: KServe storage initializer нуждается в credentials для загрузки артефакта модели из S3 (или Harbor, если мы используем OCI). Хранить эти credentials в Git (даже зашифрованные через SOPS) – идея так себе.
Поэтому, логика работы будет следующей: все креды хранятся в Vault, а VSO создаёт и обновляет Kubernetes Secret при каждой ротации, безопасно забирая их по строгим политикам, которые предоставляют конкретному VaultAuth доступ до конкретного секрета в Vault. Для аутентификации мы будем использовать Kubernetes auth method. Это наиболее удобный и безопасный вариант: нет долгоживущих токенов, нет секретов в CI/CD переменных.
Prometheus – мониторинг и алертинг
Prometheus – стандарт мониторинга в Kubernetes. Prometheus Operator упрощает конфигурацию через CRD: вместо правки prometheus.yml вы создаёте ServiceMonitor, PodMonitor и PrometheusRule как Kubernetes-ресурсы.
Для inference-контура мониторинг – обязательный слой. ML-модель может деградировать незаметно и без мониторинга вы узнаете об этом от пользователей. В нашем контуре Prometheus собирает метрики на двух уровнях: через ServiceMonitor (стабильные эндпоинты) и PodMonitor (прямой скрейпинг подов – критично для Knative, где поды создаются и удаляются динамически). PrometheusRule определяет алерты на P99 latency инференса.
Визуально поток трафика будет выглядеть следующим образом:

-
Клиентский запрос проходит попадает на Istio Gateway и маршрутизируется через VirtualService
-
Затем попадает на KServe InferenceService, а от туда на Knative Pod
-
VaultSecretOperator доставляет S3-credentials из Vault через автоматическое создание нативного Kubernetes Secret
-
Prometheus собирает метрики со всех слоёв через ServiceMonitor
Разобравшись с общей архитектурой, можно переходить к реализации.
Предварительные требования
Предполагается, что в вашем кластере уже установлены следующие операторы и их CRD:
-
Istio
-
KServe controller (v0.14+)
-
Knative Serving (v1.12+)
-
Vault Secrets Operator (v0.5+)
-
kube-prometheus-stack
Также нам будет необходим установленный в Kubernetes Vault. Действия по установке операторов мы не будем расписывать здесь – установка всех компонентов выше отлично расписана в документациях проектов.
Затем нам будет необходимо установить сам nxs-universal-chart через стандартный helm install:
helm install ai-mesh oci://registry.nixys.ru/nuc/nxs-universal-chart
-f values.yaml
--version 3.0.17
А теперь – к самому интересному: разберём каждую секцию, который описывает весь inference-контур.
Полный values.yaml с разбором
Общие настройки:
nameOverride: ai-mesh
nameOverride задаёт базовое имя для всех генерируемых ресурсов. Вместо длинного release-name-nxs-universal-chart-... получим ai-mesh-....
Слой 1: Istio – маршрутизация и авторизация
nuc-istio:
enabled: true
gateways:
inference:
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- ai-mesh.example.local
virtualservices:
inference:
spec:
hosts:
- ai-mesh.example.local
gateways:
- inference
http:
- route:
- destination:
host: predictor.default.svc.cluster.local
port:
number: 80
destinationrules:
predictor:
spec:
host: predictor.default.svc.cluster.local
authorizationpolicies:
inference:
spec:
selector:
matchLabels:
app: predictor
rules:
- to:
- operation:
paths:
- /v1/models/*
Здесь создаётся четыре Istio-ресурса:
-
Gateway – точка входа. Привязывается к существующему
istio-ingressgatewayи слушает HTTP на порту 80 для хостаai-mesh.example.local. В production сюда добавляется TLS-терминация через cert-manager (субчартnuc-certificates). -
VirtualService – задает правила маршрутизации. Весь трафик, приходящий на
ai-mesh.example.localчерез Gatewayinference, направляется к сервису предиктора. Если бы у нас были canary-версии модели, здесь можно было бы добавитьweight-based routing. -
DestinationRule – политики соединений. В минимальной конфигурации он просто объявляет destination. В production сюда добавляется
trafficPolicy.tls.mode: ISTIO_MUTUALдля включения mTLS. -
AuthorizationPolicy – контроль доступа. Разрешает обращения только к эндпоинтам
/v1/models/*, что соответствует V2 Inference Protocol. Всё остальное (health checks, метрики, admin endpoints) блокируется для внешних клиентов.
Слой 2: KServe — serverless inference
nuc-kserve:
enabled: true
inferenceServices:
predictor:
spec:
predictor:
model:
modelFormat:
name: sklearn
storageUri: s3://models/predictor
KServe InferenceService — абстракция, которая объединяет модель, runtime, autoscaling и networking в одном ресурсе.
modelFormat.name: sklearn говорит KServe использовать встроенный sklearn serving runtime (на базе MLServer). KServe поддерживает sklearn, PyTorch, TensorFlow, XGBoost, Hugging Face и другие фреймворки из коробки.
storageUri: s3://models/predictor — путь к артефакту модели в S3-совместимом хранилище. KServe автоматически инициализирует sidecar-контейнер (storage initializer), который скачивает модель перед запуском serving-контейнера. Для доступа к S3 нужны credentials — их мы получаем из Vault (см. слой 4).
При деплое KServe создаёт под капотом:
-
Knative Service для serverless-поведения
-
Revision для версионирования
-
Route для traffic splitting
-
Service и VirtualService для доступа
Слой 3: Knative — serverless runtime
nuc-knative:
enabled: true
services:
runtime:
spec:
template:
spec:
containers:
- image: ghcr.io/nixys/inference-runtime:latest
Knative Service объявляет serverless workload с автоматическим scale-to-zero. Когда запросов нет, поды полностью удаляются (экономия GPU-ресурсов). Когда приходит первый запрос, Knative activator буферизирует его и поднимает под.
В этом примере runtime – дополнительный сервис для кастомного inference-runtime-а. Если ваша модель обслуживается стандартным KServe-рантаймом (sklearn, pytorch, tensorflow), этот блок можно опустить. Он нужен для:
-
кастомных pre/post-processing pipeline-ов
-
ensemble-моделей, где несколько моделей работают в цепочке
-
sidecar-сервисов (feature enrichment, logging, tracing)
Слой 4: Vault — безопасная доставка секретов
nuc-vault-secret-operator:
enabled: true
vaultConnections:
default:
spec:
address: https://vault.example.local:8200
vaultAuths:
app:
vaultConnectionRef: default
method: kubernetes
mount: kubernetes
role: ai-mesh
serviceAccount: default
vaultStaticSecrets:
model-credentials:
spec:
vaultAuthRef: app
mount: kvv2
type: kv-v2
path: ai/predictor
destination:
name: predictor-secret
create: true
Этот блок создаёт три CRD-ресурса Vault Secrets Operator:
-
VaultConnection – адрес Vault-сервера. Оператор будет обращаться к
https://vault.example.local:8200. -
VaultAuth – настройки аутентификации. Используется Kubernetes auth method: оператор обменивает ServiceAccount token пода на Vault token с ролью
ai-mesh. Это безопаснее, чем хранить Vault token в Secret-е: ServiceAccount token ротируется автоматически, а Vault token выдаётся с коротким TTL. -
VaultStaticSecret – непосредственно сами данные. Оператор читает секрет по пути
ai/predictorв KV движке Vault и создаёт Kubernetes Secretpredictor-secret. Этот секрет содержит AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY для доступа KServe storage initializer к S3.
Ключевое: create: true в destination говорит оператору создать Secret, если его нет. Оператор также следит за изменениями в Vault и обновляет Secret автоматически — rotate credentials без пересоздания подов.
Слой 5: Prometheus — мониторинг и алертинг
nuc-kube-prometheus-stack:
enabled: true
serviceMonitors:
predictor:
enabled: true
name: predictor
spec:
selector:
matchLabels:
app: predictor
endpoints:
- port: http
podMonitors:
predictor:
enabled: true
name: predictor
spec:
selector:
matchLabels:
app: predictor
podMetricsEndpoints:
- port: http
prometheusRules:
predictor:
enabled: true
name: predictor
spec:
groups:
- name: inference
rules:
- alert: InferenceHighLatency
expr: vector(1)
for: 5m
Мы развертываем три ресурса Prometheus Operator:
-
ServiceMonitor – скрейпинг метрик через Service. Prometheus будет собирать метрики со всех подов, label которых содержит
app: predictor, через портhttp. -
PodMonitor – прямой скрейпинг подов без использования Service. Полезно, когда поды создаются динамически (в нащем случае – это поды от Knative Revisions) и не всегда имеют стабильный Service.
-
PrometheusRule – алерт на latency. В примере используется заглушка
vector(1), которую в production нужно заменить на реальное выражение. Например:
# Production-ready алерт
- alert: InferenceHighLatency
expr: |
histogram_quantile(0.99,
sum(rate(revision_request_latencies_bucket{
service_name="predictor"
}[5m])) by (le)
) > 2.0
for: 5m
labels:
severity: warning
annotations:
summary: "P99 inference latency above 2s for 5 minutes"
Заключение
Пример ai-inference-mesh – это только отправная точка для примера и старта. Для production-использования рекомендуется добавить TLS сертифкацию через cert-manager, полноценный мониторинг моделей и правила безопасности.
Inference-контур в Kubernetes – это не один ресурс. Это конструкция из 5-7 операторов, каждый со своими CRD, и десяток ресурсов, которые должны корректно ссылаться друг на друга. В этой статье мы попыталсиь упростить это, использовав nxs-universal-chart как общую абстрацию: все CRD-ресурсы описываются в одном values.yaml, чарт обеспечивает консистентность имен и лейблов, а модульная архитектура позволяет включать только нужные subchart.
Полный пример values.yaml из этой статьи доступен в репозитории проекта. Как и ранее, будем рады услышать ваши мысли и увидеть предложения по улучшению на GitHub, а также в нашем сообществе в Telegram. Увидимся!
Автор: RukInDaHouse


