Заметка

Kubernetes 1.36 (Haru): что реально меняется в проде

Mutating webhooks начали умирать, Ingress NGINX retired, HPA scale-to-zero всё ещё alpha. Прагматичный триаж 1.36 для платформенной команды — без блогерских преувеличений.

K8s 1.36 (Haru) выехал в GA 22 апреля 2026. Сквозная тема релиза — «толкаем сложность в ядро платформы»: всё меньше внешнего glue (admission webhooks, метрики-адаптеры, custom log shippers), всё больше встроенных эндпоинтов и CEL внутри API-сервера. Для платформенной команды это означает, что часть привычного зоопарка сервисов можно начинать выпиливать — но не везде, где блогеры пишут «GA». Полезно сверять с официальной таблицей feature-gates, потому что половина обзорных статей про 1.36 уже разошлась с реальностью.

Mutating webhooks начали умирать

MutatingAdmissionPolicy ушёл в GA — мутация теперь живёт CEL-выражением внутри kube-apiserver. Никакого внешнего HTTP-вебхука, TLS-ротации, отдельных подов, мониторинга up{job="...-webhook"} и таймаутов. Целый класс инцидентов закрывается одним релизом: просроченный сертификат, недоступный Gatekeeper, latency-spike на admission, который сваливает CREATE/UPDATE по всему кластеру.

Это не значит, что Kyverno и Gatekeeper уезжают завтра. Сложные политики с lookup'ами в кросс-объект-стейте, генерация ресурсов, image-verification — пока на внешних движках. Но шаблонные мутации вида «впихнуть HTTP_PROXY env во все поды namespace'а» теперь натурально живут в API-сервере и тестируются на стейджинге без curling вебхука.

Ingress NGINX выведен из эксплуатации

SIG Network вместе с Security Response Committee 24 марта 2026 объявили ingress-nginx retired: ни релизов, ни багфиксов, ни security-патчей. Существующие установки продолжают принимать трафик — это не killswitch. Но annotation-heavy конфиги — теперь technical debt с тикающим таймером. Целевые опции: Envoy Gateway, Cilium Gateway, ALB/Lattice у облачных провайдеров, абстракция Gateway API сверху. Аудит начинается с инвентаризации: сколько annotation-фич реально используется, сколько из них имеет 1:1-эквивалент в Gateway API. Часто оказывается, что 80% аннотаций — это rewrite-target и proxy-buffer-size, мигрируется быстро.

HPA Scale-to-Zero — это alpha, а не GA

Здесь больше всего шума. Feature-gate HPAScaleToZero сидит в alpha с K8s 1.16 и в 1.36 остаётся alpha, default false. Часть обзорных статей утверждает обратное — это дезинформация. Verify через feature-gates docs, не через медиум.

Что реально работает в 1.36, если включить gate флагом --feature-gates=HPAScaleToZero=true у kube-apiserver: HPA умеет нативно дойти до minReplicas: 0 для Object и External метрик (например, sqs_queue_length), но не для CPU/memory. Метрики-адаптер всё равно нужен. На практике это означает: KEDA остаётся релевантной, потому что её scaler-каталог покрывает все источники, которых нет в Kubernetes-родной метрик-цепочке. Combo «Karpenter + HPA scale-to-zero + KEDA-источник» — это и есть serverless K8s, который ждали с 2019-го.

User Namespaces GA — главный security-win за годы

Контейнерный root маппится на unprivileged user на хосте. Container breakout (CVE-runc-стиля) выходит в sandbox без привилегий вместо хост-root. Для multi-tenant кластеров — самое существенное изменение модели угроз за несколько лет. Включается userNamespaces: true в Pod spec плюс kernel ≥ 6.5 на нодах. На EKS/GKE это уже стандартные AMI, на bare-metal и Talos — проверять.

GPU-планирование: beta приезжает сама, alpha — нет

Второй сюжет, где обзоры релиза расходятся с таблицей гейтов, — планирование GPU-нагрузок. Partitionable devices в 1.36 ушли в beta, и гейт DRAPartitionableDevices включён по умолчанию в kube-apiserver и kube-scheduler; в 1.33–1.35 фича была alpha и выключена. Разница практическая: механизм приезжает вместе с апгрейдом, отдельного решения оператора для этого не нужно.

Механика такая. Драйвер объявляет в ResourceSlice набор sharedCounters — пул физического ресурса, скажем 8Gi памяти карты, — а логические устройства через consumesCounters записывают, сколько из этого пула забирают. Два устройства по 6Gi из общего 8Gi одновременно выданы не будут: перекрытие считает планировщик, потребителю ResourceClaim знать о нём не нужно. Это тот самый учёт, ради которого раньше нарезали MIG-профили руками или писали свой device-плагин, и он же выводит дорогую карту из режима «отдана поду целиком» — арифметика та же, что с CPU- и memory-реквестами.

А вот gang scheduling, который в обзорах 1.36 подают как новинку релиза, приехал раньше. API Workload и PodGroup (scheduling.k8s.io/v1alpha2) сидит в alpha с 1.35, гейты GenericWorkload и GangScheduling по умолчанию выключены. В 1.36 добавились два своих alpha-гейта вокруг него: WorkloadWithJob — Job-контроллер сам создаёт Workload и PodGroup, руками объекты больше не лепить; WorkloadAwarePreemption — вытеснение считает единицей всю группу и ищет жертв по кластеру, а не по одной ноде. Релиз принёс не all-or-nothing планирование, а его пригодность к работе — при трёх включённых гейтах и явно включённой alpha-API-группе.

Деталь, ради которой в закладках стоит держать именно таблицу feature-gates, а не концепт-страницы: на 24 августа 2026 подраздел про partitionable devices лежит в документации под заголовком «DRA alpha features», хотя текст внутри подраздела говорит beta. Группировка разделов отстаёт от статусов, таблица гейтов — нет.

Тихая операционная зрелость

Несколько вещей, не делающих заголовков, но меняющих day-2:

  • In-Place Vertical Pod Scaling теперь работает даже при Static CPU Manager policy: VPA меняет requests/limits без рестарта и без потери CPU pinning. Для high-perf workloads VPA становится truly non-disruptive.
  • Ephemeral Service Account Tokens for image pulls (KEP-2535, GA): kubelet получает short-lived OIDC-токен у registry под scope пода вместо вечно живущего imagePullSecret. Один зеро-трастовый артефакт меньше в Secret store.
  • PSI metrics GA: Pressure Stall Information из Linux kernel напрямую в kubelet metrics. Вместо «memory at 95%» (которое может быть file cache) — реальное «насколько долго таски стоят, ожидая ресурс». Меньше ложных NodeNotReady, точнее тюнинг VPA.
  • Node Log Query GA: kubectl get --raw "/api/v1/nodes/<node>/proxy/logs/?query=kubelet" — системные логи без SSH-доступа на ноду. Требует gate NodeLogQuery плюс enableSystemLogQuery в kubelet config.
  • Fine-Grained Kubelet Authz GA: вместо coarse system:kubelet-api-admin — гранулярные verbs на каждый subresource (nodes/proxy/logs — get, nodes/proxy/exec — deny). Аудит-аккаунты получают read-only без полного админа над kubelet.

Что молча сломается на upgrade

  • gitRepo volume permanently disabled: манифесты с gitRepo: дают broken pods. Чинится переносом build в CI и mount'ом artifact'а.
  • IPVS mode kube-proxy удалён (был deprecated в 1.35). Миграция: iptables с nftables backend, либо Cilium/eBPF.
  • 1.36 — последний релиз с containerd 1.6 support. Параллельно с upgrade'ом готовить containerd 2.x.
  • service.spec.externalIPs теперь печатает warning'и: путь к удалению. Уезжать на Ingress controller или Gateway API.

Триаж на месяц

Adopt early: MutatingAdmissionPolicy GA, User Namespaces GA, Suspended Job mutability, Fine-Grained Kubelet Authz. Adopt selectively: DRA для GPU-нагрузок — partitionable devices приезжают в beta уже включёнными, OCI artifact volumes, In-Place VPA (если уже на VPA). Watch, don't rush: HPA scale-to-zero (alpha, нужен feature-gate), gang scheduling (API с 1.35, три гейта выключены), Mixed Version Proxy (beta), Smarter HPA Pod Selection (alpha). Перед kubeadm upgrade — обязательная пара kubent + Pluto на манифесты и Helm-charts; deprecated API leak есть в большинстве кластеров и всплывает только в момент upgrade.

© 2026 axyi.ru · CC BY 4.0