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

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

Это руководство для пользователя namespace: вы заказываете инференс и читаете результат. Здесь описано сегодняшнее поведение модуля, одним проходом. Какая способность появилась в какой фазе — отдельный предмет, о нём Пошаговый сценарий.

Чего вы здесь не делаете: не выбираете ускоритель, не задаёте размер тома модели, не называете среду исполнения и не называете договор API инференса. Всё это назначает платформа. Вы называете класс и модель.

Быстрое начало

  1. Спросите у администратора кластера, каким InferenceServiceClass разрешено пользоваться вашему namespace. Класс живёт на уровне кластера, и прочитать его вам нельзя — права на чтение классов пользователю namespace не даны. Модуль поставляет встроенный класс default-llm.
  2. Создайте в своём namespace InferenceService из ссылки на класс и блока модели.
  3. Дождитесь status.phase: Ready.
  4. Прочитайте status.endpoint.url, а если класс требует токен — ещё и status.authSecretName.
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 заказа одно обязательное поле, model, и одно необязательное, inferenceServiceClassName, — и нет поля ни для чего из того, что решает платформа. Это сделано намеренно, а не забыто:

  • договор API инференса выбирается из modelPolicy.allowedEndpointTypes класса в пересечении с тем, что известно о модели. Выбранное значение видно в status.model.endpointType: Chat, Embeddings или Rerank. Это ваше единственное окно в этот выбор — читать класс вам нельзя. Заказу, которому нужен другой договор, нужен другой класс;
  • среда исполнения и все параметры запуска приходят из записи рецепта плана запуска, собранной под то железо, которое выбрал план. Другое значение — это другой рецепт или другой класс, то есть решение администратора;
  • ускоритель, его доля и оценки процессора, памяти и тома модели назначает платформа и возвращает их в status.resolved.

Заказ, который всё же несёт блок среды исполнения, клиент со строгой проверкой полей отвергнет, а клиент без неё молча срежет.

Заказ может обойтись без класса

Отсутствие spec.inferenceServiceClassName — самостоятельный, законченный режим, а не ошибка, которая пока не сработала:

  • договор API инференса вовсе не проверяется — ничего из modelPolicy.allowedEndpointTypes его не сужает, и status.model.endpointType у такого заказа не появляется;
  • экспозиция и допуск неймспейсов — те же значения, что несёт собственный поставляемый класс default-llm модуля на день выхода этой возможности (внешняя экспозиция, аутентификация токеном, TLS через cert-manager; допущен любой неймспейс), — зашиты в платформу, а не читаются из объекта default-llm, поэтому продолжают работать, даже если администратор впоследствии снимет этот класс с поставки;
  • любая другая политика (ускорителя, масштабирования, стратегии обновления, приоритета) уже ведёт себя без класса вовсе так же, как с классом, не задающим соответствующий блок.

Заказ, называющий класс, не меняет ни одного поведения, описанного в этом руководстве.

Откуда берётся модель

spec.model.src выбирает источник, и от него зависит вид spec.model.ref:

src ref.name ref.kind ref.namespace
HuggingFace идентификатор хранилища, например Qwen/Qwen2.5-32B-Instruct-AWQ не используется отвергается при записи
ai-models имя объекта Model или ClusterModel Model или ClusterModel допустимо только для Model

Это объединение проверяет сервер API до того, как объект будет сохранён, поэтому несоответствие отвергается при записи, а не всплывает потом условием.

Для модели с ограниченным доступом положите токен в Secret своего namespace и назовите его:

spec:
  model:
    ref:
      name: meta-llama/Llama-3.1-8B
    src: HuggingFace
    authSecretRef:
      name: hf-token
      key: token   # необязательно; ключ по умолчанию — "token"

Контроллер проверит этот Secret вместе с заказом и смонтирует его в загрузчик модели рабочей нагрузки заказа как HF_TOKEN.

Что происходит после создания заказа

  1. Заказ проверяется: класс обязан существовать, быть в состоянии Ready и объявлять непустой перечень договоров API; ссылка на модель обязана соответствовать своему источнику.
  2. Платформа планирует заказ: выбирает ускоритель, способ размещения и долю, считает оценки процессора, памяти и тома модели. Итог попадает в status.resolved и в условие Planned.
  3. Контроллер применяет объекты рабочей нагрузки заказа в вашем namespace. Каждый объект назван по заказу и несёт ownerReferences на него, поэтому удаление заказа удаляет и их.
  4. Считается точка доступа и публикуется в status.endpoint.
  5. Если класс требует токен, создаётся Secret с именем {заказ}-auth, и его имя попадает в status.authSecretName.
  6. API инференса опрашивается по HTTP. Только после успешного опроса заказ доходит до status.phase: Ready.
  7. После Ready состояние проверяется периодически. Устойчивые ошибки API переводят заказ в Failed с причиной ServiceUnhealthy; отказ до первого Ready оставляет его в Pending с причиной HealthCheckFailed.

Чтение состояния

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

У готового заказа видно:

  • status.phase: Ready;
  • status.endpoint.url — адрес HTTPS, и status.endpoint.type, повторяющий выбранный классом способ публикации: ClusterLocal или External;
  • status.endpoint.toolCallingSupported — объявляет, поддерживает ли разрешённый план вызов инструментов: true или false, как только план разрешён; поле отсутствует до этого момента. Объявленное true значит, что разрешённый план несёт параметр среды исполнения, включающий вызов инструментов, а не то, что каждый запрос обязательно получит вызов инструмента;
  • status.authSecretName — есть, если класс требует токен;
  • status.model.endpointType — договор API, который выбрала платформа;
  • status.constraints — действующие границы числа копий и класс важности, наложенные классом;
  • status.resolved — что назначила платформа: deviceClass, acceleratorProductName, acceleratorMemoryGiB, placementMode, sharingMode, sharePercent и replanCount.

Четыре состояния значат:

Состояние Смысл
Pending согласование ещё не завершилось успешно
Ready заказ обслуживает свой API инференса
Degraded API инференса работает, но рост числа копий заблокирован
Failed согласование остановилось на устойчивой ошибке

Внимательнее всего стоит читать Degraded: ваша точка доступа отвечает. Не работает рост.

Если заказ не становится готовым

Читайте условия, а не состояние: состояние говорит, что что-то не так, а условия — что именно.

kubectl get inferenceservice support-llm -n support \
  -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" "}{.reason}{"\n"}{end}'

Пять условий отвечают по порядку: ClassResolved, ModelResolved, Planned, WorkloadReady, Ready. Шестое, ScalingHealthy, говорит о росте, а не о готовности, и True у него означает благополучие.

Ответ несёт причина. Частые причины и то, чего каждая от вас требует:

  • ClassNotFound, ClassNotReady — класса, который называет заказ, нет либо он не готов. Прочтите spec.inferenceServiceClassName и сверьте с тем, что поставил администратор; этой причины следует ждать сразу после обновления, переименовавшего поставляемый класс;
  • ModelNotFound, ModelNotReady — ссылка на модель не разрешается или модель ещё не готова. Ваше;
  • EndpointTypePolicyConflict — то, что разрешает класс, и то, что предлагает модель, не пересекаются. Нужен другой класс; перечнем владеет администратор;
  • FormatNotAllowed, ParameterCountNotAllowed — модель запрещена политикой класса. Другая модель или другой класс;
  • CatalogDisabled — интеграция с каталогом выключена в настройках модуля, а ваш заказ называет модель каталога. Возьмите прямой источник или попросите изменить настройку;
  • NoCapacity, NoAcceleratorWithEnoughMemory — в кластере сейчас нет места под этот заказ. Здесь ожидание — верный ответ;
  • QuantizationMismatch, NoCompatibleRuntimeAvailable — ни один собранный рецепт не подходит этой модели на этом железе. Из заказа это не решается;
  • ResourceClaimExhausted — перебраны все классы устройств, которые заказу разрешено было пробовать, и ни один его не держит. Значит искать вместимость;
  • PlacementUndecidable — пробовать было нечего с самого начала: класс нельзя рассудить вовсе. Ожидание здесь не ответ — выражению отбора этого класса нужен взгляд администратора;
  • ScaleUpBlocked — заказ обслуживает, но вырастить его автоматика не может: вытеснение исчерпало вместимость. Это причина за состоянием Degraded;
  • LaunchPlanInForce — причина условия Planned, а не Ready, и заказ при ней готов. Она значит, что заказ работает по плану запуска, который уже держит, а пересчитать этот план не удалось; чем именно не удалось, сказано в message того же условия. Своё место занятый заказ не может получить второй раз — пока он его держит, оно не публикуется, — поэтому отказ пересчёта говорит о вместимости помимо этого места.

Все причины, какие может нести заказ, а не только частые, разобраны на странице FAQ.

Различие между двумя последними важнее, чем кажется. ResourceClaimExhausted значит: поиск был и ничего не нашёл — предмет здесь вместимость. PlacementUndecidable значит: поиск не начинался — предмет здесь класс.

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

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"

Если класс задаёт authentication: None, ни Secret, ни заголовка нет.

Правка и удаление заказа

Модель и класс заказа можно изменить правкой объекта: платформа перепланирует, а контроллер заново применит рабочую нагрузку. status.resolved.replanCount считает, сколько раз план пересчитывался.

Удаление InferenceService удаляет всё, чем он владеет: рабочую нагрузку, службу, объекты публикации и Secret с токеном доступа — все они несут ownerReferences на заказ. Secret с вашим токеном Hugging Face принадлежит вам и не затрагивается.

Куда смотреть дальше