Kubernetes 1.34 в Deckhouse и ROSA: graduated DRA и что с ним делать GPU-кластеру
Kubernetes 1.34 вышел с graduated DRA и улучшенным sidecar lifecycle. Deckhouse и ROSA уже дали поддержку - разбираем, как DRA меняет работу с GPU под локальный вывод LLM.
Kubernetes 1.34 вышел с graduated DRA и улучшенным управлением lifecycle sidecar-контейнеров
Kubernetes 1.34 вышел на прошлой неделе, и отечественные дистрибутивы на этот раз отреагировали неожиданно быстро. Deckhouse выкатил поддержку 1.34 в релизе 1.69 (changelog появился несколько дней назад), ROSA Kubernetes тоже объявила о поддержке. Для нас это интересно не само по себе, а в конкретном контексте: есть клиент с кластером под локальный вывод LLM, и там DRA - уже не эксперимент, а основа GPU-воркеров.
Что изменилось в 1.34 по DRA
В Kubernetes 1.32 DRA получил статус GA, но тогда были ограничения: CEL-выражения для фильтрации устройств работали не везде, часть structured parameters вела себя непредсказуемо. В 1.34 эти ограничения сняты - API считается финальным без оговорок, и вся документация по ResourceClaim, ResourceSlice и ResourceClaimTemplate теперь в основном API-reference без пометки «experimental».
Что реально изменилось в поведении:
- ResourceSlice теперь поддерживает partition-модель. Устройство можно представить как набор секций с разными атрибутами - это нужно для MIG на GPU NVIDIA A100/H100, где один GPU делится на несколько изолированных экземпляров с разными профилями памяти. Раньше приходилось регистрировать каждый MIG-экземпляр как отдельный ResourceSlice, что создавало кучу объектов в кластере.
- CEL-выражения в ResourceClaimTemplate стабилизированы. Запросы типа «GPU с памятью не менее N гигабайт» теперь работают без обходных решений через именованные селекторы.
- Lifecycle sidecar-контейнеров доведён до graduated. Sidecar в 1.34 - полноценный первоклассный объект, а не beta-фича с оговорками. Порядок старта и остановки контейнеров в поде наконец-то детерминирован без кастомных preStop-хуков.
Как это выглядит у нас
У клиента кластер под локальный вывод: несколько нод с отечественными GPU-ускорителями под vLLM-совместимый inference-движок. Мы перешли на DRA ещё в конце прошлого года при переходе на 1.32, и с тех пор модель работы с GPU стала ощутимо чище.
После обновления до 1.34 главное изменение - переписали ResourceClaimTemplate под MIG. Раньше у нас были отдельные шаблоны для разных профилей, потому что partition-модели не было. Теперь один шаблон с CEL-условием на минимальный объём памяти:
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: gpu-16gb-min
spec:
spec:
devices:
requests:
- name: gpu
deviceClassName: nvidia.com/gpu
selectors:
- cel:
expression: >
device.attributes["nvidia.com/gpu"].memory >= 16384
До 1.34 это выражение в CEL работало через раз и требовало точного соответствия атрибутам, задокументированным в NVIDIA GPU Operator. Сейчас работает без патчей.
Deckhouse 1.69: что добавилось вместе с 1.34
Deckhouse 1.69 несёт Kubernetes 1.34 плюс несколько собственных изменений, которые пересекаются с DRA-темой. Модуль node-manager теперь умеет помечать ноды с зарегистрированными ResourceDriver-ами в статусах NodeGroup - это мелочь, но полезная: видно прямо в kubectl get ng, на каких нодах есть DRA-ресурсы, а не нужно идти смотреть ResourceSlice.
Также в 1.69 обновился шаблон NodeGroup для GPU-нод: явная настройка kubelet.systemReservedMemory стала дефолтно выше для нод с большим количеством ускорителей. На практике без этого параметра на нодах с 8+ GPU kubelet периодически убивал системные поды из-за memory pressure, даже если GPU-память и host-память технически не пересекались. Приятно, что это вошло в дефолт, а не висит в FAQ.
ROSA: поддержка есть, нюанс тоже
ROSA Kubernetes 1.34 объявила поддержку через свой update-канал. Для нас это пока теоретически, потому что кластеры на ROSA у клиентов не стоят в очереди на обновление до 1.34 прямо сейчас. Но смотрели changelog: ROSA добавила собственный DRA-профиль для своего стека виртуализации - это важно, если на ROSA Virtualization запускаются виртуалки с GPU passthrough и нужен единый механизм управления устройствами.
Один нюанс, который выяснился из общения с коллегами, работающими с ROSA: feature gate DRAResourceClaimDeviceStatus по умолчанию включён в 1.34, но в ROSA-дистрибутиве его состояние зависит от конфигурации платформы. Если включили DRA до обновления через кастомный feature gate, лучше проверить, не задублировалось ли управление.
Sidecar lifecycle: зачем нам это на GPU-нодах
Казалось бы, при чём тут sidecar к GPU. Но в нашем кластере на каждой inference-ноде работает DCGM Exporter как sidecar в поде с inference-движком - собирает метрики GPU и отдаёт их в Prometheus. До 1.34 была систематическая история: при плановом рестарте inference-пода exporter иногда успевал остановиться раньше, чем inference-движок заканчивал текущий запрос. В результате последние секунды работы пода не попадали в метрики, и в Grafana получались дыры на перезапусках.
В 1.34 lifecycle sidecar гарантирует: sidecar-контейнер с restartPolicy: Always остаётся живым до тех пор, пока не завершатся все основные контейнеры пода. После этого sidecar завершается сам в порядке, обратном старту. Перезапуск inference-пода - exporter дописывает метрики - потом sidecar выходит. Проверили на тестовом поде: дыры в метриках исчезли.
Где сейчас
Кластер клиента обновлён до Deckhouse 1.69 с Kubernetes 1.34 на прошлой неделе. DRA-конфигурация переписана с учётом partition-модели и стабилизированного CEL - количество объектов ResourceSlice в кластере сократилось, шаблоны стали читаемее. Sidecar для DCGM Exporter переведён на новый lifecycle.
На ROSA будем смотреть по мере появления задач. DRA как механизм управления GPU теперь в достаточно зрелом состоянии, чтобы проектировать новые GPU-кластеры сразу под него, а не под device plugin с последующей миграцией.