Стадия жизненного цикла модуля: 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 default StorageClass.

Документация

  • Каталог провайдера 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 или новее.