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

Kubernetes 1.35 в Deckhouse: in-place pod resizing graduated и что это значит для stateful-нагрузок

Kubernetes 1.35 вышел с graduated in-place pod resizing и обновлённым scheduler framework. Тестируем вертикальный автоскейлинг без рестарта пода на stateful-нагрузках в Deckhouse.

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

Kubernetes 1.35 вышел с graduated in-place pod resizing и улучшенным scheduler framework

Kubernetes 1.35 вышел несколько дней назад, и в этом релизе наконец-то случилось то, что ждали достаточно долго: in-place pod resizing перешёл в статус graduated. Фича была в alpha с 1.27, потом долго жила в beta с разными оговорками - и вот теперь API считается финальным. Для нас это не абстрактно: есть несколько stateful-нагрузок у клиентов, где вертикальный автоскейлинг с рестартом пода - это боль, и мы давно присматривались к тому, когда можно будет перейти на in-place resize в production.

Deckhouse с поддержкой 1.35 ещё не вышел в stable-канале на момент написания, но мы подняли тестовый кластер на кандидате и потратили пару дней на замеры. Результаты неоднозначные - об этом честно.

Что graduated означает на практике

Graduated в Kubernetes - это не просто маркетинг. Это конкретные гарантии: API не будет ломаться без deprecation notice, фича включена по умолчанию без feature gate, поведение считается стабильным.

Для in-place pod resizing graduated означает несколько вещей:

  • Feature gate InPlacePodVerticalScaling включён по умолчанию. Больше не нужно явно включать его в kubelet и kube-apiserver - это меняет расчёт при обновлении кластеров, где кто-то мог случайно не добавить gate на все ноды.
  • API поля resize в resources теперь финальные. pod.spec.containers[].resources.requests можно менять через patch без пересоздания пода - и это официально поддержанный путь.
  • Статус resize виден в pod.status.containerStatuses[].resources. Отдельное поле, которое показывает актуальное состояние ресурсов контейнера в отличие от запрошенных.

Поведение при изменении limits vs requests тоже уточнили: если контейнер не принимает изменение без рестарта (это зависит от cgroup-настроек и runtime), pod переходит в статус Infeasible или Deferred, но не рестартует автоматически. Это важно - ниже расскажем, почему.

Scheduler framework: что изменилось

Второй крупный блок в 1.35 - улучшения scheduler framework. Здесь нет одного громкого изменения, скорее набор доработок:

  • PreScore плагины теперь получают полный список feasible нод, а не выборку после sampling. Для кастомных scheduler плагинов, которые делают scoring на основе балансировки - это меняет точность.
  • QueueingHint API стабилизирован. Это механизм, который позволяет плагину сказать: «вот это событие может разблокировать под из очереди». Раньше он был experimental и не все плагины его реализовывали корректно. Теперь стабилен, и scheduler тратит меньше лишних попыток scheduling на поды, которые всё равно не поместятся.
  • Scheduler теперь правильно учитывает resize-статус пода при принятии решений. Под в статусе Deferred resize не рассматривается как кандидат на rescheduling только из-за ресурсного несоответствия.

Для большинства кластеров это фоновые улучшения. Для тех, кто пишет кастомные плагины к scheduler или использует VPA активно - заметнее.

Как мы тестировали in-place resize на stateful-нагрузке

Тестовый стенд: кластер на Deckhouse (кандидат с 1.35), нагрузка - PostgreSQL в StatefulSet с одним primary и двумя репликами. Не самый экзотический кейс, но показательный: это именно та нагрузка, где рестарт пода при вертикальном масштабировании болезненен - переключение с primary на реплику и обратно, временная недоступность записей.

Сценарий: меняем requests.cpu для primary с 2 до 4 через patch. Смотрим что происходит.

Что получили:

Изменение применилось без рестарта контейнера. CPU-лимит у cgroup увеличился в течение нескольких секунд. PostgreSQL продолжал принимать запросы без прерывания. В pod.status появился containerStatuses[].resources с новыми значениями.

Это работает. Availability при изменении CPU requests не пострадала.

Где оказалось сложнее:

Memory requests - другая история. Уменьшение requests.memory для контейнера у нас привело к статусу Deferred: kubelet честно сказал, что уменьшить allocation без рестарта не может при текущей конфигурации cgroup v2 и containerd. Это не баг - это задокументированное поведение, но важно понимать: in-place resize работает легко на увеличение, а уменьшение памяти по-прежнему может требовать рестарта.

Ещё один момент: VPA (Vertical Pod Autoscaler) в нашей версии Deckhouse пока что не интегрирован с in-place resize полностью. VPA умеет выдавать рекомендации и применять их, но в нашем тесте он по умолчанию всё равно шёл через eviction и пересоздание пода. Нужно явно настраивать VPA в режиме updateMode: InPlaceOrRecreate, который появился именно в 1.35. Это важный нюанс для тех, кто хочет совместить VPA и in-place без рестартов - надо явно указать режим, само не случится.

Где сейчас

На тестовом стенде картина такая: для CPU-intensive stateful-нагрузок in-place resize работает чисто и availability не трогает. Для сценариев с уменьшением памяти - поведение зависит от конкретного runtime и требует проверки. Мы зафиксировали это как ограничение, которое нужно учитывать при проектировании VPA-политик.

В production на клиентских кластерах будем переходить после выхода stable-версии Deckhouse с 1.35. До этого - только тестовые стенды. После обновления Deckhouse до 1.68 и Kubernetes 1.34 у нас уже есть опыт накатки свежих релизов на stateful-инфраструктуру, так что процесс отработан. Но in-place resize - достаточно серьёзное изменение в поведении kubelet, чтобы не торопиться.

Если резюмировать текущее понимание: graduated - это хороший сигнал, CPU resizing работает, для памяти нужно проверять. Для stateful-нагрузок с репликацией это уже практически применимо, для монолитных stateful-сервисов с большим потреблением памяти - проверяйте на стенде перед включением VPA с in-place режимом.

Контакт

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

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