ADG Оставить заявку
Блог DevOps 4 мин чтения

Kubernetes 1.33 на Deckhouse: что из нового реально работает в производственных конфигурациях

Обновили кластер на Deckhouse до Kubernetes 1.33: разбираем Sidecar Containers в stable, улучшения планировщика и что из этого применимо в КИИ-окружениях.

Контекст момента

Kubernetes 1.33 вышел GA в апреле 2025: Sidecar Containers перешли в stable, планировщик получил улучшения QueueHint и bin-packing

Kubernetes 1.33 вышел в апреле, и мы уже прошли обновление на одном из кластеров под Deckhouse. Кластер production-grade, в нём живут сервисы нескольких заказчиков из реального сектора, есть и КИИ-сегменты. Поэтому «потрогать новое» - это не просто любопытство, а рабочая необходимость: нужно понять, что из 1.33 реально меняет поведение кластера, а что в changelog для галочки.

Разберём три вещи, которые нас интересовали больше всего: Sidecar Containers в stable, изменения в планировщике и то, как всё это прошло через Deckhouse в условиях ограниченного доступа к внешним registry.

Sidecar Containers: наконец-то stable

Самая заметная история этого релиза - перевод Sidecar Containers (KEP-753) в stable. Суть простая: теперь init-контейнер можно пометить как restartPolicy: Always, и он превращается в настоящий sidecar - запускается раньше основных контейнеров, живёт всё время жизни пода и завершается после них. Не параллельно, а именно в правильном порядке.

До этого sidecar-паттерн реализовывался через обычные init-контейнеры с хаками (бесконечный sleep, самоубийство через trap) или просто через дополнительный контейнер без гарантий порядка запуска. Оба варианта - костыли с известными проблемами: log-агент стартует после приложения, service mesh proxy ещё не готов в момент первого запроса.

На практике мы сразу применили это там, где стоит Envoy-sidecar для mTLS: теперь порядок запуска определён на уровне spec, а не через readiness-probe с retry-логикой. Манифесты стали чище, а поведение предсказуемее. Deckhouse при этом не добавляет никакой специфики - это чистый upstream-механизм, работает как есть.

Важная деталь: stable-статус означает, что feature gate SidecarContainers теперь включён по умолчанию и не выключается. Если у вас где-то стояло явное --feature-gates=SidecarContainers=false - это сломается при обновлении до 1.33. Мы проверили все кастомные конфигурации kubelet на нодах, у нас такого не было, но на гетерогенных кластерах стоит проверить.

Планировщик: QueueHint и bin-packing по умолчанию

В 1.33 планировщик получил два изменения, которые влияют на поведение в production.

QueueHint - механизм, который снижает лишние попытки планирования. Раньше при событии (например, нода освободилась) планировщик мог пытаться разместить поды, которые всё равно не подойдут по другим критериям. QueueHint позволяет плагинам планировщика давать подсказки: «это событие не меняет ситуацию для данного пода, пропусти». В результате меньше холостых итераций, быстрее реакция при бурстах.

На нашем кластере с регулярными всплесками нагрузки (пакетные задачи ночью, резкое масштабирование днём) мы увидели, что время от pending до running сократилось - особенно при одновременном старте многих подов. Измерить точно сложно без baseline-бенчмарка, но визуально по Grafana разница есть.

NodeInclusionPolicyInPodTopologySpread (GA с 1.32) - в topologySpreadConstraints можно явно управлять тем, учитываются ли tainted ноды при подсчёте spread. Для кластеров с выделенными нодами под специализированные задачи (у нас это ноды под ML-инференс и ноды под Ceph-OSD) это позволяет не учитывать их в топологии обычных сервисов без дополнительных ухищрений.

Как прошло обновление через Deckhouse

Сам переход на 1.33 через Deckhouse - это прежде всего обновление самой платформы до версии, которая поддерживает 1.33. Механика та же, что мы описывали при переходе на 1.31: сначала обновляется Deckhouse, потом в ClusterConfiguration меняем kubernetesVersion.

Специфика этого кластера - частично изолированный контур: внешний интернет доступен, но только через прокси с белым списком доменов. Registry.deckhouse.io в белый список добавлен, поэтому с доставкой образов проблем не было. Это проще, чем полностью изолированный КИИ-кластер, но всё равно требует проверки до обновления, а не в процессе.

Из неожиданного: одна нода при drain завалилась на PodDisruptionBudget - деплоймент с maxUnavailable: 0 и одной репликой, которую никто не трогал с прошлого обновления. Ситуация знакомая, поэтому мы теперь делаем проверку PDB стандартным шагом перед любым обновлением кластера:

kubectl get pdb -A -o json | jq '
  .items[] |
  select(.spec.maxUnavailable == 0 or .spec.minAvailable == .status.expectedPods) |
  "\(.metadata.namespace)/\(.metadata.name): disrupted=\(.status.disruptionsAllowed)"
'

Если disruptionsAllowed: 0 - нода при drain встанет намертво. Либо масштабируем деплоймент, либо временно снимаем PDB, либо мирно договариваемся с командой разработки.

Что пока не применяем

В 1.33 есть ещё несколько нового: DRA (Dynamic Resource Allocation) продвинулся, появился JobSuccessPolicy в GA. Но DRA нам пока незачем - GPU у этого заказчика не в Kubernetes, а на выделенных хостах. JobSuccessPolicy интересен для пакетных задач, но производственное применение требует проверки на тестовом контуре, которую мы запланировали на следующий спринт.

В целом 1.33 - это релиз, где stable Sidecar Containers действительно закрывают настоящую проблему, а не просто меняют статус фичи в документации. Остальное - полезные улучшения, но без срочности. В managed-сопровождении мы держим несколько кластеров на разных версиях одновременно, и 1.33 пока не требует форсированного перехода всех - но для новых кластеров уже берём его как baseline.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.