Сегодня официально выпустили новую версию Kubernetes — 1.32. Среди главных нововведений — возможность задавать ресурсы на уровне пода, асинхронное вытеснение подов планировщиком, нулевое ожидание (sleep) для PreStop-хуков, новые эндпоинты /statusz и /flagz для ключевых компонентов K8s, более гранулярная авторизация для API kubelet’а, внешнее управление ключами сервисных учётных записей и специальная функция, с помощью которой плагины смогут подсказывать планировщику, когда стоит повторить попытку планирования.

Для подготовки статьи мы использовали информацию из блога Kubernetes, таблицы Kubernetes enhancements tracking, CHANGELOG-1.32, а также конкретные issues, pull requests и Kubernetes Enhancement Proposals (KEPs).

Мы разбили все изменения на следующие разделы:

Внутри каждого раздела упорядочили изменения по уровню их готовности к использованию. Всего в новом релизе 43 изменения. Из них:

  • Alpha — 18 новых функций; 

  • Beta — 12 продолжают улучшаться;

  • Stable — 13 признаны стабильными.

Примечание

Мы сознательно не переводим названия фич на русский. Они в основном состоят из специальной терминологии, с которой инженеры чаще сталкиваются в оригинальной формулировке.

Узлы

Alpha-фичи

Split stdout and stderr log stream of container

#3288; KEP

Сейчас kubelet умеет возвращать определенный поток логов из контейнера, но эта возможность недоступна пользователю. Они могут просматривать только комбинированный лог.

KEP добавляет новое поле Stream в PodLogOptions. Теперь можно указать, какой именно поток логов нужен. В целях обратной совместимости, если это поле не задано, будет возвращаться комбинированный stdout и stderr из контейнера.

Получить поток stderr логов контейнера с помощью kubectl можно следующим образом:

kubectl logs --stream=stderr -c container pod

Пример

Сервис foo постоянно выводит информационные сообщения в stdout, а предупреждения/ошибки — в stderr. В случае проблем владелец сервиса захочет как можно скорее узнать, что происходит. Для этого он обратится к его логам, однако сообщение об ошибке будет сложно заметить, так как из контейнера возвращается объединённый поток логов stdout и stderr, что затрудняет поиск.

Эту проблему легко решить, указав stderr в качестве потока, который будет выводиться.

Pod level resources

#2837; KEP

На данный момент ресурсы в PodSpec (запросы и лимиты) указываются для каждого контейнера отдельно. Планировщик использует совокупность ресурсов, запрошенных всеми контейнерами в поде, чтобы найти подходящий узел для планирования. Далее kubelet реализует эти ограничения, переводя запросы и лимиты в настройки cgroup как для контейнеров, так и для пода (где значения на уровне пода — это совокупность значений на уровне контейнеров, полученных по формуле из KEP#753). В существующем API нельзя задавать ограничения ресурсов на уровне подов. Это особенно проблематично, когда пользователи хотят контролировать общее потребление ресурсов подов без необходимости настраивать ресурсы для каждого отдельного контейнера в нём.

Данный KEP вводит в Pod API два новых поля: pod.spec.resources.requests и pod.spec.resources.limit. Это позволяет задавать запросы и лимиты на уровне пода для нерасширяемых ресурсов (CPU, память и HugePages) в дополнение к существующим настройкам на уровне контейнеров.

Пример

Рассмотрим dev-окружение, которое представляет собой под с несколькими sidecar-контейнерами для инструментов и обычным контейнером для IDE. Для контейнера IDE можно задать лимит памяти, при этом ресурсные потребности контейнеров с инструментами могут меняться в зависимости от того, что делает разработчик.

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: ide
  name: myide
spec:
  resources:
    limits:
      memory: "1024Mi"    # Лимит памяти для всего пода
      cpu: "4"            # Лимит CPU для всего пода
  initContainers:
    - image: debian:buster
      name: shell
      restartPolicy: Always
    - image: first-tool:latest
      name: tool1
      restartPolicy: Always
    - image: second-tool:latest
      name: tool2
      restartPolicy: Always
  containers:
    - name: ide
      image: theia:latest
      resources:
        requests:
          memory: "128Mi"  # Запрос памяти для IDE-контейнера
          cpu: "0.5"       # Запрос ресурсов процессора для IDE-контейнера
        limits:
          memory: "256Mi"  # Лимит памяти для IDE-контейнера
          cpu: "1"         # Лимит CPU для IDE-контейнера

Add Resource Health Status to the Pod Status for Device Plugin and DRA

#4680; KEP

KEP дополняет текущую информацию о состоянии пода новыми данными о здоровье используемых ресурсов. В секцию status спецификации пода добавляется новое поле resourceHealth. Оно будет содержать информацию о здоровье используемых подом ресурсов. resourceHealth будет принимать одно из следующих значений: Healthy, Unhealthy или Unknown.

Плагины устройств и DRA лишены проработанной стратегии обработки сбоев. С ростом спроса на рабочие нагрузки, использующие GPU и другие ресурсы, всё чаще возникают случаи, когда эти ресурсы выходят из строя временно или постоянно. K8s должен обрабатывать такие случаи нативно.

Существующий подход базируется на том, что задачи (job), использующие отказавшее устройство, по возможности завершаются с определённым кодом ошибки. В случае долгосрочных рабочих нагрузок K8s будет пытаться перезапустить задачу, а не перенести её на другое устройство. Контейнер зависнет в цикле crash loop backoff, а информацию о причинах сбоя взять будет неоткуда.

Проброс информации о том, что ресурс нездоров, в статус пода позволит понять, что сбой вызван отказавшим устройством.

KEP повторно выходит как альфа. Изменения теперь доехали до DRA (их можно включить соответствующим переключателем функциональности ResourceHealthStatus). Также для DRA добавлены тесты e2e.

Split L3 Cache Topology Awareness in CPU Manager

#4800; KEP

KEP вводит новую опцию статической политики CPU Manager, prefer-align-cpus-by-uncorecache, которая группирует ресурсы CPU по uncore-кэшу, если это возможно. В результате меняется алгоритм выделения процессоров — добавляется сортировка по uncore-кэшу. В случаях, когда количество запрашиваемых процессоров превышает количество процессоров, доступных в одном uncore-кэше, алгоритм пытается оптимальным образом распределить запрос по процессорам, минимизируя число uncore-кэшей. Распределение с учетом uncore-кэша предпочтительно, но не обязательно.

Мотивация

Основная мотивация этого KEP — уменьшить количество сценариев с «шумными соседями», которые возникают в системах с разделённым uncore-кэшем, доступным как на архитектуре x86, так и на архитектуре ARM. Проблема текущего менеджера процессоров kubelet заключается в том, что тот не знает об архитектуре разделённого uncore-кэша и выделяет процессоры из разных кэшей. Это создает проблему «шумных соседей», когда различные поды/контейнеры совместно используют один и тот же uncore-кэш. Кроме того, для подов, распределенных по разным uncore-кэшам, снижается производительность из-за задержек, связанных с необходимостью доступа к разным uncore-кэшам. Для рабочих нагрузок, чувствительных к задержкам и производительности, минимизация проблемы «шумных соседей» в uncore-кэше может значительно повысить производительность. Например, для рабочей нагрузки HammerDB TPROC-C/My-SQL прирост скорости составил 18%.

Пример

Предположим, что у нас есть процессор AMD EPYC 7303 32C (smt-off, NPS=1) со следующей архитектурой:

NumCores:              32,
NumCPUs:               32,
NumSockets:            1,
NumCPUsPerUncoreCache: 8,
NPS:                   1
UncoreCache Topology: {
    0: {CPUSet: 0-7,    NUMAID: 0,  SocketID: 0},
    1: {CPUSet: 8-15,   NUMAID: 0,  SocketID: 0},
    2: {CPUSet: 16-23,  NUMAID: 0,  SocketID: 0},
    3: {CPUSet: 24-31,  NUMAID: 0,  SocketID: 0}
}

Также у нас есть три контейнера:

  • Container1 запрашивает 2 CPU;

  • Container2 запрашивает 20 CPU;

  • Container3 запрашивает 6 CPU.

При распределении CPU с учётом uncore-кэша Container1 получит 2 CPU из UncoreCache 0 (CPUSet: 1–2; примечание: CPU0 зарезервирован),  Container2 получит 20 CPU из UncoreCache 0, 1 и 2 (CPUSet: 3–6, 8–15, 16–23),  Container3 получит 6 CPU из UncoreCache 3 (CPUSet: 24–29).

DRA: Resource Claim Status with possible standardized network interface data

#4817; KEP

KEP добавляет новое поле Devices в ResourceClaim.Status. Теперь драйверы могут сообщать данные о состоянии для каждого устройства в заявке на ресурс (resource claim). Это повысит наблюдаемость и облегчит поиск и устранение проблем.

В API добавляется новая структура AllocatedDeviceStatus, которая содержит:

  • информацию о запросе ресурса;

  • данные о драйвере;

  • имя пула устройств;

  • имя конкретного устройства;

  • условия (conditions) работы устройства (например, Ready);

  • сетевую информацию (IP-адреса, MAC-адрес).

Мотивация

Сегодня при настройке устройства в поде/контейнере состояние и характеристики устройства, заданные на этапе конфигурирования, остаются невидимыми. Отсутствие этой информации создаёт проблемы для пользователей и разработчиков при диагностике, проверке конфигурации и интеграции выделенных ресурсов в сервисы более высокого уровня. Эта информация пригодилась бы в окружениях, где необходимо подстраивать конфигурацию под конкретное устройство.

Для некоторых типов устройств, например сетевых интерфейсов, информация о параметрах выделенных ресурсов особенно полезна. Например, сообщение об имени интерфейса, MAC-адресе и IP-адресе сетевых интерфейсов в статусе ResourceClaim может существенно помочь в настройке и управлении сетевыми сервисами, а также в отладке проблем, связанных с сетью.

Fine grained Kubelet API authorization

#2862; KEP

В настоящее время в API kubelet применяется слишком грубая схема авторизации. Например, чтобы просто прочитать статус здоровья узла (/healthz) или список подов, требуются такие же права доступа, как и для выполнения команд внутри контейнера.

KEP-2862 предлагает более гранулярную систему авторизации для API kubelet. Вместо использования единого разрешения nodes/proxy для всех операций вводятся специальные эндпоинты:

  • nodes/healthz — для проверки здоровья;

  • nodes/pods — для просмотра подов;

  • nodes/configz — для конфигурации.

Новое поведение включается переключателем функциональности KubeletFineGrainedAuthz (в альфа-версии по умолчанию установлен в False). При включённом переключателе kubelet сначала попытается авторизовать запрос через новые эндпоинты. Если авторизация не прошла, он вернётся к старому способу через субресурс proxy.

Allow zero value for Sleep Action of PreStop Hook

#4818; KEP

KEP 3960 представил действие sleep для PreStop-хуков жизненного цикла контейнеров. Однако для него нельзя установить ноль в качестве допустимого значения. Этот KEP исправляет ситуацию.

Мотивация

В настоящее время попытка создать контейнер с хуком PreStop со значением sleep 0 секунд приводит к ошибке следующего вида:

Invalid value: 0: must be greater than 0 and less than terminationGracePeriodSeconds (30)

Однако в некоторых случаях требуется установить длительность sleep в ноль: например, когда хук PreStop задаётся для проверки ресурса, но пауза на самом деле не требуется. Пример: хук PreStop добавляется по умолчанию, если он явно не задан пользователем. Чтобы не вызывать true, автор комментария пробовал задавать sleep 0 для хука PreStop, однако это приводило к ошибке.

KEP реализует переключатель функциональности PodLifecycleSleepActionAllowZero (по умолчанию выключен). При его включении метод validateSleepAction будет разрешать значения больше или равные нулю в качестве допустимых значений sleep.

Add CPUManager policy option to restrict reservedSystemCPUs to system daemons and interrupt processing

#4540; KEP

KEP добавляет новую опцию strict-cpu-reservation в статическую политику CPU Manager. Она гарантирует, что процесоры, зарезервированные для системы (reservedSystemCPUs), будут использоваться только ею (то есть поды burstable и best-effort не смогут получить к ним доступ, как это было ранее).

Пример

Предположим, что имеется следующая конфигурация kubelet:

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
featureGates:
  ...
  CPUManagerPolicyOptions: true
  CPUManagerPolicyAlphaOptions: true
cpuManagerPolicy: static
cpuManagerPolicyOptions:
  strict-cpu-reservation: "true"
reservedSystemCPUs: "0,32,1,33,16,48"
...

Тогда при выключенной опции strict-cpu-reservation все процессоры окажутся в defaultCpuSet:

 # cat /var/lib/kubelet/cpu_manager_state
{"policyName":"static","defaultCpuSet":"0-79","checksum":1241370203}

При включённой опции strict-cpu-reservation в defaultCpuSet окажутся только незарезервированные процессоры:

# cat /var/lib/kubelet/cpu_manager_state
{"policyName":"static","defaultCpuSet":"2-15,17-31,34-47,49-63","checksum":4141502832}

Beta-фичи

Add support for a drop-in kubelet configuration directory

#3983; KEP

KEP добавляет поддержку drop-in-директории для конфигов kubelet. Её можно задать с помощью флага --config-dir, например /etc/kubernetes/kubelet.conf.d. Напомним, что конфигурационные файлы обрабатываются в алфавитно-цифровом порядке. По умолчанию флаг будет пустым, и если его не указать, то поддержка drop-in не будет включена. Синтаксис в файлах конфигурации должен быть такой же, как в kubelet.conf.

Allow almost all printable ASCII characters in environment variables

#4369; KEP

KEP смягчает правила валидации имён env-переменных при проверке create-запросов к API. Теперь валидацию успешно проходят все ASCII-символы в диапазоне 32–126, кроме «=». Подробнее смотрите в обзоре Kubernetes 1.30.

DRA: structured parameters

#4381; KEP

Параметры ресурсов в DRA непрозрачны для Kubernetes. Они интерпретируются контроллером драйвера DRA (для размещения claim’ов) и kubelet-плагином драйвера DRA (для конфигурирования ресурсов на узле). При планировании пода kube-scheduler и контроллер(ы) драйвера DRA, обрабатывающий(ие) claim’ы для пода, обмениваются данными через apiserver, обновляя объект PodSchedulingContext. В итоге все активные claim’ы учитываются и под планируется на узел.

Такой подход создаёт проблемы для Cluster Autoscaler (CA) или любого контроллера более высокого уровня, которому необходимо принимать решения для группы подов, например для планировщика заданий. Он не может смоделировать эффект аллокации или реаллокации claim’ов с течением времени. Только у драйверов DRA есть необходимая для этого информация.

KEP «Динамическое распределение ресурсов с помощью структурированных параметров» (4381) решает эту проблему. Подробности — в нашем обзоре Kubernetes 1.30.

Stable-фичи

Memory Manager

#1769; KEP

Менеджер памяти ­— компонент в экосистеме kubelet, предназначенный для гарантированного выделения памяти (и HugePages) для подов в классе Guaranteed QoS. Предлагается несколько стратегий выделения. Первая из них, single-NUMA, предназначена для высокопроизводительных и чувствительных к производительности приложений. Вторая, multi-NUMA, дополняет общий дизайн и позволяет преодолеть ситуацию, с которой невозможно справиться с помощью стратегии single-NUMA, а именно: когда объём памяти, требуемый подом, превышает ёмкость одного узла NUMA, гарантированная память распределяется между несколькими узлами NUMA с помощью стратегии multi-NUMA.

Support to size memory backed volumes

#1967; KEP

Ранее размер для томов emptyDir, которые хранятся в оперативной памяти (tmpfs), по умолчанию составлял 50% от памяти Linux-хоста. Это вызывало ряд сложностей, которые и решил KEP 1967. Теперь размер таких томов по умолчанию равен объёму выделяемой поду памяти. Кроме того, это значение можно уменьшить.

Improved multi-numa alignment in Topology Manager

#3545; KEP

KEP оптимизирует работу менеджера топологий в Kubernetes. Теперь тот может выбирать физически близкие NUMA-узлы при размещении рабочих нагрузок. Это важно для приложений, для которых критичны низкая задержка и высокая производительность. Подробности — в обзоре Kubernetes 1.26.

Приложения

Beta-фичи

Job API managed-by mechanism

#4368; KEP

Поле managedBy в спецификации задачи (job) позволяет делегировать её синхронизацию внешнему контроллеру.

В рамках проекта Kueue ведётся работа над мультикластерным диспетчером задач MultiKueue. В MultiKueue, построенном по архитектуре «менеджер — воркер», пользователь заводит задачу в управляющем кластере, а её зеркальная копия создаётся и выполняется в одном из кластеров-воркеров. Контроллер Kueue доносит обновления статуса задачи из воркера до управляющего кластера — они отражаются в статусе оригинальной задачи, созданной пользователем.

Такой рабочий процесс нуждается в механизме, который позволял бы отключать основной контроллер задач и передавать синхронизацию статусов контроллеру Kueue.

Stable-фичи

Add job creation timestamp to job annotations

#4026; KEP

KEP добавляет новую аннотацию batch.kubernetes.io/cronjob-scheduled-timestamp. Она используется для записи исходной (ожидаемой) временно́й метки создания задачи, когда эта задача является частью CronJob.

Add Pod Index Label for StatefulSets and Indexed Jobs

#4017; KEP

KEP добавляет лейбл индекса для индексированных задач и StatefulSet’ов. Подробнее — в обзоре нововведений Kubernetes 1.28.

Auto remove PVCs created by StatefulSet

#1847; KEP

KEP вводит необязательное поле .spec.persistentVolumeClaimRetentionPolicy для контроля за тем, когда и как PVC удаляются во время жизненного цикла StatefulSet.

Хранилище

Beta-фичи

Support recovery from volume expansion failure

#1790; KEP

С помощью PVC можно расширять ёмкость хранилища, запрашивая у провайдера том нужного объёма. Иногда пользователи запрашивают больше, чем может выдать провайдер (например, запросить 500 ГБ, когда доступно только 100 ГБ. При этом контроллер, который отвечает за расширение томов, хотя и получает отказ, продолжает повторять запросы. 

KEP позволяет отменить запрос на расширение, если тот ещё не завершён или некорректен, и повторить его, указав меньший объём тома с помощью параметра pvc.Spec.Resources. Подробнее см. в обзоре Kubernetes 1.23.

VolumeGroupSnapshot

#3476; KEP

KEP дополняет API Kubernetes, позволяя снимать согласованные снапшоты сразу с нескольких томов. Для этого вводятся новые CRD VolumeGroupSnapshot, VolumeGroupSnapshotContent и VolumeGroupSnapshotClass

Для объединения нескольких PVC в VolumeGroupSnapshot на них навешивается соответствующий лейбл, который затем указывается в селекторе labelSelector в VolumeGroupSnapshot, если драйвер CSI поддерживает возможность CREATE_DELETE_GET_VOLUME_GROUP_SNAPSHOT. Подробнее о логике работы можно почитать в разделе Proposal KEP’а.

Speed up recursive SELinux label change

#1710; KEP

На хостах с SELinux в принудительном режиме (enforcing mode) пользователи одного контейнера не могут получить доступ к другому контейнеру или к хосту. Это обеспечивается за счёт контекста, который уникален для каждого контейнера, и лейблов, которые назначаются каждому файлу в каждом томе. Злоумышленник, которому удалось выбраться из контейнера, не сможет получить доступ к данным в других контейнерах, потому что у каждого контейнера свои тома со своими лейблами.

Однако такая защита может усложнять жизнь пользователям, которые разворачивают кластеры на базе SELinux: при запуске нового контейнера запускается рекурсивное переназначение лейблов для всех файлов в томе, привязанном к поду. Если том большой, процесс переназначения может затянуться.

Новая функция позволяет пропустить этап переназначения лейблов и тем самым ускорить монтирование тома. Подробности смотрите в обзоре Kubernetes 1.25.

Сеть

Alpha-фичи

Relaxed DNS search string validation

#4427; KEP

Сейчас в K8s проверка строки поиска в dnsConfig.searches ведётся в соответствии с RFC-1123, который определяет ограничения для имён хостов. По ряду причин эта проверка слишком строга для использования в dnsConfig.searches.

Во-первых, хотя большинство имён DNS идентифицируют хосты, есть типы записей, например SRV, которые этого не делают. Для них не совсем ясно, применяются ли ограничения на имена хостов. Например, в разделе 2.3.1 RFC-1035 указывается, что лучше придерживаться валидных имён хостов, но также говорится, что лейблы должны соответствовать требованиям к именам хостов.

На практике легаси-рабочие нагрузки иногда включают символ подчёркивания «_» в имена DNS, и обычно это не вызывает проблем у DNS-серверов.

Во-вторых, пользователи могут захотеть установить в dnsConfig.searches символ точки «.», чтобы избежать ненужных DNS-поисков внутренних доменных имён Kubernetes.

KEP ослабляет проверки для строк поиска DNS. Эти значения можно будет указывать в поле searches в dnsConfig, и поды смогут правильно разрешать короткие имена в случаях, когда строка поиска содержит символ подчёркивания или точку. Вводится переключатель функциональности RelaxedDNSSearchValidation (по умолчанию выключен). При его включении будет использоваться новая логика проверки DNS-имён, которая в дополнение к существующей позволяет использовать символ подчёркивания «_» в любом месте, где в настоящее время разрешено использовать дефис «-», а также разрешает использовать точку «.».

Stable-фичи

Make Kubernetes aware of the LoadBalancer behaviour

#1860; KEP

KEP добавляет новое поле (ipMode) в поле loadBalancer в статусе сервиса. С его помощью kube-proxy будет решать, когда не привязывать внешний IP LoadBalancer’а к узлу как в режиме ipvs, так и в режиме iptables. Значение VIP по умолчанию будет означать обычное поведение, если оно не задано для инстанса. А Proxy будет пускать трафик через LoadBalancer. Подробнее — в обзоре Kubernetes 1.29.

API

Alpha-фичи

Mutating Admission Policies

#3962; KEP

KEP развивает идеи, заложенные в KEP-3488 (см. обзор K8s 1.30), и добавляет новый механизм для изменения (мутации) объектов перед их сохранением в etcd — Mutating Admission Policies, основанные на CEL (Common Expression Language). Они станут альтернативой Mutating Admission Webhooks, которые сейчас являются основным способом выполнения мутаций.

Аналогично полю validations в ValidatingAdmissionPolicy добавляется поле mutations в MutatingAdmissionPolicy. Оно позволяет задавать список мутаций, которые будут применяться к конкретным ресурсам. Каждое поле mutations содержит CEL-выражение, результатом вычисления которого будет «частично заполненный» (то есть содержащий только необходимые изменения) объект, готовый для дальнейшего Server Side Apply. Наконец, этот объект объединяется с исходным объектом запроса.

CBOR Serializer

#4222; KEP

KEP добавляет в Kubernetes новый CBOR-сериализатор. CBOR станет альтернативой JSON при сериализации ресурсов в телах запросов и ответов и заменит JSON в apiextensions-apiserver при сериализации кастомных ресурсов.

Мотивация

При запросе к API Kubernetes различные представления ресурса могут многократно кодироваться и декодироваться:

  • клиентом (кодировать тело запроса, декодировать тело ответа);

  • сервером (декодировать тело запроса, декодировать данные из хранилища, кодировать тело ответа, кодировать данные в хранилище).

Kubernetes долгое время поддерживал формат Protobuf, который гораздо экономнее JSON или YAML в плане ресурсов процессора и операций с heap-памятью. Переход на Protobuf повысил эффективность кластеров Kubernetes, а пропускная способность API выросла.

CustomResourceDefinitions (CRDs) в Kubernetes применяются для декларативного расширения API. В отличие от нативных типов, сериализация кастомных ресурсов в Protobuf нетривиальна. В результате кастомные ресурсы с большим количеством объектов и высоким трафиком сильно проигрывают нативным ресурсам K8s по эффективности. Бенчмарки показывают, что кодирование и декодирование кастомных ресурсов и динамических клиентов можно ускорить в 8 раз и в 2 раза соответственно, если использовать CBOR (объём операций с heap-памятью также значительно сократится).

Beta-фичи

Allow informers for getting a stream of data instead of chunking

#3157; KEP

В некоторых случаях API-сервер Kubernetes страдает от взрывного роста потребления памяти. Эта проблема особенно очевидна в больших кластерах, где всего несколько LIST-запросов могут привести к серьёзным сбоям. Неконтролируемое и неограниченное потребление памяти серверами влияет не только на кластеры, работающие в режиме HA, но и на другие программы на узле.

KEP реализует запросы WATCH в качестве альтернативы запросам LIST. Чтобы снизить потребление памяти при получении списка данных и сделать его более предсказуемым, авторы предлагают использовать потоковую передачу из watch-cache вместо подкачки из etcd. В первую очередь изменения затронут информеры, поскольку они обычно являются наиболее активными пользователями LIST-запросов. Основная идея в том, чтобы использовать стандартную механику WATCH-запросов для получения потока отдельных объектов, но применять её для LIST'ов.

Stable-фичи

#4358; KEP

KEP добавляет поддержку селекторов полей для кастомных ресурсов. В CustomResourceDefinition появляется секция selectableFields:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: selector.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      selectableFields:
      - jsonPath: .spec.color 
      - jsonPath: .spec.size 
      additionalPrinterColumns:
      - jsonPath: .spec.color
        name: Color
        type: string
      - jsonPath: .spec.size
        name: Size
        type: string

Retry Generate Name

#4420; KEP

KEP вносит ряд изменений в apiserver, которые предписывают повторять попытки генерации новых имён в случае, если create-запрос с использованием generateName заканчивается ошибкой «конфликт имён». Подробнее — в обзоре K8s 1.30.

Аутентификация

Alpha-фичи

API for external signing of Service Account tokens

#740; KEP

Для аутентификации сервисных учётных записей используются ключи. Сейчас Kubernetes сам хранит эти ключи и управляет ими. KEP 740 позволяет внешним специализированным системам, например HSMs и облачным KMS, управлять этими ключами.

Мотивация

Простота ротации. В настоящее время kube-apiserver загружает ключи учётных записей при старте процесса, и ключи остаются неизменными в течение всего времени жизни процесса. Таким образом, чтобы произвести ротацию ключей, необходимо перезапустить kube-apiserver. Внешнее управление ключами устраняет необходимость перезапуска.

Повышенная безопасность. kube-apiserver загружает ключи сервисных учётных записей из файла на диске. Это означает, что любой человек с привилегированным доступом к конфигурации / файловой системе kube-apiserver может получить к ним доступ. Внешний подписывающий механизм устраняет этот риск.

Детали реализации

В рамках KEP будет создан новый gRPC API (ExternalJWTSigner) для взаимодействия kube-apiserver с внешними сервисами аутентификации. Этот API определяет методы для:

  • подписи JWT — SignJWTRequest и SignJWTResponse: kube-apiserver отправляет запрос на подпись payload-токена, а внешний сервис возвращает подпись и сериализованный заголовок;

  • получения публичных ключей — FetchKeysRequest и FetchKeysResponse: kube-apiserver запрашивает список доверенных публичных ключей для подписи токенов.

Для интеграции с различными внешними системами используются плагины. Плагин выступает в роли клиента gRPC API и взаимодействует с конкретным сервисом аутентификации.

Handling undecryptable resources

#3926; KEP

KEP реализует механизм удаления средствами API повреждённых зашифрованных ресурсов Kubernetes.

Шифрование  ресурсов API «в состоянии покоя» (at rest) уже давно используется в Kubernetes. Увы, периодически возникают ситуации, когда из-за неправильного обращения или сбоев во внешней системе кластерное шифрование выходит из строя.

Если какой-либо один объект определённого типа ресурса не удаётся расшифровать, перечисление ресурсов этого типа в префиксе пути, содержащем этот объект, всегда заканчивается неудачей, даже если остальные экземпляры ресурсов доступны. Удалить такой повреждённый объект через API Kubernetes невозможно. Администратору приходится вручную удалять данные из etcd.

KEP 3926 предлагает способ выявления ресурсов, которые не удаётся расшифровать или декодировать в объект, и вводит новую  DeleteOption — IgnoreStoreReadErrorWithClusterBreakingPotential, которая позволяет удалить ресурс, даже если его данные не могут быть прочитаны.

Beta-фичи

Authorize with Field and Label Selectors

#4601; KEP

KEP предлагает новый механизм авторизации в Kubernetes на базе селекторов для управления доступом к ресурсам.

Запросы List, Watch и DeleteCollection смогут использовать селекторы полей и лейблов для более точной фильтрации ресурсов, которые возвращаются в ответ на запрос.

Атрибуты авторизации получат упрощённый доступ к параметрам запроса для селекторов полей и лейблов. Селекторы не будут включаться в атрибуты авторизации для запросов, для которых селектор поля не имеет смысла, например для запросов с методами Create или Update.

API-объект SubjectAccessReview теперь будет использовать разные сериализации для различных случаев использования, таких как вызовы вебхуков и авторизационные проверки от клиентов. Это повысит совместимость и упростит обработку запросов.

Node Authorizer будет модифицирован, чтобы авторизовать только тех клиентов, которые могут перечислять и наблюдать поды с селекторами полей, содержащими spec.nodeName=$nodeName.

Определённые изменения коснутся и CEL Authorizer — он будет поддерживать использование селекторов полей и лейблов для авторизационных проверок, делая управление доступом более гибким.

Only allow anonymous auth for configured endpoints

#4633; KEP

В настоящее время анонимная аутентификация в Kubernetes включена по умолчанию. Это означает, что запросы без токена аутентификации автоматически обрабатываются как анонимные. Однако администраторы не могут настраивать, к каким именно ресурсам разрешён анонимный доступ, а могут лишь включить или выключить это поведение с помощью логического флага --anonymous-auth (по умолчанию он установлен в true).

KEP реализует механизм, который позволяет пользователям настраивать, к каким эндпоинтам возможен анонимный доступ, и отключать анонимную аутентификацию для всех остальных эндпоинтов. Подробнее см. обзор Kubernetes 1.31.

Structured Authentication Config

#3331; KEP

KEP от «Фланта» реализует структурированную конфигурацию для аутентификации, которая обладает рядом весомых преимуществ по сравнению с традиционным подходом. Он поддерживает любые JWT-совместимые токены, динамическое изменение конфигурации, одновременную работу с несколькими провайдерами аутентификации и Common Expression Language. Дополнительная информация о KEP — в заметке. Подробнее о предпосылках появления новой аутентификации и о том, как она работает, можно узнать из статьи одного из авторов KEP Максима Набоких.

Stable-фичи

Structured Authorization Configuration

#3221; KEP

Сегодня kube-apiserver позволяет настраивать цепочку авторизации с помощью набора флагов командной строки вида --authorization-*. При этом администраторы кластеров могут включить в цепочку авторизации только один вебхук, используя флаг --authorization-modes. В текущей реализации нет возможности указать несколько вебхуков для авторизации пользователей, но KEP позволяет передавать apiserver структурированный файл конфигурации. С его помощью можно решить проблемы, которые ранее были нерешаемы. Подробности — в обзоре Kubernetes 1.29.

Bound service account token improvements 

#4193; KEP

KEP дополняет генерируемые токены при обработке вызова TokenRequest create kube-apiserver-функциями, автоматически включая name и uid узла, с которым ассоциирован под (через spec.nodeName).

Так как в этой области кода уже есть под, который содержит имя узла, необходимо пробросить геттер (get) для объектов Node на уровень хранения TokenRequest. Это нужно, чтобы можно было получать UID узла аналогично тому, как это делается для объектов Pod и Secret.

CLI

Stable-фичи

Custom profile in kubectl debug

#4292; KEP

KEP добавляет кастомное профилирование поверх предопределённых профилей в команде kubectl debug, избавляя от необходимости открывать issue для очередного «нового» флага. Подробнее — в обзоре Kubernetes 1.30.

Планировщик

Alpha-фичи

Asynchronous preemption in the scheduler

#4832; KEP

В Kubernetes планировщик работает циклически, выбирая поды из очереди и пытаясь найти для них подходящий узел. Если узел занят подами с более низким приоритетом, планировщик может инициировать вытеснение (preemption), чтобы освободить ресурсы для пода с более высоким приоритетом. Процесс вытеснения включает в себя несколько API-вызовов и может занять продолжительное время.

KEP предлагает выполнять эти API-вызовы асинхронно, в отдельной горутине. Так планировщик сможет не ждать завершения вытеснения, а продолжать обработку других подов.

Beta-фичи

Per-plugin callback functions for accurate requeueing in kube-scheduler

#4247; KEP

KEP развивает идеи KEP 3063 (см. обзор K8s 1.27). В Kubernetes различные плагины проверяют, соответствует ли под требованиям узла — наличие ресурсов, соответствие лейблам узла и так далее. Если под не проходит проверку, плагин сообщает об этом планировщику. Раньше планировщик просто ставил под в очередь на повторную попытку через некоторое время (с использованием backoff, то есть интервал между повторными попытками экспоненциально увеличивался). KEP-4247 вводит функцию QueueingHint, которая позволяет плагинам давать планировщику подсказки о том, когда стоит повторить попытку планирования.

Пример

Плагин NodeAffinity проверяет соответствие пода лейблам узла. Предположим, что под требует некий лейбл key: value, однако подходящего узла с таким лейблом нет. В этом случае плагин вернет QueueSkip, то есть попытка планирования не имеет смысла. Когда в кластере появится узел с лейблом key: value, функция QueueingHint вернет Queue — попытка планирования может быть успешной — и планировщик попробует запланировать под на этот узел.

Инструментирование

Alpha-фичи

Statusz for Kubernetes Components

#4827; KEP

KEP добавляет observability-эндпоинт /statusz в ключевые компоненты Kubernetes (kube-apiserver, kubelet, kube-controller-manager, kube-scheduler, kube-proxy). Он будет выводить важную информацию о состоянии компонента — версию, сведения о сборке, используемой версии Go, совместимости с API Kubernetes, полезные ссылки на другие важные эндпоинты (/healthz, /livez, /readyz и /metrics).

Доступ к /statusz будут иметь члены существующей RBAC-роли system:monitoring. Изначально данные будут выдаваться в формате простого текста. В будущем может быть добавлена поддержка структурированных форматов вроде JSON.

Чтобы открыть доступ к эндпоинту /statusz kubelet'а, дополните роль system:monitoring следующим образом:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:monitoring 
rules:
# existing rules
- apiGroups: [""]
  resources: ["nodes/statusz"]
  verbs: ["get"]

Flagz for Kubernetes Components

#4828; KEP

По аналогии с предыдущим KEP в ключевые компоненты Kubernetes добавляется эндпоинт /flagz. Он будет возвращать информацию о флагах, с которыми был запущен компонент. Изначально данные (имя флага и его значение) будут выдаваться в простом текстовом виде. В будущем может быть добавлена поддержка структурированных форматов. Доступ к /flagz будут иметь члены RBAC-роли system:monitoring.

Windows

Alpha-фичи

Windows CPU and Memory Affinity

#4885; KEP

KEP добавляет поддержку менеджеров CPU, памяти и топологии в kubelet для Windows. Основная задача KEP — адаптировать существующую логику менеджеров ресурсов к особенностям Windows.

Windows node gracefully shutdown

#4802; KEP

KEP добавляет поддержку корректного завершения работы (graceful shutdown) подов на узлах Windows при выключении самого узла. Сейчас при выключении узла Windows поды просто убиваются без возможности подготовиться к завершению работы. Осведомлённость kubelet об отключении Windows-узла позволит инициировать процедуру корректного завершения работы подов с сохранением элементов жизненного цикла (типа хуков PreStop).

Устаревшие или удалённые фичи

Отказ от старой реализации DRA

KEP 3063 в Kubernetes 1.26 ввёл динамическое распределение ресурсов (DRA).

В Kubernetes v1.32 подход к DRA был существенно переработан. Код, связанный с оригинальной реализацией, будет удалён. KEP 4381 станет «новой» базовой функциональностью.

Решение об изменении существующего подхода было принято из-за его несовместимости с автомасштабированием кластера, поскольку доступность ресурсов была непрозрачной, что усложняло принятие решений как для автомасштабировщика кластера, так и для контроллеров. Новая модель структурированных параметров заменяет эту функциональность. Теперь Kubernetes сможет более предсказуемо обрабатывать требования к оборудованию и заявки на ресурсы.

Удаление типов томов gitRepo

Тип тома gitRepo признан устаревшим и будет удалён в K8s 1.32. Способствовала этому уязвимость CVE-2024-10220: Выполнение произвольных команд через том gitRepo (см. issue #128885).

Удаления в API

Удалена версия API flowcontrol.apiserver.k8s.io/v1beta3 для FlowSchema и PriorityLevelConfiguration. Рекомендуем отредактировать существующие манифесты и перенастроить клиентское ПО на использование flowcontrol.apiserver.k8s.io/v1, доступной с версии K8s 1.29. Все существующие персистентные объекты доступны через новый API. Из заметных изменений: поле PriorityLevelConfiguration spec.limited.nominalConcurrencyShares теперь по умолчанию принимает значение 30 только в случае, если оно не задано, а явно указанное значение 0 не изменяется на 30.

Перед обновлением рекомендуем ознакомиться с changelog.

P. S.

Читайте также в нашем блоге:

Комментарии (0)