Стадия жизненного цикла модуляExperimental

У модуля есть требования для установки

Пользуйтесь этой страницей как перечнем манифестов. О том, когда выбирать какой вид и как разбирать отказ, рассказывают Руководство пользователя и Руководство администратора; здесь только манифесты.

Манифесты, проверенные на живом стенде, лежат в каталоге examples/ хранилища.

Минимальный ModuleConfig

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: ai-inference
spec:
  enabled: true
  version: 1

ModuleConfig без каталога

Для кластера, где заказы называют прямые источники моделей, а ai-models не установлен.

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: ai-inference
spec:
  enabled: true
  version: 1
  settings:
    catalog:
      mode: None

Минимальный заказ

Ссылка на класс и модель.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceService
metadata:
  name: support-llm
  namespace: support
spec:
  inferenceServiceClassName: default-llm
  model:
    ref:
      name: Qwen/Qwen2.5-32B-Instruct-AWQ
    src: HuggingFace

Заказ без класса

spec.inferenceServiceClassName необязателен — заказ, вовсе его не называющий, получает встроенные классless-значения по умолчанию (см. раздел «Заказ может обойтись без класса» руководства пользователя), а не отказ разрешения.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceService
metadata:
  name: support-llm-no-class
  namespace: support
spec:
  model:
    ref:
      name: Qwen/Qwen2.5-32B-Instruct-AWQ
    src: HuggingFace

Заказ модели Hugging Face с ограниченным доступом

Secret лежит в том же namespace, что и заказ. Поле key необязательно: ключ по умолчанию — token.

apiVersion: v1
kind: Secret
metadata:
  name: hf-token
  namespace: support
type: Opaque
stringData:
  token: <HUGGING_FACE_TOKEN>
---
apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceService
metadata:
  name: llama-chat
  namespace: support
spec:
  inferenceServiceClassName: default-llm
  model:
    ref:
      name: meta-llama/Llama-3.1-8B
    src: HuggingFace
    authSecretRef:
      name: hf-token
      key: token

Заказ модели из каталога

kind выбирает между Model в namespace и ClusterModel уровня кластера. Поле namespace внутри ref допустимо только для Model.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceService
metadata:
  name: catalog-chat
  namespace: support
spec:
  inferenceServiceClassName: default-llm
  model:
    ref:
      kind: ClusterModel
      name: qwen2-5-8b-instruct-awq
    src: ai-models

Класс с публикацией внутри кластера

Ни входа извне, ни сертификата, ни токена.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceServiceClass
metadata:
  name: llm-internal
spec:
  admissionPolicy:
    allowedNamespaces:
      - support
  modelPolicy:
    allowedEndpointTypes:
      - Chat
  exposurePolicy:
    type: ClusterLocal
    authentication: None
  updatePolicy:
    strategy: RollingUpdate

Этот класс не называет ни scalingPolicy, ни acceleratorPolicy, поэтому его заказы получают по одной копии и по ускорителю целиком каждый. Оба значения — решения по умолчанию, они описаны в руководстве администратора.

Класс с публикацией за пределы кластера

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceServiceClass
metadata:
  name: llm-chat-external
spec:
  admissionPolicy:
    allowedNamespaces:
      - support
      - analytics
  modelPolicy:
    allowedEndpointTypes:
      - Chat
  exposurePolicy:
    type: External
    authentication: Token
    https:
      mode: CertManager
      certManager:
        clusterIssuerName: letsencrypt
  scalingPolicy:
    minReplicas: 1
    maxReplicas: 4
  acceleratorPolicy:
    allowedSharingModes:
      - Shared
      - Dedicated
    allowedPlacementTypes:
      - WholeDevice
      - Partition
    maxAcceleratorCount: 1
  updatePolicy:
    strategy: RollingUpdate

Класс, ограничивающий каждую свою политику

Заполнены все блоки, включая названный класс устройств и названный класс важности. Этот вид стоит копировать, когда классу нельзя выходить за одно поколение железа.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceServiceClass
metadata:
  name: llm-strict
spec:
  admissionPolicy:
    allowedNamespaces:
      - support
  modelPolicy:
    allowedEndpointTypes:
      - Chat
    maxParameterCount: 1B
  acceleratorPolicy:
    allowedSharingModes:
      - Shared
      - Dedicated
    allowedPlacementTypes:
      - Partition
      - WholeDevice
    allowedDeviceClasses:
      - nvidia-t4-mps-physical
    maxAcceleratorCount: 1
  exposurePolicy:
    type: External
    authentication: Token
    https:
      mode: CertManager
      certManager:
        clusterIssuerName: selfsigned
  scalingPolicy:
    allowedPriorityClassNames:
      - inference-normal
    minReplicas: 1
    maxReplicas: 4
  updatePolicy:
    strategy: RollingUpdate

Класс только для представлений

Один договор в перечне, поэтому ни один заказ этого класса не будет обслужен как беседа.

apiVersion: ai.deckhouse.io/v1alpha1
kind: InferenceServiceClass
metadata:
  name: embeddings-only
spec:
  admissionPolicy:
    allowedNamespaces:
      - analytics
  modelPolicy:
    allowedEndpointTypes:
      - Embeddings
  exposurePolicy:
    type: ClusterLocal
    authentication: None
  acceleratorPolicy:
    allowedSharingModes:
      - Shared
    allowedPlacementTypes:
      - WholeDevice
      - Partition
    maxAcceleratorCount: 1
  updatePolicy:
    strategy: RollingUpdate

Классы важности для вытеснения

Вместимость переходит между заказами по важности. Класс допускает класс важности по имени через scalingPolicy.allowedPriorityClassNames.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: inference-low
value: 100
globalDefault: false
description: Заказы, отдающие вместимость первыми.
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: inference-normal
value: 500
globalDefault: false
description: Повседневные заказы.
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: inference-high
value: 1000
globalDefault: false
description: Заказы, забирающие вместимость у остальных.

Чтение результата заказа

kubectl get inferenceservice support-llm -n support -o yaml

# только ответы
kubectl get inferenceservice support-llm -n support -o jsonpath='{.status.phase}{"\n"}'
kubectl get inferenceservice support-llm -n support -o jsonpath='{.status.endpoint.url}{"\n"}'
kubectl get inferenceservice support-llm -n support -o jsonpath='{.status.model.endpointType}{"\n"}'

# условия и их причины
kubectl get inferenceservice support-llm -n support \
  -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" "}{.reason}{"\n"}{end}'

Обращение к точке доступа

URL=$(kubectl get inferenceservice support-llm -n support -o jsonpath='{.status.endpoint.url}')
SECRET=$(kubectl get inferenceservice support-llm -n support -o jsonpath='{.status.authSecretName}')
TOKEN=$(kubectl get secret "$SECRET" -n support -o jsonpath='{.data.token}' | base64 -d)

curl -sS "$URL/v1/models" -H "Authorization: Bearer $TOKEN"

curl -sS "$URL/v1/chat/completions" \
  -H "Authorization: Bearer $TOKEN" \
  --json '{"model":"Qwen/Qwen2.5-32B-Instruct-AWQ","messages":[{"role":"user","content":"ping"}]}'