Стадия жизненного цикла модуля: Experimental
У модуля есть требования для установки
Страница — источник правды по заметкам о релизах модуля ai-models. В каждом
блоке релиза перечислено только то, что важно администратору кластера или
пользователю неймспейса; журнал изменений, который уезжает вместе с релизным
образом, — короткая проекция того же содержимого.
v0.1.0
Модуль: ai-models · Версия: v0.1.0 · Дата: 2026-08-06
Ключевые изменения
- Каталог моделей можно наполнить из внешнего провайдера:
ModelCatalogSourceиндексирует каталог Hugging Face в кластер, и по проиндексированным записям работает поиск через API каталога — регистрировать каждую модель вручную больше не нужно. - Записи каталога содержат метаданные провайдера и факты для расчёта ресурсов инференса, поэтому модель можно оценить до того, как что-либо скачано в кластер.
- Модуль
ai-inferenceполучает сведения о модели через внутренний API поиска, а не чтением ресурсов каталога. - Точки входа каталога, раздачи и загрузки моделей маршрутизируются через Gateway API — наряду с существующей маршрутизацией через Ingress.
- Модуль переживает медленный или загруженный старт кластера вместо крашлупа, а его runtime режима
NodeCacheдопустим в профиле restricted Pod Security Standards. - Модуль сразу сообщает, может ли он вообще доставлять модели в этом кластере: предпосылки к хранилищу для выбранного режима доставки проверяются до появления первой модели или рабочей нагрузки, а том, который кластер не может выдать, заканчивается названной причиной, а не бесконечным ожиданием.
- Занятость хранилища моделей — факт, который сообщает модуль, а не число, которое потребитель считает сам: занятость и бюджет отдаются в разрезе областей, а каждая запись каталога несёт предварительный вердикт о том, поместится ли загрузка.
Новые возможности
ModelCatalogSourceдля провайдера Hugging Face: индексация запускается и по событиям источника, и по таймеру, большие каталоги индексируются порциями с курсором возобновления, а синхронизация с провайдером начинается только после явной аннотации на источнике.- В результатах поиска по каталогу доступны описательные метаданные провайдера и факты для расчёта ресурсов инференса, выведенные из конфигурации модели.
GET /api/internal/v1/models/lookupвозвращает сведения о модели по её ссылке для потребителей внутри кластера.- Ресурсы
HTTPRouteдля точек входа каталога и раздачи моделей, а также отдельный маршрут для загрузки, который передаёт поток без ограничения на размер тела запроса. - Проверка предпосылок к хранилищу на уровне модуля сообщает, может ли модуль доставлять модели в этом кластере, независимо от того, есть ли хотя бы один
Model,ClusterModelили рабочая нагрузка: вердикт и его причина отдаются метрикойd8_ai_models_storage_prerequisites_satisfiedс алертомD8AIModelsStoragePrerequisitesNotSatisfied, а также пишутся в лог контроллера при старте — для кластеров без мониторинга. Проверка выполняется на каждом сборе метрик, поэтому исправленный кластер снимает сигнал без перезапуска, а модуль остаётся включённым в деградированном состоянии: поиск по каталогу, источники и API чтения продолжают работать. GET /api/catalog-import/v1/storage-summaryсообщает занятость хранилища моделей, которым владеет модуль, — раздельно по копиям в неймспейсах и кластерным копиям — вместе с бюджетом хранилища, если он модулю известен. То, что модуль определить не может, в ответе отсутствует, а не выдаётся за нуль:capacityKnownиusageKnownуказывают, какая из двух половин является фактом.- Записи каталога несут предварительный вердикт о загрузке:
downloadVerdictпринимает значенияFeasible,NotFeasibleилиEstimateUnavailableи содержитrequiredBytes, если размер известен; вердикт считается тем же механизмом резервирования, который применяет реальная загрузка. Запись с неизвестным размером никогда не блокируется из-за оценки, которой у модуля нет. - Учёт хранилища сообщает собственное состояние: метрики о здоровье прохода инвентаризации и его последнем успехе, а также о наличии и подтверждённости журнала учёта, и алерты над ними — загрузка, отклонённая из-за неизвестной занятости, больше не видна только как одна строка в логе в минуту.
- Вся публичная поверхность чтения модуля выдаётся на уровне доступа
User:Model,ClusterModel,ModelCatalogSourceи представление импортов каталога, которым просматривают каталог провайдера. Раньше пользователь читал модели, но получалForbiddenна источники каталога, имя которых обязан указать вspec.source.catalog.sourceName, а просмотр каталога требовалClusterAdmin.Editor,ClusterEditorиClusterAdminостаются дельтами только на запись поверх этого, потому что уровни доступа Deckhouse накопительные.ClusterModelиModelCatalogSource— cluster-scoped, поэтому уровень, выданный сlimitNamespaces, их всё равно не прочитает: если пользователю нужен общий каталог, выдавайте уровень без ограничения по неймспейсам.
Улучшения
- API каталога генерируется из контракта OpenAPI 3, опубликованного как документ OpenAPI 3: закрытые словари стали типизированными перечислениями, метки времени — типизированными полями date-time, а ответы шлюза 502 и 503 описаны в контракте.
- Индексация каталога хранит записи провайдера в разрезе источника, поэтому несколько источников больше не перетирают записи друг друга.
- Сводка по хранилищу отдаётся из пятисекундного снимка с одним обновлением на группу запросов, поэтому просмотр каталога больше не тянет за собой живое чтение всего журнала учёта на каждый запрос.
- Чтение объяснения провизионера для непривязанного тома ограничено самим claim’ом через серверный field selector и одной страницей — вместо некэшированного перечисления целого неймспейса на каждую повторную обработку.
- Каждая задокументированная причина в условиях — это причина, которую модуль действительно выставляет: значения, которые были объявлены, но никогда не сообщались, убраны, а в документации указано, на какой поверхности живёт каждый словарь — в условиях
Modelили в отчёте о доставке для рабочей нагрузки.
Исправления
- API чтения каталога продолжает отдавать сохранённый каталог, пока источник не готов, вместо ошибки на запросах поиска.
- Доставка через общий том больше не перегружает кластер параллельными задачами подготовки:
maxConcurrentMaterializationsограничивает их число и по умолчанию равен 2. - Внутренний API моделей отдаёт сертификат, выпущенный CA платформы, на своё внутрикластерное DNS-имя, поэтому клиентам больше не нужно отключать проверку TLS.
- Исправлены теги модуля, из-за которых модуль не устанавливался на свежесобранном релизе.
- Контроллер записывает события Kubernetes о обработке моделей и перевыкладывает повреждённый артефакт вместо того, чтобы оставить модель в зависшем состоянии.
- Компоненты модуля больше не уходят в крашлуп при старте под нагрузкой: старт контролируется
startupProbeпо/healthz, миграция схемы каталога убрана с пути readiness, аGOMEMLIMITне превышает лимит памяти контейнера. - Остановленная доставка больше не уничтожает уже подготовленный том. Доставка, которая не могла продолжаться — модель по ссылке на короткое время потеряла
Ready, рабочая нагрузка заблокирована собственным контрактом, — освобождала все общие тома своего владельца, после чего сборка неиспользуемых томов забирала claim, который был уже привязан и содержал скачанную модель. Остановка доставки теперь сохраняет уже привязанные claim’ы вместе со ссылками, которые их удерживают. - Общий том, который невозможно выделить, заканчивается названной причиной вместо бесконечного
SharedPVCClaimPending: отказ провизионера передаётся дословно какSharedPVCProvisioningFailed, claim, не привязанный по истечении отведённого срока, — какSharedPVCProvisioningTimedOut, класс с отложенной привязкой называется сразу, а не после дедлайна, а том, потерявшийPersistentVolume, получает собственную причину. Ни один отчёт не залипает, поэтому исправление в кластере возвращает доставку в рабочее состояние. - Учёт хранилища никогда не считает от потерянного состояния: отсутствующий или опустошённый журнал учёта читается как «занятость неизвестна», а не «ничего не занято», новые загрузки отклоняются, пока проход инвентаризации не сверит журнал с фактически сохранёнными артефактами, а publish-коммит, который пересоздаёт журнал ради записи одного артефакта, больше не выдаёт его за подтверждённый.
- Проход инвентаризации обрабатывает все артефакты и объединяет ошибки, поэтому один артефакт, учёт которого не удаётся записать, больше не скрывает остальную инвентаризацию, продолжая при этом блокировать подтверждение для всех.
- Вердикт о хранилище сообщает каждая реплика сразу при старте, не дожидаясь лидерской аренды, — отчёт только читает и пишет в лог, а вся его ценность в том, чтобы появиться рано.
Обновления безопасности
- Закрыты находки CVE-сканирования во всех Go-модулях, включая обновление
golang.org/x/netдо 0.56.0. - CSI-runtime режима
NodeCacheдопустим в профиле restricted Pod Security Standards: контейнеры сбрасывают все capabilities, дерево/devузла больше не монтируется, а единственная привилегия, которая всё ещё нужна CSI-плагину, объявлена черезSecurityPolicyException. - Отчёт о том, почему общий том не привязан, принимает только событие, у которого UID в
involvedObjectточно совпадает с claim’ом. Создание событий — часть обычного доступа на изменение в неймспейсе рабочей нагрузки, а имя claim’а выводится детерминированно, поэтому без сверки UID пользователь неймспейса мог поместить в отчёт модуля текст на своё усмотрение. Доступ к событиям, который нужен этому отчёту, — только на чтение и выдаётся лишь для режима доставкиSharedPVC.
Несовместимые изменения
- Пользовательские ресурсы
DownloadTaskиModelDeliveryудалены вместе с полямиModelиClusterModel, которые были объявлены и никогда не заполнялись:spec.availability,spec.metadata,status.state,status.discoveredиstatus.downloadTasks. Ни один контроллер их не создавал, не читал и не записывал, поэтому в работе кластера ничего не меняется — но объект или манифест, который их упоминает, больше не относится к API модуля. Рабочие поля жизненного цикла и обогащения —status.phaseиstatus.resolved; пометка «устарело в пользу удалённых полей» с них снята. Из внутреннего контракта поиска моделей по той же причине убрано всегда пустое полеstate.
Замечания по обновлению
- Определения
downloadtasks.ai.deckhouse.ioиmodeldeliveries.ai.deckhouse.ioостанутся зарегистрированными в кластере, где была установлена предыдущая версия: платформа применяет определения, которые модуль поставляет, но не удаляет те, которые он поставлять перестал. Они по-прежнему видны вkubectl api-resourcesвместе с созданными под ними объектами, а доступа к ним у контроллера больше нет. Если оставить всё как есть, ничего не сломается; удалить можно в удобный момент командойd8 k delete crd downloadtasks.ai.deckhouse.io modeldeliveries.ai.deckhouse.io— вместе с определениями удалятся и объекты этих типов. StorageClassсvolumeBindingMode: WaitForFirstConsumerне подходит для доставкиSharedPVC: доставка ждёт привязки тома, прежде чем создать его первого потребителя, поэтому такой том не привяжется никогда. Раньше это выглядело как бесконечныйSharedPVCClaimPending, теперь сообщается сразу как неудовлетворённая предпосылка. Выберите класс с поддержкой ReadWriteMany иvolumeBindingMode: Immediate— черезaiModels.delivery.sharedPVCStorageClassName, через глобальные настройки класса хранения Deckhouse или единственным Kubernetes defaultStorageClass.
Документация
- Каталог провайдера Hugging Face описан в руководствах пользователя и администратора, включая примеры запросов и ответов API поиска по каталогу.
- В руководстве администратора предпосылки к хранилищу описаны сразу: что требует каждый режим доставки, что означает каждая причина вердикта и как читать сводку по хранилищу и вердикт о загрузке для записи каталога.
- В руководстве администратора перечислено, что читает и что пишет каждый уровень доступа, сказано, что уровни накопительные, и названо условие для двух cluster-scoped типов — им нужна кластерная привязка, в том числе для API просмотра каталога, который субъекту с ограничением по неймспейсам отвечает 403 даже на нужном уровне.
- Эксплуатационные факты, которые раньше выяснялись в переписке, теперь на страницах: у
Deploymentпри доставке появляется второйReplicaSet, а устаревший удаляет контроллер; предварительная проверка хранилища смотритvolumeBindingMode, аReadWriteManyподтверждается первым заказанным томом; один bucket обслуживает один кластер;spec.source.catalog.name— это имяClusterModelв раздающем кластере.
Зависимости
deckhouse_lib_helm: 1.72.0 → 1.72.10.- Модуль требует Deckhouse 1.75.0 или новее и Kubernetes 1.34 или новее.