Kubernetes 1.33: упорядоченное удаление ресурсов, изменение алгоритма CrashLoopBackOff и декларативная валидация
Сегодня официально выпустили новую версию Kubernetes — 1.33. Среди главных нововведений — упорядоченное удаление ресурсов в пространстве имён на основе логических зависимостей и соображений безопасности, декларативная валидация для нативных API-типов, расширение механизма CredentialProvider, доступ подов к информации о топологии кластера, изменение алгоритма выдержки CrashLoopBackOff, обязательная аутентификация при извлечении private-образов из репозиториев и новый конфигурационный файл .kuberc
.
Для подготовки статьи мы использовали информацию из блога Kubernetes, таблицы Kubernetes enhancements tracking, CHANGELOG-1.33, а также конкретные issues, pull requests и Kubernetes Enhancement Proposals (KEPs).
Мы разбили все изменения на следующие разделы:
Внутри каждого раздела упорядочили изменения по уровню их готовности к использованию. Всего в новом релизе 64 изменения. Из них:
Alpha — 26 новых функций;
Beta — 20 продолжают улучшаться;
Stable — 18 признаны стабильными.
Примечание
Мы сознательно не переводим названия фич на русский. Они в основном состоят из специальной терминологии, с которой инженеры чаще сталкиваются в оригинальной формулировке.
Узлы
Alpha-фичи
DRA: Prioritized Alternatives in Device Requests
KEP 4831 «Динамическое распределение ресурсов с помощью структурированных параметров» (см. Обзор Kubernetes 1.30) позволил запрашивать специфические типы ресурсов с помощью ResourceClaim
. Однако текущая реализация API не позволяет пользователю задавать приоритеты, если потребностям рабочей нагрузки удовлетворяют несколько типов или конфигураций устройств. KEP решает эту проблему: теперь можно указать несколько вариантов запросов на динамические ресурсы (например, разные типы GPU) в виде упорядоченного списка. Планировщик попытается удовлетворить эти запросы по очереди, начиная с самого предпочтительного.
Реализация
Объект ResourceClaim
содержит поле DeviceClaim
, которое, в свою очередь, включает список объектов DeviceRequest
. Такая структура уже позволяет пользователю запрашивать выделение разных типов устройств в рамках одного общего запроса и применять общие ограничения и настройки. Предлагаемые изменения добавят гибкости: например, можно будет создать общий запрос на GPU, который может быть удовлетворён разными моделями графических ускорителей.
Изменения будут вноситься постепенно: версия v1beta1 API будет дополнена, а чистая, переработанная структура появится в версии v1beta2.
В v1beta1 появится новое поле FirstAvailable
. Оно будет содержать упорядоченный список объектов DeviceSubRequest
(подзапросов на устройства). Чтобы выполнить основной запрос (тот, что содержит FirstAvailable
), K8s достаточно будет выполнить ровно один подзапрос из этого списка. Порядок элементов в списке задаёт приоритет: планировщик сначала попытается выполнить первый подзапрос, если не получится — второй и так далее.
Дополнение не ломает совместимость, но приводит к определённым тонкостям при работе с API: при использовании FirstAvailable
почти все остальные поля исходного DeviceRequest
(кроме Name
) использовать нельзя.
Отказаться от такой неудобной конструкции позволит v1beta2. В ней структура DeviceRequest
будет переработана. Поле Name
останется без изменений, но для самого запроса появятся два взаимоисключающих поля, позволяющие указать либо один конкретный запрос, либо список альтернатив:
Поле
Exactly
— используется, когда нужен один конкретный тип устройства без альтернатив. Его тип —SpecificDeviceRequest
, который содержит все поля изv1beta1.DeviceRequest
, кромеName
.Поле
FirstAvailable
— используется для задания упорядоченного списка альтернативных запросов. Каждый элемент списка имеет типDeviceSubRequest
. Планировщик будет перебирать списокFirstAvailable
по порядку и выберет первый же вариант, который удовлетворяет требованиям.
Важно отметить, что механизм динамического выделения ресурсов (DRA) пока не умеет проводить оценку (скоринг) доступных вариантов, то есть выбранное устройство не всегда будет самым оптимальным из возможных. Такое поведение соответствует текущей логике DRA — всегда выбирается первый найденный подходящий вариант. Реализация скоринга планируется в будущем (предварительное обсуждение ведётся в #4970).
Ensure secret pulled images
Раньше для политик извлечения образов IfNotPresent
и Never
kubelet ограничивался проверкой того, доступен ли образ на узле. Если образ был скачан ранее (например, другим подом), новый под мог его использовать без проверки авторизации.
Теперь kubelet отслеживает, с какими учётными данными (ImagePullSecrets
) был скачан каждый образ. Эта информация сохраняется даже после перезагрузки kubelet'а. Когда под с IfNotPresent
или Never
и ImagePullSecrets
запрашивает образ, kubelet смотрит, есть ли он на узле. После этого проверяет, скачивался ли этот образ ранее с теми же ImagePullSecrets
, которые указаны в текущем поде.
Если образ есть и авторизован с теми же секретами, kubelet запускает под так же, как и раньше для IfNotPresent
. Если образ есть, но авторизация с этими секретами не проходила, kubelet попытается выполнить аутентификацию и при необходимости заново скачать образ, используя указанные секреты. В том случае, если используется политика Never
, kubelet откажет в запуске контейнера, так как образ необходимо проверить/скачать, а политика это запрещает.
Для imagePullPolicy: Always
поведение не меняется — она всегда проверяет доступ и наличие обновлений в репозитории.
Теперь администраторы кластеров смогут выбрать способ проверки образов:
Запретить доступ к любым образам без проверки.
Разрешить доступ без проверки только к определённому списку предварительно загруженных образов.
Разрешить доступ ко всем предварительно загруженным образам без проверки (поведение по умолчанию).
Разрешить доступ ко всем образам без повторной проверки учётных данных (как раньше).
Новое поведение можно включить с помощью переключателя функциональности KubeletEnsureSecretPulledImages
(в alpha-версии по умолчанию отключён).
DRA: AdminAccess for ResourceClaims and ResourceClaimTemplates
Администраторам кластера иногда нужно получить доступ к устройству, которое уже используется обычным подом, например, для мониторинга его состояния, диагностики или сбора метрик. У имеющегося механизма DRA нет стандартного и безопасного способа сделать это, чтобы не прервать работу пользователя или не запросить эксклюзивный доступ к устройству.
KEP позволяет администраторам кластера помечать запрос в ResourceClaim
или ResourceClaimTemplate
флагом доступа администратора. Этот флаг разрешает привилегированный доступ к устройствам, позволяя выполнять административные задачи без ущерба для безопасности. Доступ имеют только пользователи, которые уполномочены создавать объекты ResourceClaim
или ResourceClaimTemplate
в пространствах имён, помеченных флагом доступа администратора, то есть пользователи, не являющиеся администраторами, не смогут злоупотребить этой функцией.
Механизм работы
В спецификацию (spec.devices.requests[])
внутри ResourceClaim
и ResourceClaimTemplate
добавляется булево поле adminAccess
. Если установить его в true
, запрос будет помечен как административный. Создавать или изменять ResourceClaim
/ResourceClaimTemplate
с adminAccess: true
разрешено только в пространствах имён со спецлейблом kubernetes.io/dra-admin-access: "true"
. Это предотвращает использование фичи обычными пользователями.
При создании/обновлении ResourceClaim
/ResourceClaimTemplate
с adminAccess: true
API-сервер проверяет, есть ли у пространства имён соответствующая метка. Если её нет, запрос отклоняется. Планировщик Kubernetes игнорирует ResourceClaim
с adminAccess: true
при расчёте доступности ресурсов для обычных подов. То есть административный доступ не мешает выделению того же устройства для обычного пользователя. Планировщик просто пропускает стандартные проверки эксклюзивности и позволяет административному поду «подключиться» к уже занятому устройству.
Вся новая функциональность скрыта за переключателем функциональности (feature gate) DRAAdminAccess
.
Support PSI based on cgroupv2
Механизм PSI (Pressure Stall Information) в ядре Linux измеряет, сколько времени задачи ждут доступа к ресурсам (CPU, память, ввод/вывод), даже если общая загрузка ресурсов не 100 %. Высокие значения PSI означают, что задачи тормозят из-за нехватки ресурсов, что напрямую влияет на производительность приложений. PSI позволяет получить более точную картину давления на ресурсы в отличие от классических метрик утилизации (usage %).
Иногда узел Kubernetes начинает тормозить из-за нехватки CPU, памяти или диска, но сам Kubernetes узнаёт об этом слишком поздно, после того как на узле начинаются проблемы (например, OOM Killer убивает процессы). Стандартные метрики загрузки не всегда показывают реальную картину потребления ресурсов.
KEP реализует поддержку метрики PSI («давления»), которая показывает, как долго задачи ждут своей очереди для доступа к ресурсам. Если давление высокое, kubelet пометит узел как перегруженный. Планировщик увидит это и перестанет отправлять новые поды на этот узел, пока тот не «придёт в себя».
KEP предусматривает два этапа реализации. На первом (alpha-1) kubelet получит поддержку механизма PSI и сможет получать статистику о давлении на ресурсы на узле. Соответствующие метрики добавятся в Summary API (/stats/summary
), и их можно будет просматривать через инструменты мониторинга или kubectl top node
(после его обновления).
На втором этапе (alpha-2) будут введены новые NodeCondition (условия узла) — NodeSystemCPUContentionPressure
, NodeSystemMemoryContentionPressure
и NodeSystemDiskContentionPressure
, а kubelet сможет отслеживать метрики и принимать решения на их основе. Например, если avg60 (среднее «давление» за 60 секунд) превысит настраиваемый порог (threshold) (В будущем как периоды, так и порог могут быть изменены. — Прим. авт.) и при этом avg10 (среднее за 10 секунд) тоже окажется выше порога (то есть давление растёт или стабильно высокое), то kubelet установит соответствующий NodeCondition в True. Если avg60 упадёт ниже порога, NodeCondition будет установлен в False.
Кроме того, kubelet сможет автоматически навешивать ограничение (taint) NoSchedule
на узел, когда тот получает один из новых NodeCondition (например, node.kubernetes.io/cpu-contention-pressure=:NoSchedule
). В этом случае на узел не будут планироваться новые поды.
Фича управляется переключателем функциональности PSINodeCondition
.
Pod Generation
Предыстория
Поле status.resize
в PodStatus отображает статус последнего запроса на изменение выделенных ресурсов (CPU/памяти) для пода без его перезапуска (in-place resize). Состояние Proposed было одним из возможных значений, которое мог принимать ResizeStatus в первоначальной реализации фичи.
Вот как раньше выглядел процесс:
Пользователь меняет
spec.containers[].resources
пода, например запрашивает больше CPU/памяти.API-сервер обнаруживает это изменение и устанавливает
pod.status.resize = "Proposed"
, сигнализируя, что пользователь запросил изменение размера.Kubelet видит изменения в spec, статус "Proposed" и начинает проверять, возможно ли выполнить это изменение на узле.
После проверки kubelet перезаписывает
pod.status.resize
на другое значение, например на "InProgress" (изменение размера выполняется).
Такой механизм мог приводить к ситуациям, когда kubelet менял статус, например, на Feasible, а API-сервер перезаписывал его обратно на Proposed или наоборот. В результате было решено убрать состояние "Proposed" из возможных значений ResizeStatus (PR 130574). После этого только kubelet отвечал за обновление этого поля, исходя из реального прогресса обработки запроса на изменение ресурсов.
Увы, когда убрали "Proposed", исчез и явный сигнал от API-сервера о том, что запрос только что поступил. То есть невозможно сказать, видел ли kubelet новое значение в spec или он просто ещё не успел обновить status.resize
.
KEP-5067 закрывает [именно этот — см. предысторию] пробел в понимании, видел ли kubelet последнее изменение PodSpec. Разработчики воспользовались существующим полем metadata.generation
. Теперь API-сервер будет устанавливать его в 1 (единицу) при создании пода и увеличивать на 1 при каждом изменении в PodSpec. Кроме того, в PodStatus добавится новое целочисленное поле status.observedGeneration
.
При синхронизации состояния пода в рамках цикла syncLoop kubelet записывает в status.observedGeneration
значение metadata.generation
того пода, который обрабатывается в данный момент. Аналогичное поле observedGeneration
добавляется и в каждую запись status.conditions
, чтобы было ясно, к какой версии пода относится конкретное условие.
Tune CrashLoopBackOff
Механизм CrashLoopBackOff (экспоненциальной выдержки) в Kubernetes смягчает последствия ситуации, когда контейнер по какой-либо причине постоянно перезапускается: интервалы между повторными попытками запуска постепенно возрастают (10 с. → 20 с. → 40 с. → 80 с. → 160 с. → 300 с. (5 минут) → 300 с. → 300 с. → 300 с.…). Сброс до минимального значения происходит, если контейнер без сбоев проработал 10 минут.
Проблема в том, что 5 минут — это часто слишком долго, особенно для современных приложений (например, для AI/ML или игр) или вспомогательных контейнеров (сайдкаров), которые должны работать всегда.
KEP меняет алгоритм выдержки. Пауза теперь будет начинаться с 1 секунды (вместо 10) и увеличиваться максимум до 1 минуты (вместо 5). Кроме того, администраторы кластера смогут на конкретных узлах настраивать максимальную паузу по своему усмотрению (до 1 секунды).
Второе изменение касается сброса до минимального значения. Время, которое контейнер должен успешно проработать, чтобы Kubernetes «забыл» про предыдущие падения и начал отсчёт пауз с самого начала, останется прежним — 10 минут. Раньше оно зависело от максимальной паузы (2х), теперь — нет.
Новое поведение для CrashLoopBackOff (и только для CrashLoopBackOff) можно включить переключателем функциональности ReduceDefaultCrashLoopBackOffDecay
. После этого для всех рабочих нагрузок с restartPolicy: Always
или restartPolicy: OnFailure
кривая ожидания будет начинаться с одной секунды и достигать максимального значения в одну минуту.
Примечание
KEP содержит массу дополнительной информации, такой как анализ влияния различных начальных значений выдержки (число рестартов за определённый промежуток времени), анализ оверхеда kubelet’а, который должен вырасти из-за большего числа рестартов, и др.
Container Stop Signals
Среды исполнения (runtime) контейнеров позволяют задавать STOPSIGNAL, который будет посылаться приложению перед завершением работы. Раньше, чтобы изменить стандартный сигнал SIGTERM, нужно было пересобирать образ контейнера, прописав нужный сигнал прямо в Dockerfile. Это особенно неудобно, когда используются готовые (pre-built) образы.
KEP позволяет указывать STOPSIGNAL прямо в настройках пода. Для этого в секции lifecycle контейнера в спецификации пода появится новое поле stopSignal
:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
lifecycle:
stopSignal: SIGUSR1
При остановке контейнера kubelet в первую очередь будет смотреть на это поле. Если оно задано, kubelet передаст указанный сигнал (SIGUSR1 в примере) через CRI (Container Runtime Interface) в среду исполнения контейнера, а та — процессу в контейнере.
Новый stopSignal
в PodSpec имеет наивысший приоритет и переопределяет STOPSIGNAL, заданный в образе. STOPSIGNAL, который реально был использован, будет отображаться в статусе контейнера.
Split L3 Cache Topology Awareness in CPU Manager
KEP является продолжением KEP 4800 (см. обзор Kubernetes 1.32). В его рамках была дополнена документация, добавлены метрики для отслеживания распределения блоков кэша Uncore (он же L3), добавлены топологии процессоров с раздельным Uncore-кэшем и монолитным Uncore-кэшем для процессоров на базе x86 и ARM и др.
Expose Node labels via downward API
Многим приложениям (особенно AI/ML, распределённым stateful-приложениям, сетевым плагинам CNI) важно знать топологию кластера для оптимизации производительности (например, чтобы GPU общались с соседними GPU) или повышения отказоустойчивости (размещения реплик в разных зонах). Сейчас, чтобы получить эту информацию, подам приходится использовать initContainer, который запрашивает у API Kubernetes информацию об узле, где под работает. Это сложно, требует дополнительных прав для initContainer и по сути является «костылём».
KEP добавляет механизм, который будет автоматически копировать стандартные топологические лейблы с узла на под, когда тот планируется на узел. После этого приложение внутри контейнера сможет получить к ним доступ через стандартный механизм Downward API так же легко, как и к любым другим лейблам пода.
По умолчанию будут копироваться стандартные метки узла topology.kubernetes.io/zone
, topology.kubernetes.io/region
и kubernetes.io/hostname
. В kube-apiserver добавится новый admission-плагин PodTopologyLabels
. Этот плагин будет добавлять топологические лейблы узла в субресурс pods/binding
. Если у пода уже были лейблы с такими же ключами (например, topology.kubernetes.io/zone
), они будут перезаписаны значениями с узла.
Фича будет отключена по умолчанию; активировать её можно будет через переключатель функциональности PodTopologyLabelsAdmission
.
Beta-фичи
Fine grained Kubelet API authorization
KEP-2862 предлагает более гранулярную систему авторизации для API kubelet. Вместо использования единого разрешения nodes/proxy для всех операций вводятся специальные эндпойнты:
nodes/healthz
— для проверки здоровья;nodes/pods
— для просмотра подов;nodes/configz
— для конфигурации.
Новое поведение включается переключателем функциональности KubeletFineGrainedAuthz
(в альфа-версии по умолчанию установлен в False). При включённом переключателе kubelet сначала попытается авторизовать запрос через новые эндпойнты. Если авторизация не прошла, он вернётся к старому способу через субресурс proxy
.
Add CPUManager policy option to restrict reservedSystemCPUs to system daemons and interrupt processing
KEP добавляет новую опцию strict-cpu-reservation
в статическую политику CPU Manager. Она гарантирует, что процесоры, зарезервированные для системы (reservedSystemCPUs), будут использоваться только ею (то есть поды burstable и best-effort не смогут получить к ним доступ, как это было ранее). Примеры см. в обзоре Kubernetes 1.32.
DRA: structured parameters
Параметры ресурсов в DRA непрозрачны для Kubernetes. Они интерпретируются контроллером драйвера DRA (для размещения claim’ов) и kubelet-плагином драйвера DRA (для конфигурирования ресурсов на узле). При планировании пода kube-scheduler и контроллер(ы) драйвера DRA, обрабатывающий(ие) claim’ы для пода, обмениваются данными через apiserver, обновляя объект PodSchedulingContext
. В итоге все активные claim’ы учитываются и под планируется на узел.
Такой подход создаёт проблемы для Cluster Autoscaler (CA) или любого контроллера более высокого уровня, которому необходимо принимать решения для группы подов, например для планировщика заданий. Он не может смоделировать эффект аллокации или реаллокации claim’ов с течением времени. Только у драйверов DRA есть необходимая для этого информация.
KEP «Динамическое распределение ресурсов с помощью структурированных параметров» (4381) решает эту проблему. Подробнее — в обзоре Kubernetes 1.30.
VolumeSource: OCI Artifact and/or Image
KEP добавляет в Kubernetes новый VolumeSource, поддерживающий OCI-образы и/или OCI-артефакты. Теперь пользователи смогут упаковывать файлы и шарить их в контейнерах пода, не включая в основной образ. Это позволит снизить уязвимости и упростит создание образов. Подробнее — в обзоре Kubernetes 1.31.
In-Place Update of Pod Resources
KEP позволяет обновлять запросы и лимиты пода «на месте» — то есть без необходимости перезапускать под или его контейнеры. PodSpec теперь допускает изменение определённых ресурсов (то есть она сделана частично mutable). PodStatus также доработан — он предоставляет информацию о ресурсах, выделенных для пода, а также о фактических ресурсах, потребляемых подом и его контейнерами (подробнее).
В этом релизе статус Resize заменён состояниями пода (PodResizePending
и PodResizing
), политика ResizeRestartPolicy NotRequired
переименована в PreferNoRestart
, контракт CRI UpdateContainerResources обновлён, убран переключатель функциональности InPlacePodVerticalScalingAllocatedStatus
, а AllocatedResources включены в расчёты для суммирования ресурсных запросов подов и активируются переключателем InPlacePodVerticalScaling
.
Add CPUManager policy option to distribute CPUs across NUMA nodes instead of packing them
KEP добавляет опцию distribute-cpus-across-numa
для static-политики CPUManager, чем позволяет равномерно распределять эксклюзивные CPU по нескольким NUMA-узлам. Тем самым повышается производительность параллельных приложений, чувствительных к задержкам синхронизации, за счёт более сбалансированной загрузки NUMA-ресурсов. В таких сценариях производительность часто лимитируется самым медленным потоком/процессом.
add ProcMount option
KEP добавляет поле procMount
в секцию securityContext
. Оно позволяет сделать директорию /proc
контейнера Unmasked
или смонтировать её как доступную для чтения/записи процессом контейнера. Подробнее — в обзоре Kubernetes 1.30.
Support User Namespaces in pods
KEP добавляет поддержку пользовательских пространств имён в stateless-подах. Идея в том, чтобы запускать процессы в подах с другими ID пользователя и ID группы, а не только с унаследованными с хоста. В этом случае привилегированный процесс в поде будет непривилегированным на хосте. Если такой процесс «вырвется» за пределы контейнера, потенциальный вред будет минимизирован, поскольку на хосте его привилегии будут ограничены. Подробнее — в обзоре Kubernetes 1.27.
DRA: Resource Claim Status with possible standardized network interface data
KEP добавляет новое поле Devices
в ResourceClaim.Status
. Теперь драйверы могут сообщать данные о состоянии для каждого устройства в заявке на ресурс (resource claim). Это повысит наблюдаемость и облегчит поиск и устранение проблем. Подробнее — в обзоре Kubernetes 1.32.
Allow zero value for Sleep Action of PreStop Hook
KEP 3960 представил действие sleep для PreStop-хуков жизненного цикла контейнеров. Однако для него нельзя установить ноль в качестве допустимого значения. Этот KEP исправляет ситуацию. Подробнее — в обзоре Kubernetes 1.32.
Fine-grained SupplementalGroups control
KEP предлагает ввести в API новое поле SupplementalGroupsPolicy
. Оно позволит контролировать, какие дополнительные группы навешиваются на первый процесс в контейнере, следуя «принципу наименьшей неожиданности». Администраторы кластера смогут настраивать политики безопасности на защиту SupplementalGroupsPolicy
в кластере, что позволит устранять проблему неожиданного обхода SupplementalGroups
. Также пользователи смогут определять, какие группы на самом деле навешены на процессы в контейнерах. Подробнее — в обзоре Kubernetes 1.31.
Stable-фичи
Deprecate status.nodeInfo.kubeProxyVersion field
Поле kubeProxyVersion
в NodeStatus
окончательно получает deprecated-статус. Оно использовалось облачным провайдером GCP до версии 1.28 для устаревшего встроенного cloud-provider-gcp (#117806), а до версии 1.29 — для внешнего cloud-provider-gcp (#533).
Sidecar Containers
Поле restartPolicy
для init-контейнеров, появившееся в Kubernetes 1.28, переходит в stable-статус. Его смысл — дать знать kubelet’у, что init-контейнер является sidecar-контейнером. В результате kubelet будет запускать init-контейнеры с restartPolicy = Always
в том же порядке, что и другие init-контейнеры, но вместо того, чтобы дожидаться завершения их работы, он будет ждать завершения последовательности запуска контейнера (условием завершения последовательности запуска будут успешное выполнение startup-пробы и завершение обработчика postStart).
node: cpumanager: add options to reject non SMT-aligned workload
KEP добавляет новые опции для существующей политики CPU Manager (static). Например, если включить опцию full-pcpus-only
, Kubernetes будет выделять контейнерам CPU только целыми физическими ядрами. То есть, если ядро имеет два логических потока, контейнер получит либо оба потока этого ядра, либо ни одного. Подробнее — в обзоре Kubernetes 1.22 (раздел «New CPU Manager Policies»).
Recursive Read-only (RRO) mounts
Монтирование read-only-томов появилось в Kubernetes с самого начала. Проблема в том, что в Linux read-only-тома при определённых условиях являются не совсем read-only.
Параметр recursiveReadOnly
(появился в v1.30) исправляет этот недочёт, позволяя проводить read-only-монтирования рекурсивно. Для обратной совместимости поле recursiveReadOnly
не заменяет readOnly, а используется совместно с ним. То есть для того, чтобы включить рекурсивный режим read-only, необходимо задать оба поля (readOnly: true
и recursiveReadOnly: Enabled
). Параметр recursiveReadOnly
в v1.33 получает stable-статус.
Приложения
Alpha-фичи
Consider Terminating Pods in Deployments
Kubernetes различает terminating- (завершающиеся поды, deletionTimestamp
установлен, но контейнер ещё работает) и terminated-поды (завершённые поды, фаза Succeeded
или Failed
). В зависимости от стратегии развёртывания меняется отношение к terminating-подам: при RollingUpdate K8s не ждёт завершения старых подов, а сразу создаёт новые. В случае Recreate Kubernetes ждёт завершения работы старых подов во время обновления, но не ждёт при масштабировании. Это приводит к тому, что фактическое количество работающих + завершающихся подов может превысить лимит spec.replicas
+ maxSurge
.
KEP добавляет поле .spec.podReplacementPolicy
в DeploymentSpec, которое будет принимать два значения:
TerminationStarted (значение по умолчанию) — для RollingUpdate и для масштабирования поведение будет соответствовать текущему (то есть terminating-поды будут игнорироваться при запуске новых). В случае Recreate логика изменится: K8s перестанет ждать полного завершения работы подов и будет действовать, как только поды начнут переходить в terminating.
TerminationComplete — для RollingUpdate и при масштабировании новые поды не будут создаваться, если общее количество подов (работающих и завершающихся) превышает
.spec.replicas
+.spec.strategy.rollingUpdate.maxSurge
. Для Recreate это будет соответствовать его текущему поведению во время обновления (ждать полного завершения).
Кроме того, в статус Deployment'а и ReplicaSet'а будет добавлено новое поле .status.terminatingReplicas
для явного отслеживания количества завершающихся подов.
Stable-фичи
Backoff Limit Per Index For Indexed Jobs
KEP дополняет API Job, позволяя задавать число повторных попыток (backoff limit) для каждого индекса в индексированных задачах.
Job success/completion policy
KEP дополняет API Job, позволяя задавать кастомные условия, при которых индексированная задача (Job) может быть объявлена успешной. Подробнее — в обзоре Kubernetes 1.30.
Хранилище
Alpha-фичи
Add storage capacity scoring
KEP предлагает способ оценки узлов для динамического выделения постоянных томов (Persistent Volume, PV), который базируется на объёме памяти в плагине VolumeBinding. Поды можно будет динамически планировать на узлы в зависимости от объёма доступного пространства на узле и преследуемых целей:
Пример 1.
Мы хотим располагать запасом пространства для возможного увеличения размера тома. В этом случае планировщик найдёт узел с максимальным объёмом свободного места.
Пример 2.
Мы хотим максимально сократить количество узлов, чтобы снизить затраты на облако. В этом случае планировщик найдёт узел с наименьшим достаточным объёмом свободного места.
KEP добавляет в плагин VolumeBinding логику оценки узлов на основе доступной ёмкости хранилища, сообщаемой через механизм CSIStorageCapacity
. В результате планировщик может не просто найти узел, но и выбрать предпочтительный с точки зрения свободного места.
Логика настраивается глобально для всего кластера. Для этого в API планировщика (kubescheduler.config.k8s.io
) добавляется поле VolumeBindingArgs
. Предлагаются две стратегии:
Prefer a node with the maximum allocatable (по умолчанию). Планировщик будет выбирать узел, у которого, по данным CSIStorageCapacity, больше всего доступного места для данного типа хранилища (StorageClass).
Prefer a node with the least allocatable. Планировщик будет выбирать узел, у которого минимум доступного места.
Примечание
Новая логика оценки будет применяться только для динамически создаваемых томов. Если под запросит хотя бы один статически выделенный том, будет использована старая логика оценки.
Управлять новой функциональностью будет переключатель StorageCapacityScoring
.
Mutable CSINode Allocatable Property
Сейчас поле CSINode.Spec.Drivers[*].Allocatable.Count
(максимальное число томов CSI, которые можно подключить к узлу) не меняется после инициализации CSI-драйвера. Планировщик использует его для принятия решений о размещении подов с Persistent Volumes. Проблема в том, что при изменении (уменьшении) реального количества доступных слотов для подключения томов на узле (например, администратор вручную примонтировал том или слот был занят другим драйвером) информация в CSINode перестаёт соответствовать действительности. В результате планировщик может разместить под на узел, на котором по факту уже не осталось свободных слотов, и под зависнет в состоянии ContainerCreating
.
KEP решает эту проблему, делая поле CSINode.Spec.Drivers[*].Allocatable.Count
изменяемым (mutable). Также добавляются механизмы динамического обновления его значения: kubelet может периодически посылать запросы на эндпойнт NodeGetInfo
CSI-драйвера (интервал задаётся в новом поле CSIDriver.Spec.NodeAllocatableUpdatePeriodSeconds
) или немедленно реагировать на ошибки нехватки ресурсов (ResourceExhausted
) при попытке подключения тома, обновляя значение в CSINode.
Remove gitRepo volume driver
KEP удаляет устаревший драйвер тома gitRepo из Kubernetes из-за ряда проблем, в первую очередь из-за критической уязвимости CVE-2024-10220, позволяющей выполнить код на узле с правами root.
В версии 1.33 появится переключатель функциональности GitRepoVolumeDriver, который по умолчанию будет установлен в false, что приведёт к невозможности запуска подов, использующих gitRepo. API-определение gitRepo пока сохранится для обратной совместимости и плавного перехода, однако пользователям настоятельно рекомендуется мигрировать на безопасные альтернативы, такие как init-контейнеры или sidecar-контейнеров c git-sync.
В версии 1.36 переключатель функциональности будет заблокирован. Полное удаление кода драйвера запланировано в версии 1.39. Администраторы также могут запретить запуск рабочих нагрузок с gitRepo на уровне API с помощью Validating Admission Policy.
CSI Differential Snapshot for Block Volumes
KEP дополняет API CSI механизмом для отслеживания изменённых блоков (Changed Block Tracking, CBT). Это значительно повышает эффективность резервного копирования томов Kubernetes — CSI-драйвер теперь самостоятельно сообщает о том, какие блоки изменились с момента предыдущего снапшота. Кроме того, чтобы предотвратить перегрузку API Kubernetes, приложения для резервного копирования взаимодействуют не напрямую с apiserver, а через защищённое gRPC-соединение с выделенным sidecar-контейнером external-snapshot-metadata
. Тот отвечает за аутентификацию клиента с помощью Kubernetes audience-scoped-токенов и авторизацию доступа к ресурсам снапшотов, после чего проксирует запрос к CSI-драйверу через локальный сокет.
Beta-фичи
Speed up recursive SELinux label change
На хостах с SELinux в принудительном режиме (enforcing mode) пользователи одного контейнера не могут получить доступ к другому контейнеру или к хосту. Это обеспечивается за счёт контекста, который уникален для каждого контейнера, и лейблов, которые назначаются каждому файлу в каждом томе.
Однако такая защита может усложнять жизнь пользователям, которые развёртывают кластеры на базе SELinux: при запуске нового контейнера запускается рекурсивное переназначение лейблов для всех файлов в томе, привязанном к поду. Если том большой, процесс переназначения может затянуться.
Новая функция позволяет пропустить этап переназначения лейблов и тем самым ускорить монтирование тома. Подробнее — в обзоре Kubernetes 1.25.
В v1.33 фича остаётся в бета-стадии. Основные изменения коснулись документации, которая была дополнена/актуализирована.
Stable-фичи
Generic data populators
Старое поле DataSource в PVC было ограничено типами Persistent Volume Claim (клонирование тома) и Volume Snapshot (восстановление из снапшота). В него не получалось встроить поддержку кастомных типов данных из-за особенностей валидации (неподдерживаемые типы попросту игнорировались, а не приводили к ошибке).
KEP ввёл новое поле spec.dataSourceRef
в объект PVC. Оно позволяет создавать предзаполненные тома из произвольных источников (например, заполнять их образами виртуальных машин или данными из резервных копий). Для обработки этих новых источников используются внешние контроллеры-наполнители, а типы данных, с которыми те умеют работать, регистрируются в новом CRD VolumePopulator
.
Portworx file in-tree to CSI driver migration
KEP обеспечивает миграцию встроенного в кодовую базу Kubernetes (in-tree) драйвера Portworx в самостоятельный (out-of-tree) CSI-драйвер. Драйвер вошёл как бета-фича в K8s 1.25, однако он был по умолчанию выключен. В версии Kubernetes 1.31 он был включён по умолчанию, в 1.33 фича признана стабильной.
Always Honor PersistentVolume Reclaim Policy
Политика возврата (reclaim policy) томов типа Persistent Volume (PV) может не соблюдаться, если PV работает в связке с PVC (Persistent Volume Claim): PV соблюдает политику, если PVC удаляется до удаления PV.
Если первым из пары удаляется PV, политика возврата не выполняется, а связанный с PV внешний ресурс хранения не удаляется. KEP обеспечивает соблюдение политики возврата PV, если его удаление происходит раньше, чем удаление PVC.
Сеть
Alpha-фичи
IP/CIDR validation improvements
Раньше валидация IP-адресов и CIDR-строк в конфигурациях Kubernetes была не очень строгой — допускалось любое значение, которое принимали базовые функции (net.ParseIP
и net.ParseCIDR
), даже если в некоторых случаях это приводило к неоднозначности. Например, Go мог воспринять 010.0.0.1 как 10.0.0.1 (опустив лишний ноль), а система на базе libc могла интерпретировать 010.0.0.1 как 8.0.0.1 (приняв 010 за восьмеричное число).
После CVE-2021-29923 в Go 1.17 была изменена обработка IP-адресов с ведущими нулями. В Kubernetes также пришло понимание того, что необходимо изменить механизм валидации, сделав его более строгим.
Проблема в том, что резкое изменение валидации может поломать старые конфигурации, поэтому новый механизм будет вводиться постепенно: сначала будут выводиться предупреждения, потом включится строгая проверка — сначала она будет отключена по умолчанию, потом включена (список затронутых полей). При этом можно будет обновлять объекты со старыми IP-адресами, если такой IP-адрес не меняется.
PreferSameNode Traffic Distribution (formerly PreferLocal traffic policy / Node-level topology)
Раньше в Kubernetes была опция TrafficDistribution: PreferClose
, которая должна была направлять трафик на близкие инстансы сервиса. Однако понятие «близкие» определялось неоднозначно — это мог быть тот же узел, та же зона доступности или что-то ещё.
KEP убирает неоднозначность: старое значение PreferClose
переименовано в PreferSameZone
— «предпочитать ту же зону доступности». Кроме того, появляется опция PreferSameNode
, которая предписывает направлять трафик на тот же узел, если на нём есть копия целевого сервиса. Это очень полезно, например, для локальных DNS-кэшей.
Beta-фичи
Relaxed DNS search string validation
KEP ослабляет проверки для строк поиска DNS. Эти значения можно будет указывать в поле searches
в dnsConfig
, и поды смогут правильно разрешать короткие имена в случаях, когда строка поиска содержит символ подчёркивания или точку. Вводится переключатель функциональности RelaxedDNSSearchValidation
(по умолчанию выключен). При его включении будет использоваться новая логика проверки DNS-имён, которая в дополнение к существующей позволяет использовать символ подчёркивания «_» в любом месте, где в настоящее время разрешено использовать дефис «-», а также разрешает использовать точку «.». Подробнее — в обзоре Kubernetes 1.32.
Stable-фичи
Multiple Service CIDRs
KEP реализует новую логику работы аллокатора IP-адресов на базе двух новых объектов API: ServiceCIDR
и IPAddress
— и создаёт новые ServiceCIDR
, тем самым позволяя динамически увеличивать количество доступных IP-адресов для сервиса.
Новый аллокатор сможет «автомагически» потреблять IP-адреса из любого доступного ServiceCIDR. Эту модель можно сравнить с добавлением дополнительных дисков в систему хранения данных для увеличения её емкости. Дополнительная информация — в обзоре Kubernetes 1.29.
Topology Aware Routing
В многозональных кластерах случайная маршрутизация между сервисами может приводить к ненужному обмену трафиком между зонами, что увеличивает задержку (latency) и стоимость. KEP реализует механизм, который с помощью поля hints
в объектах EndpointSlice
позволит потребителям вроде kube-proxy маршрутизировать трафик с учётом топологии кластера (то есть направлять запрос к подам в той же зоне, из которой пришёл запрос).
В Kubernetes 1.33 стабильным (GA) становится само поле hints
, в то время как специфические механизмы автоматической маршрутизации на основе аннотаций (например, service.kubernetes.io/topology-mode=Auto
) не переходят в GA и считаются устаревшими — авторы KEP рассчитывают на соответствующее расширение API в будущем.
nftables kube-proxy backend
KEP реализует поддержку нового официального бэкенда nftables для kube-proxy. В перспективе тот сможет заменить iptables и IPVS и станет режимом kube-proxy по умолчанию в Linux. Замена и вывод из эксплуатации старых бэкендов пройдут в рамках отдельного KEP в будущем. Подробнее — в обзоре K8s 1.29.
Traffic Distribution for Services
KEP вводит новое поле routingPreference
в спецификацию сервисов Kubernetes. Оно должно заменить аннотацию service.kubernetes.io/topology-mode
и её предшественника — поле topologyKeys
(устарело в Kubernetes 1.21). Пример и подробности — в обзоре Kubernetes 1.30.
Deprecate v1.Endpoints and Associated Controllers
KEP формально объявляет устаревшим API v1.Endpoints в пользу v1.EndpointSlice — более производительного механизма, который уже используется ключевыми компонентами вроде kube-proxy. Сам API v1.Endpoints пока не удаляется из-за необходимости обеспечить обратную совместимость, при этом допускается отключение контроллеров (endpoints-controller, endpointslice-mirroring-controller), которые автоматически создают эти устаревшие объекты.
API
Alpha-фичи
Ordered namespace deletion
В настоящее время при удалении пространства имён его ресурсы удаляются в случайном порядке. Это может привести к непредсказуемым и небезопасным последствиям, когда, например, NetworkPolicy удаляется раньше пода.
KEP вводит механизм приоритетного удаления ресурсов в пространстве имён на основе логических зависимостей и соображений безопасности (например, поды удаляются раньше NetworkPolicies). Включить его можно переключателем функциональности OrderedNamespaceDeletion
.
Snapshottable API server cache
Механизм кэширования kube-apiserver (watchcache) эффективно обслуживает запросы для последнего наблюдаемого состояния. Однако LIST-запросы для предыдущих состояний вместо кэша отправляются напрямую в etcd либо через пагинацию, либо через указание resourceVersion
. Это создаёт значительную и непредсказуемую нагрузку на память API-сервера и снижает эффективность механизмов защиты от перегрузки (API Priority and Fairness).
KEP предлагает усовершенствовать кэширующий слой kube-apiserver, чтобы тот обслуживал все LIST-запросы из кэша. Кроме того, для гарантии корректности данных вводится механизм периодической проверки консистентности между кэшем и etcd с использованием хеширования и публикацией результатов в виде метрик (для альфы), которые будут указывать на неконсистентность. В бета-версии планируется реализовать автоматическое переключение на etcd в случае обнаружения расхождений.
Beta-фичи
Declarative Validation Of Kubernetes Native Types With validation-gen
В настоящее время правила валидации запросов к API Kubernetes пишутся вручную, что затрудняет прямой доступ к ним, анализ, обслуживание и тестирование.
KEP вводит механизм декларативной валидации для нативных API-типов Kubernetes, позволяя разработчикам определять правила проверки полей (например, минимальное значение, обязательность) с помощью специальных IDL-тегов прямо в файлах types.go
(см. пример ниже). Новый инструмент validation-gen
будет автоматически генерировать Go-код для валидации.
Активировать новый способ валидации можно будет с помощью переключателя функциональности DeclarativeValidation. В бета-версии это позволит осуществить частичную миграцию, когда сначала небольшое количество полей будет переведено на декларативную валидацию. Со временем их число будет расти, пока вся логика валидации не станет декларативной.
Кроме того, чтобы убедиться в идентичности ручной и декларативной валидации, будет создана дополнительная рантайм-проверка, которую можно будет активировать переключателем функциональности DeclarativeValidationMismatchMetrics
. При её включении будут выполняться как валидация, определённая вручную, так и декларативная валидация, а любые несоответствия будут выводиться в метрике declarative-validation-mismatch.
// staging/src/k8s.io/api/core/v1/types.go
// ReplicationControllerSpec is the specification of a replication controller.
type ReplicationControllerSpec struct {
// +k8s:optional
// +k8s:minimum=0
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
// +k8s:optional
// +k8s:minimum=0
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"`
...
}
В примере выше +k8s:optional
и +k8s:minimum
— IDL-теги, из которых validation-gen
сгенерирует код для валидации.
Coordinated Leader Election
Предлагается более безопасный механизм выборов лидера на основе lease’ов, но с двумя ключевыми изменениями:
Вместо конкуренции за lease инстансы будут «выдвигать» свои кандидатуры на lease, а координатор выборов закрепит lease за лучшим из доступных кандидатов.
Координатор выборов может пометить lease как «заканчивающуюся» (end of term), что тем самым послужит сигналом текущему лидеру прекратить её продление. В результате текущий лидер будет отстранён и заменён лучшим.
Подробнее — в обзоре Kubernetes 1.31.
Streaming Encoding for LIST Responses
KEP решает проблему высокого потребления памяти API-сервером при обработке LIST-запросов, особенно для больших CustomResourceDefinitions (CRDs).
Существующие механизмы кодирования ответа (в JSON или Protobuf) загружают все объекты из списка в память, формируют единый большой блок данных и только потом отправляют его клиенту. Этот KEP реализует «потоковое кодирование» (streaming encoding) конкретно для ответов на LIST-запросы («коллекций»). Вместо загрузки всего списка API-сервер будет кодировать и отправлять каждый элемент списка по отдельности. Это радикально снизит требования к памяти для одного запроса и сделает её потребление более предсказуемым.
Активировать новую фичу можно с помощью переключателей функциональности StreamingCollectionEncodingToJSON
(JSON) или StreamingCollectionEncodingToProto
(Protobuf).
Аутентификация
Alpha-фичи
Projected service account tokens for Kubelet image credential providers
Сейчас, чтобы под мог скачать приватный образ контейнера, ему нужен либо секрет (imagePullSecret), который хранится в Kubernetes и живёт долго, либо учётные данные, настроенные прямо на узле (то есть доступ к ним имеют все поды на этом узле). Оба варианта не слишком безопасны и удобны.
KEP расширяет существующий механизм kubelet credential provider. Это специальные плагины, через которые kubelet может получать учётные данные для доступа к репозиториям. В настройках kubelet (CredentialProvider) появляется новое поле TokenAttributes
. В нём в секции ServiceAccountTokenAudience
указывается целевая аудитория для учётных данных, а в ServiceAccountAnnotationKeys
перечисляются ключи аннотаций, которые будут извлечены и переданы плагину как часть CredentialProviderRequest
. Плагины могут использовать его для извлечения дополнительной информации, необходимой для получения учётных данных.
Пример конфигурации CredentialProvider
apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
providers:
- name: acr-credential-provider
matchImages:
- "*.registry.io/*"
defaultCacheDuration: "10m"
apiVersion: credentialprovider.kubelet.k8s.io/v1
tokenAttributes:
serviceAccountTokenAudience: my-audience
serviceAccountAnnotationKeys:
- domain.io/identity-id
- domain.io/identity-type
- domain.io/annotation-that-does-not-exist
Если для соответствующего репозитория настроен CredentialProvider с этой новой опцией и kubelet’у нужно скачать из него образ, kubelet запрашивает у API-сервера специальный, короткоживущий projected service account token (отсюда и название KEP), привязанный к этому конкретному поду. У него есть поле audience
, которое указывает, для кого этот токен предназначен (например, для конкретного репозитория или плагина).
Далее kubelet вызывает плагин credential provider'а, передавая ему не только информацию об образе (как раньше), но и этот PSA-токен. Плагин с помощью токена аутентифицируется во внешнем сервисе и обменивает PSA-токен на временные учётные данные для скачивания образа.
Плагин возвращает эти временные учётные данные kubelet'у, и тот использует их для скачивания образа.
API for external signing of Service Account tokens
Для аутентификации сервисных учётных записей используются ключи. Сейчас Kubernetes сам хранит эти ключи и управляет ими. KEP 740 позволяет внешним специализированным системам, например HSMs и облачным KMS, управлять ими. Подробнее — в обзоре Kubernetes 1.32.
KEP повторно выходит в альфа-версии. Была улучшена функциональность --service-account-max-token-expiration
при использовании внешнего подписчика с --service-account-signing-endpoint
, централизована логика ExtendedSigningDuration
в опциях apiserver, добавлены Plugin и Key Cache, которые позволят интегрироваться с ExternalJWTSigner и введён новый флаг service-account-signing-endpoint
, который позволяет настроить кластер на использование ExternalJWTSigner.
Beta-фичи
ClusterTrustBundles (previously Trust Anchor Sets)
KEP вводит ClusterTrustBundle — новый ресурс в Kubernetes, предназначенный для стандартизированного распространения якорей доверия (CA-сертификатов) внутри кластера. Этот ресурс может быть опционально связан с конкретным издателем сертификатов (signerName), что позволяет использовать RBAC для контроля над изменениями важных цепочек доверия. Также вводится новый тип projected-тома clusterTrustBundle
. Он позволяет монтировать содержимое одного или нескольких ClusterTrustBundle в виде файла с PEM-сертификатами прямо в файловую систему пода, при этом файл автоматически обновляется при изменениях. Такой механизм упрощает управление доверием для кастомных CA и со временем должен заменить текущий способ распространения CA API-сервера. Функциональность включается через переключатели ClusterTrustBundle
и ClusterTrustBundleProjection
.
Stable-фичи
Bound service account token improvements
KEP дополняет генерируемые токены при обработке вызова TokenRequest create
kube-apiserver-функциями, автоматически включая name
и uid
узла, с которым ассоциирован под (через spec.nodeName
).
Так как в этой области кода уже есть под, который содержит имя узла, необходимо пробросить геттер (get
) для объектов Node на уровень хранения TokenRequest. Это нужно, чтобы можно было получать UID узла аналогично тому, как это делается для объектов Pod и Secret.
CLI
Alpha-фичи
Separate kubectl user preferences from cluster configs
KEP вводит новый опциональный конфигурационный файл kuberc, предназначенный для хранения пользовательских настроек утилиты kubectl, отделяя их от данных для подключения к кластерам, которые остаются в kubeconfig. Это позволяет избежать перезаписи настроек при смене kubeconfig. Теперь пользовательские настройки будут применяться независимо от значения флага --kubeconfig
или переменной окружения $KUBECONFIG
.
В альфа-версии подключить kuberc можно с помощью переменной окружения KUBECTL_KUBERC
, установив её в true
. В kuberc можно будет описывать пользовательские алиасы для команд kubectl (секция aliases) и задавать флаги по умолчанию для определённых команд (секция overrides), при этом флаги, явно указанные в командной строке, будут иметь более высокий приоритет.
Пример файла kuberc
apiVersion: kubectl.config.k8s.io/v1alpha1
kind: Preference
aliases:
- name: getdbprod
command: get
prependArgs:
- pods
flags:
- name: labels
default: what=database
- name: namespace
default: us-2-production
overrides:
- command: apply
flags:
- name: server-side
default: "true"
- command: delete
flags:
- name: interactive
default: "true"
Stable-фичи
Add subresource support to kubectl
KEP добавляет новый флаг --subresource=[subresource-name]
к командам kubectl get
и kubectl patch
. Это позволит запрашивать и обновлять подресурсы status, scale и другие, оперируя командами kubectl. Дополнительная информация доступна в обзоре нововведений Kubernetes 1.24.
Планировщик
Alpha-фичи
DRA: Add support for partitionable devices
Изначально Dynamic Resource Allocation (DRA) задумывался для динамического выделения не только целого устройства, но и части его ресурсов (partition). Классический API плагинов устройств поддерживал только статическое разбиение устройства на партиции, DRA же позволил создавать их по требованию, тем самым повысив эффективность использования ресурсов.
С развитием DRA от «классического» до «структурированных параметров» эта возможность динамического разбиения устройств на партиции была утрачена. KEP возвращает эту возможность в рамки «структурированных параметров». Кроме того, он предоставляет примитивы для представления как полных устройств, так и их партиций более компактным способом, чем это возможно сегодня.
Основная идея заключается в том, чтобы позволить вендорам устройств описывать в объекте ResourceSlice все возможные способы разделения физического ресурса на партиции (включая потенциально пересекающиеся по ресурсам, как в случае NVIDIA MIG). Планировщик Kubernetes использует эту информацию, чтобы проверить, доступны ли ресурсы, и предотвратить выделение конфликтующих партиций, при этом само физическое разделение ресурса происходит только после успешного выделения партиции планировщиком по запросу пользователя. Это значительно повышает гибкость работы с дорогим оборудованием и эффективность использования его ресурсов. Также вводится поле PerDeviceNodeSelection
, которое позволяет указывать, на каких узлах доступна каждая конкретная партиция, а не весь ResourceSlice целиком (актуально для сценариев с ресурсами, охватывающими несколько хостов, например multi-host TPU).
Пример
ResourceClaim
для выбора непересекающихся MIG-устройств с конкретного GPU:
apiVersion: resource.k8s.io/v1alpha3
kind: ResourceClaim
metadata:
name: mig-devices
spec:
spec:
devices:
requests:
- name: mig-1g-5gb-0
deviceClassName: mig.nvidia.com
selectors:
- cel:
expression: "device.attributes['gpu.nvidia.com'].profile == '1g.5gb'"
- name: mig-1g-5gb-1
deviceClassName: mig.nvidia.com
selectors:
- cel:
expression: "device.attributes['gpu.nvidia.com'].profile == '1g.5gb'"
- name: mig-2g-10gb
deviceClassName: mig.nvidia.com
selectors:
- cel:
expression: "device.attributes['gpu.nvidia.com'].profile == '2g.10gb'"
- name: mig-3g-20gb
deviceClassName: mig.nvidia.com
selectors:
- cel:
expression: "device.attributes['gpu.nvidia.com'].profile == '3g.20gb'"
constraints:
- requests: []
matchAttribute: "gpu.nvidia.com/parentUUID"
DRA: device taints and tolerations
В DRA драйверы публикуют информацию об устройствах, которыми управляют, в ResourceSlice
. Эта информация используется планировщиком при выборе устройств под нужды пользователей в ResourceClaim
.
Этот KEP позволяет драйверам DRA навешивать taints (ограничения) на устройства — в этом случае новые поды на них не будут планироваться. Кроме того, поды, которые уже работают на устройствах с taint, могут быть автоматически остановлены. Администраторы кластера могут навешивать taint’ы с помощью ResourceSlicePatch.
Также в ResourceClaim
можно добавлять tolerations (допуски) для определённых taint’ов.
Beta-фичи
Asynchronous preemption in the scheduler
В Kubernetes планировщик работает циклически, выбирая поды из очереди и пытаясь найти для них подходящий узел. Если узел занят подами с более низким приоритетом, планировщик может инициировать вытеснение (preemption), чтобы освободить ресурсы для пода с более высоким приоритетом. Процесс вытеснения включает в себя несколько API-вызовов и может занять продолжительное время.
KEP предлагает выполнять эти API-вызовы асинхронно, в отдельной горутине. Так планировщик сможет не ждать завершения вытеснения, а продолжать обработку других подов.
Pop pod from backoffQ when activeQ is empty
В планировщике Kubernetes (kube-scheduler) есть три основные очереди:
activeQ — содержит поды, готовые к планированию.
unschedulableQ — содержит поды, которые планировщик не смог разместить на узлах (например, не нашёл узла с достаточными ресурсами). Они ждут изменений в кластере, например появления нового узла.
backoffQ — содержит поды из unschedulableQ или те, что столкнулись с ошибкой при планировании. Эти поды «сидят на штрафной скамейке» в ожидании следующей попытки планирования, при этом время ожидания (backoff penalty) увеличивается с каждой неудачной попыткой.
Раньше, когда очередь activeQ оказывалась пустой, планировщик простаивал, ожидая поступления новых подов или истечения backoff-периода у подов в backoffQ. Проблема была в том, что в backoffQ при таком сценарии зависали поды, которые потенциально уже можно было бы успешно запланировать, но они ждали окончания своего backoff-периода.
KEP меняет поведение планировщика: когда activeQ пустеет, планировщик больше не простаивает, а выбирает под из backoffQ, у которого время ожидания истекает раньше всего (с учётом приоритета), и отправляет его на (вне)очередную попытку планирования.
Фича выходит сразу в бета-статусе.
Stable-фичи
Take taints/tolerations into consideration when calculating PodTopologySpread skew
KEP улучшает механизм распределения подов по узлам, в том числе skew-процесс. Теперь планировщик может учитывать свойства taints и tolerations при обработке ограничений на распространение топологии. Подробнее — в обзоре Kubernetes 1.25.
Introduce MatchLabelKeys to Pod Affinity and Pod Anti Affinity
KEP вводит дополнительные поля MatchLabelKeys
и MismatchLabelKeys
в PodAffinityTerm
. Это позволит пользователям контролировать применимость PodAffinity
или PodAntiAffinity
для подов в дополнение к существующему LabelSelector. Подробнее — в обзоре Kubernetes 1.29.
Автомасштабирование
Alpha-фичи
Configurable tolerance for Horizontal Pod Autoscalers
Инструмент горизонтального автомасштабирования в Kubernetes (HPA) постоянно подсчитывает необходимое количество реплик в развёртывании. Для этого выбирается одна метрика (или несколько) — например, загрузка процессора. Количество реплик определяется соотношением между ожидаемым и текущим значением этой метрики (подробнее об алгоритме).
Чтобы защититься от незначительных колебаний метрики, в HPA интегрирована область нечувствительности (tolerance), которая по умолчанию составляет 10 %. То есть HPA не будет реагировать на изменения значений метрики, если они меньше 10 %. Проблема в том, что значение tolerance единое для всего кластера, что не очень удобно, поскольку для одних приложений оно может быть слишком велико (например, в кластере из 1000 подов 10 % — это сотни лишних или недостающих копий), а для других — недостаточно.
KEP добавляет поле tolerance
в разделы spec.behavior.scaleUp
и spec.behavior.scaleDown
, чем позволяет настраивать порог чувствительности для каждого HPA. Причём можно задать разные пороги для увеличения (scale-up) и уменьшения (scale-down) количества подов.
Фича обратно совместима: если новое поле не указано, HPA использует глобальный порог.
Windows
Beta-фичи
Support for Direct Service Return (DSR) and overlay networking in Windows kube-proxy
KEP формализует поддержку DSR (Direct Server Return) и оверлей-сетей для Windows-узлов. Обе эти фичи появились в Kubernetes 1.14, поэтому KEP носит ретроактивный характер — он документирует и позволяет закрепить stable-статус за функциональностью, которая появилась некоторое время назад и уже доказала свою работоспособность.
Host network support for Windows pods
В v1.26 была реализована поддержка параметра hostNetwork: true
для обычных Windows-контейнеров. Тем самым обеспечивался функциональный паритет с Linux. Основная мотивация — позволить Windows-подам напрямую использовать сетевое пространство имён хоста. Это решило бы проблемы с нехваткой портов при использовании NodePort/hostPort и упростило бы запуск приложений, требующих множества портов или сетевого доступа до инициализации CNI.
Однако при тестировании этой функции в alpha-статусе containerd при работе в Windows с включённым hostNetwork начал вести себя непредсказуемо, о чём упоминается в Kubernetes v1.33 sneak peek (к сожалению, подробностей найти не удалось).
Устаревшие или удалённые фичи
API Endpoints признан устаревшим
API EndpointSlice признан стабильным в v1.21. Фактически он дублирует функциональность старого API Endpoints, поэтому от того решили отказаться (KEP 4974).
Удаление информации о версии kube-proxy в статусе узла
Поле .status.nodeInfo.kubeProxyVersion
для узлов было признано устаревшим в Kubernetes 1.31. В этой версии оно удаляется окончательно (KEP 4004).
Удаление in-tree драйвера тома gitRepo
Тип тома gitRepo был признан устаревшим в версии 1.11 почти 7 лет назад. С тех пор возник ряд проблем с безопасностью: например, томы gitRepo могли быть использованы для удалённого выполнения кода с root-правами на узлах. В версии 1.33 код драйвера in-tree удалён (KEP 5040).
Удаление поддержки host network для подов Windows
Alpha-версия фичи была выпущена в версии 1.26, однако из-за проблем с поведением containerd и наличия альтернативных решений от неё было решено отказаться. Поддержка была полностью прекращена в версии 1.33 (KEP 3503).
Перед обновлением рекомендуем ознакомиться с changelog.
P. S.
Читайте также в нашем блоге: