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

Для подготовки статьи мы использовали информацию из блога [2] Kubernetes, таблицы Kubernetes enhancements tracking [3], CHANGELOG-1.32 [4], а также конкретные issues, pull requests и Kubernetes Enhancement Proposals (KEPs).
Мы разбили все изменения на следующие разделы:
узлы [5];
приложения [6];
хранилище [7];
сеть [8];
API [9];
аутентификация [10];
CLI [11];
планировщик [12];
инструментирование [13];
Windows [14];
Внутри каждого раздела упорядочили изменения по уровню их готовности к использованию. Всего в новом релизе 43 изменения. Из них:
Alpha — 18 новых функций;
Beta — 12 продолжают улучшаться;
Stable — 13 признаны стабильными.
Примечание
Мы сознательно не переводим названия фич на русский. Они в основном состоят из специальной терминологии, с которой инженеры чаще сталкиваются в оригинальной формулировке.
Сейчас kubelet умеет [18] возвращать определенный поток логов из контейнера, но эта возможность недоступна пользователю. Они могут просматривать только комбинированный лог.
KEP добавляет новое поле Stream в PodLogOptions. Теперь можно указать, какой именно поток логов нужен. В целях обратной совместимости, если это поле не задано, будет возвращаться комбинированный stdout и stderr из контейнера.
Получить поток stderr логов контейнера с помощью kubectl можно следующим образом:
kubectl logs --stream=stderr -c container pod
Сервис foo постоянно выводит информационные сообщения в stdout, а предупреждения/ошибки — в stderr. В случае проблем владелец сервиса захочет как можно скорее узнать, что происходит. Для этого он обратится к его логам, однако сообщение об ошибке будет сложно заметить, так как из контейнера возвращается объединённый поток логов stdout и stderr, что затрудняет поиск.
Эту проблему легко решить, указав stderr в качестве потока, который будет выводиться.
На данный момент ресурсы в PodSpec (запросы и лимиты) указываются для каждого контейнера отдельно. Планировщик использует совокупность ресурсов, запрошенных всеми контейнерами в поде, чтобы найти подходящий узел для планирования. Далее kubelet реализует эти ограничения, переводя запросы и лимиты в настройки cgroup как для контейнеров, так и для пода (где значения на уровне пода — это совокупность значений на уровне контейнеров, полученных по формуле из KEP#753 [21]). В существующем 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-контейнера
KEP дополняет текущую информацию о состоянии пода новыми данными о здоровье используемых ресурсов. В секцию status спецификации пода добавляется новое поле resourceHealth. Оно будет содержать информацию о здоровье используемых подом ресурсов. resourceHealth будет принимать одно из следующих значений: Healthy, Unhealthy или Unknown.
Плагины устройств и DRA лишены проработанной стратегии обработки сбоев. С ростом спроса на рабочие нагрузки, использующие GPU и другие ресурсы, всё чаще возникают случаи, когда эти ресурсы выходят из строя временно или постоянно. K8s должен обрабатывать такие случаи нативно.
Существующий подход базируется на том, что задачи (job), использующие отказавшее устройство, по возможности завершаются с определённым кодом ошибки. В случае долгосрочных рабочих нагрузок K8s будет пытаться перезапустить задачу, а не перенести её на другое устройство. Контейнер зависнет в цикле crash loop backoff, а информацию о причинах сбоя взять будет неоткуда.
Проброс информации о том, что ресурс нездоров, в статус пода позволит понять, что сбой вызван отказавшим устройством.
KEP повторно выходит как альфа. Изменения теперь доехали до DRA (их можно включить соответствующим переключателем функциональности ResourceHealthStatus). Также для DRA добавлены тесты e2e.
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% [26].
Предположим, что у нас есть процессор 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).
KEP добавляет новое поле Devices в ResourceClaim.Status. Теперь драйверы могут сообщать данные о состоянии для каждого устройства в заявке на ресурс (resource claim). Это повысит наблюдаемость и облегчит поиск и устранение проблем.
В API добавляется новая структура AllocatedDeviceStatus [29], которая содержит:
информацию о запросе ресурса;
данные о драйвере;
имя пула устройств;
имя конкретного устройства;
условия (conditions) работы устройства (например, Ready);
сетевую информацию (IP-адреса, MAC-адрес).
Сегодня при настройке устройства в поде/контейнере состояние и характеристики устройства, заданные на этапе конфигурирования, остаются невидимыми. Отсутствие этой информации создаёт проблемы для пользователей и разработчиков при диагностике, проверке конфигурации и интеграции выделенных ресурсов в сервисы более высокого уровня. Эта информация пригодилась бы в окружениях, где необходимо подстраивать конфигурацию под конкретное устройство.
Для некоторых типов устройств, например сетевых интерфейсов, информация о параметрах выделенных ресурсов особенно полезна. Например, сообщение об имени интерфейса, MAC-адресе и IP-адресе сетевых интерфейсов в статусе ResourceClaim может существенно помочь в настройке и управлении сетевыми сервисами, а также в отладке проблем, связанных с сетью.
В настоящее время в API kubelet применяется слишком грубая схема авторизации. Например, чтобы просто прочитать статус здоровья узла (/healthz) или список подов, требуются такие же права доступа, как и для выполнения команд внутри контейнера.
KEP-2862 предлагает более гранулярную систему авторизации для API kubelet. Вместо использования единого разрешения nodes/proxy для всех операций вводятся специальные эндпоинты:
nodes/healthz — для проверки здоровья;
nodes/pods — для просмотра подов;
nodes/configz — для конфигурации.
Новое поведение включается переключателем функциональности KubeletFineGrainedAuthz (в альфа-версии по умолчанию установлен в False). При включённом переключателе kubelet сначала попытается авторизовать запрос через новые эндпоинты. Если авторизация не прошла, он вернётся к старому способу через субресурс proxy.
KEP 3960 [34] представил действие sleep для PreStop-хуков жизненного цикла контейнеров. Однако для него нельзя установить ноль в качестве допустимого значения. Этот KEP исправляет ситуацию.
В настоящее время попытка создать контейнер с хуком PreStop со значением sleep 0 секунд приводит к ошибке следующего вида:
Invalid value: 0: must be greater than 0 and less than terminationGracePeriodSeconds (30)
Однако в некоторых случаях требуется установить длительность sleep в ноль: например, когда хук PreStop задаётся для проверки ресурса, но пауза на самом деле не требуется. Пример [35]: хук PreStop добавляется по умолчанию, если он явно не задан пользователем. Чтобы не вызывать true, автор комментария пробовал задавать sleep 0 для хука PreStop, однако это приводило к ошибке.
KEP реализует переключатель функциональности PodLifecycleSleepActionAllowZero (по умолчанию выключен). При его включении метод validateSleepAction будет разрешать значения больше или равные нулю в качестве допустимых значений sleep.
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}
KEP добавляет поддержку drop-in-директории для конфигов kubelet. Её можно задать с помощью флага --config-dir, например /etc/kubernetes/kubelet.conf.d. Напомним, что конфигурационные файлы обрабатываются в алфавитно-цифровом порядке. По умолчанию флаг будет пустым, и если его не указать, то поддержка drop-in не будет включена. Синтаксис в файлах конфигурации должен быть такой же, как в kubelet.conf.
KEP смягчает правила валидации имён env-переменных при проверке create-запросов к API. Теперь валидацию успешно проходят все ASCII-символы в диапазоне 32–126, кроме «=». Подробнее смотрите в обзоре Kubernetes 1.30 [42].
Параметры ресурсов в DRA непрозрачны для Kubernetes. Они интерпретируются контроллером драйвера DRA (для размещения claim’ов) и kubelet-плагином драйвера DRA (для конфигурирования ресурсов на узле). При планировании пода kube-scheduler и контроллер(ы) драйвера DRA, обрабатывающий(ие) claim’ы для пода, обмениваются данными через apiserver, обновляя объект PodSchedulingContext. В итоге все активные claim’ы учитываются и под планируется на узел.
Такой подход создаёт проблемы для Cluster Autoscaler (CA) или любого контроллера более высокого уровня, которому необходимо принимать решения для группы подов, например для планировщика заданий. Он не может смоделировать эффект аллокации или реаллокации claim’ов с течением времени. Только у драйверов DRA есть необходимая для этого информация.
KEP «Динамическое распределение ресурсов с помощью структурированных параметров» (4381 [45]) решает эту проблему. Подробности — в нашем обзоре Kubernetes 1.30 [42].
Менеджер памяти — компонент в экосистеме kubelet, предназначенный для гарантированного выделения памяти (и HugePages) для подов в классе Guaranteed QoS. Предлагается несколько стратегий выделения. Первая из них, single-NUMA, предназначена для высокопроизводительных и чувствительных к производительности приложений. Вторая, multi-NUMA, дополняет общий дизайн и позволяет преодолеть ситуацию, с которой невозможно справиться с помощью стратегии single-NUMA, а именно: когда объём памяти, требуемый подом, превышает ёмкость одного узла NUMA, гарантированная память распределяется между несколькими узлами NUMA с помощью стратегии multi-NUMA.
Ранее размер для томов emptyDir, которые хранятся в оперативной памяти (tmpfs), по умолчанию составлял 50% от памяти Linux-хоста. Это вызывало ряд сложностей, которые и решил KEP 1967. Теперь размер таких томов по умолчанию равен объёму выделяемой поду памяти. Кроме того, это значение можно уменьшить.
KEP оптимизирует работу менеджера топологий в Kubernetes. Теперь тот может выбирать физически близкие NUMA-узлы при размещении рабочих нагрузок. Это важно для приложений, для которых критичны низкая задержка и высокая производительность. Подробности — в обзоре Kubernetes 1.26 [52].
Поле managedBy в спецификации задачи (job) позволяет делегировать её синхронизацию внешнему контроллеру.
В рамках проекта Kueue [55] ведётся работа над мультикластерным диспетчером задач MultiKueue [56]. В MultiKueue, построенном по архитектуре «менеджер — воркер», пользователь заводит задачу в управляющем кластере, а её зеркальная копия создаётся и выполняется в одном из кластеров-воркеров. Контроллер Kueue доносит обновления статуса задачи из воркера до управляющего кластера — они отражаются в статусе оригинальной задачи, созданной пользователем.
Такой рабочий процесс нуждается в механизме, который позволял бы отключать основной контроллер задач и передавать синхронизацию статусов контроллеру Kueue.
KEP добавляет новую аннотацию batch.kubernetes.io/cronjob-scheduled-timestamp. Она используется для записи исходной (ожидаемой) временно́й метки создания задачи, когда эта задача является частью CronJob.
KEP добавляет лейбл индекса для индексированных задач и StatefulSet’ов. Подробнее — в обзоре нововведений Kubernetes 1.28 [61].
KEP вводит необязательное поле .spec.persistentVolumeClaimRetentionPolicy для контроля за тем, когда и как PVC удаляются во время жизненного цикла StatefulSet.
С помощью PVC можно расширять ёмкость хранилища, запрашивая у провайдера том нужного объёма. Иногда пользователи запрашивают больше, чем может выдать провайдер (например, запросить 500 ГБ, когда доступно только 100 ГБ. При этом контроллер, который отвечает за расширение томов, хотя и получает отказ, продолжает повторять запросы.
KEP позволяет отменить запрос на расширение, если тот ещё не завершён или некорректен, и повторить его, указав меньший объём тома с помощью параметра pvc.Spec.Resources. Подробнее см. в обзоре Kubernetes 1.23 [66].
KEP дополняет API Kubernetes, позволяя снимать согласованные снапшоты сразу с нескольких томов. Для этого вводятся новые CRD VolumeGroupSnapshot, VolumeGroupSnapshotContent и VolumeGroupSnapshotClass.
Для объединения нескольких PVC в VolumeGroupSnapshot на них навешивается соответствующий лейбл, который затем указывается в селекторе labelSelector в VolumeGroupSnapshot, если драйвер CSI поддерживает возможность CREATE_DELETE_GET_VOLUME_GROUP_SNAPSHOT. Подробнее о логике работы можно почитать в разделе Proposal [69] KEP’а.
На хостах с SELinux в принудительном режиме (enforcing mode) пользователи одного контейнера не могут получить доступ к другому контейнеру или к хосту. Это обеспечивается за счёт контекста, который уникален для каждого контейнера, и лейблов, которые назначаются каждому файлу в каждом томе. Злоумышленник, которому удалось выбраться из контейнера, не сможет получить доступ к данным в других контейнерах, потому что у каждого контейнера свои тома со своими лейблами.
Однако такая защита может усложнять жизнь пользователям, которые разворачивают кластеры на базе SELinux: при запуске нового контейнера запускается рекурсивное переназначение лейблов для всех файлов в томе, привязанном к поду. Если том большой, процесс переназначения может затянуться.
Новая функция позволяет пропустить этап переназначения лейблов и тем самым ускорить монтирование тома. Подробности смотрите в обзоре Kubernetes 1.25 [72].
Сейчас в K8s проверка строки поиска в dnsConfig.searches ведётся в соответствии с RFC-1123 [75], который определяет ограничения для имён хостов. По ряду причин эта проверка слишком строга для использования в dnsConfig.searches.
Во-первых, хотя большинство имён DNS идентифицируют хосты, есть типы записей, например SRV, которые этого не делают. Для них не совсем ясно, применяются ли ограничения на имена хостов. Например, в разделе 2.3.1 RFC-1035 [76] указывается, что лучше придерживаться валидных имён хостов, но также говорится, что лейблы должны соответствовать требованиям к именам хостов.
На практике легаси-рабочие нагрузки иногда включают символ подчёркивания «_» в имена DNS, и обычно это не вызывает проблем у DNS-серверов.
Во-вторых, пользователи могут захотеть установить в dnsConfig.searches символ точки «.», чтобы избежать ненужных DNS-поисков внутренних доменных имён Kubernetes.
KEP ослабляет проверки для строк поиска DNS. Эти значения можно будет указывать в поле searches в dnsConfig, и поды смогут правильно разрешать короткие имена в случаях, когда строка поиска содержит символ подчёркивания или точку. Вводится переключатель функциональности RelaxedDNSSearchValidation (по умолчанию выключен). При его включении будет использоваться новая логика проверки DNS-имён, которая в дополнение к существующей позволяет использовать символ подчёркивания «_» в любом месте, где в настоящее время разрешено использовать дефис «-», а также разрешает использовать точку «.».
KEP добавляет новое поле (ipMode) в поле loadBalancer в статусе сервиса. С его помощью kube-proxy будет решать, когда не привязывать внешний IP LoadBalancer’а к узлу как в режиме ipvs, так и в режиме iptables. Значение VIP по умолчанию будет означать обычное поведение, если оно не задано для инстанса. А Proxy будет пускать трафик через LoadBalancer. Подробнее — в обзоре Kubernetes 1.29 [79].
KEP развивает идеи, заложенные в KEP-3488 [82] (см. обзор K8s 1.30 [42]), и добавляет новый механизм для изменения (мутации) объектов перед их сохранением в etcd — Mutating Admission Policies, основанные на CEL (Common Expression Language). Они станут альтернативой Mutating Admission Webhooks, которые сейчас являются основным способом выполнения мутаций.
Аналогично полю validations в ValidatingAdmissionPolicy добавляется поле mutations в MutatingAdmissionPolicy. Оно позволяет задавать список мутаций, которые будут применяться к конкретным ресурсам. Каждое поле mutations содержит CEL-выражение, результатом вычисления которого будет «частично заполненный» (то есть содержащий только необходимые изменения) объект, готовый для дальнейшего Server Side Apply. Наконец, этот объект объединяется с исходным объектом запроса.
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-памятью также значительно сократится).
В некоторых случаях API-сервер Kubernetes страдает от взрывного роста потребления памяти. Эта проблема особенно очевидна в больших кластерах, где всего несколько LIST-запросов могут привести к серьёзным сбоям. Неконтролируемое и неограниченное потребление памяти серверами влияет не только на кластеры, работающие в режиме HA, но и на другие программы на узле.
KEP реализует запросы WATCH в качестве альтернативы запросам LIST. Чтобы снизить потребление памяти при получении списка данных и сделать его более предсказуемым, авторы предлагают использовать потоковую передачу из watch-cache вместо подкачки из etcd. В первую очередь изменения затронут информеры, поскольку они обычно являются наиболее активными пользователями LIST-запросов. Основная идея в том, чтобы использовать стандартную механику WATCH-запросов для получения потока отдельных объектов, но применять её для LIST'ов.
KEP добавляет поддержку селекторов полей [89] для кастомных ресурсов. В 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
KEP вносит ряд изменений в apiserver, которые предписывают повторять попытки генерации новых имён в случае, если create-запрос с использованием generateName заканчивается ошибкой «конфликт имён». Подробнее — в обзоре K8s 1.30 [42].
Для аутентификации сервисных учётных записей используются ключи. Сейчас 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 и взаимодействует с конкретным сервисом аутентификации.
KEP реализует механизм удаления средствами API повреждённых зашифрованных ресурсов Kubernetes.
Шифрование ресурсов API «в состоянии покоя» (at rest) уже давно используется в Kubernetes. Увы, периодически возникают ситуации, когда из-за неправильного обращения или сбоев во внешней системе кластерное шифрование выходит из строя.
Если какой-либо один объект определённого типа ресурса не удаётся расшифровать, перечисление ресурсов этого типа в префиксе пути, содержащем этот объект, всегда заканчивается неудачей, даже если остальные экземпляры ресурсов доступны. Удалить такой повреждённый объект через API Kubernetes невозможно. Администратору приходится вручную удалять данные из etcd.
KEP 3926 предлагает способ выявления ресурсов, которые не удаётся расшифровать или декодировать в объект, и вводит новую DeleteOption — IgnoreStoreReadErrorWithClusterBreakingPotential, которая позволяет удалить ресурс, даже если его данные не могут быть прочитаны.
KEP предлагает новый механизм авторизации в Kubernetes на базе селекторов для управления доступом к ресурсам.
Запросы List, Watch и DeleteCollection смогут использовать селекторы полей и лейблов для более точной фильтрации ресурсов, которые возвращаются в ответ на запрос.
Атрибуты авторизации получат упрощённый доступ к параметрам запроса для селекторов полей и лейблов. Селекторы не будут включаться в атрибуты авторизации для запросов, для которых селектор поля не имеет смысла, например для запросов с методами Create или Update.
API-объект SubjectAccessReview теперь будет использовать разные сериализации для различных случаев использования, таких как вызовы вебхуков и авторизационные проверки от клиентов. Это повысит совместимость и упростит обработку запросов.
Node Authorizer будет модифицирован, чтобы авторизовать только тех клиентов, которые могут перечислять и наблюдать поды с селекторами полей, содержащими spec.nodeName=$nodeName.
Определённые изменения коснутся и CEL Authorizer — он будет поддерживать использование селекторов полей и лейблов для авторизационных проверок, делая управление доступом более гибким.
В настоящее время анонимная аутентификация в Kubernetes включена по умолчанию. Это означает, что запросы без токена аутентификации автоматически обрабатываются как анонимные. Однако администраторы не могут настраивать, к каким именно ресурсам разрешён анонимный доступ, а могут лишь включить или выключить это поведение с помощью логического флага --anonymous-auth (по умолчанию он установлен в true).
KEP реализует механизм, который позволяет пользователям настраивать, к каким эндпоинтам возможен анонимный доступ, и отключать анонимную аутентификацию для всех остальных эндпоинтов. Подробнее см. обзор Kubernetes 1.31 [100].
KEP от «Фланта» реализует структурированную конфигурацию для аутентификации, которая обладает рядом весомых преимуществ по сравнению с традиционным подходом. Он поддерживает любые JWT-совместимые токены, динамическое изменение конфигурации, одновременную работу с несколькими провайдерами аутентификации и Common Expression Language. Дополнительная информация о KEP — в заметке [103]. Подробнее о предпосылках появления новой аутентификации и о том, как она работает, можно узнать из статьи [104] одного из авторов KEP Максима Набоких.
Сегодня kube-apiserver позволяет настраивать цепочку авторизации с помощью набора флагов командной строки вида --authorization-*. При этом администраторы кластеров могут включить в цепочку авторизации только один вебхук, используя флаг --authorization-modes. В текущей реализации нет возможности указать несколько вебхуков для авторизации пользователей, но KEP позволяет передавать apiserver структурированный файл конфигурации. С его помощью можно решить проблемы, которые ранее были нерешаемы. Подробности — в обзоре Kubernetes 1.29 [79].
KEP дополняет генерируемые токены при обработке вызова TokenRequest create kube-apiserver-функциями, автоматически включая name и uid узла, с которым ассоциирован под (через spec.nodeName).
Так как в этой области кода уже есть под, который содержит имя узла, необходимо пробросить геттер (get) для объектов Node на уровень хранения TokenRequest. Это нужно, чтобы можно было получать UID узла аналогично тому, как это делается для объектов Pod и Secret.
KEP добавляет кастомное профилирование поверх предопределённых профилей в команде kubectl debug, избавляя от необходимости открывать issue для очередного «нового» флага. Подробнее — в обзоре Kubernetes 1.30 [42].
В Kubernetes планировщик работает циклически, выбирая поды из очереди и пытаясь найти для них подходящий узел. Если узел занят подами с более низким приоритетом, планировщик может инициировать вытеснение (preemption), чтобы освободить ресурсы для пода с более высоким приоритетом. Процесс вытеснения включает в себя несколько API-вызовов и может занять продолжительное время.
KEP предлагает выполнять эти API-вызовы асинхронно, в отдельной горутине. Так планировщик сможет не ждать завершения вытеснения, а продолжать обработку других подов.
KEP развивает идеи KEP 3063 [115] (см. обзор K8s 1.27 [116]). В Kubernetes различные плагины проверяют, соответствует ли под требованиям узла — наличие ресурсов, соответствие лейблам узла и так далее. Если под не проходит проверку, плагин сообщает об этом планировщику. Раньше планировщик просто ставил под в очередь на повторную попытку через некоторое время (с использованием backoff, то есть интервал между повторными попытками экспоненциально увеличивался). KEP-4247 вводит функцию QueueingHint, которая позволяет плагинам давать планировщику подсказки о том, когда стоит повторить попытку планирования.
Плагин NodeAffinity проверяет соответствие пода лейблам узла. Предположим, что под требует некий лейбл key: value, однако подходящего узла с таким лейблом нет. В этом случае плагин вернет QueueSkip, то есть попытка планирования не имеет смысла. Когда в кластере появится узел с лейблом key: value, функция QueueingHint вернет Queue — попытка планирования может быть успешной — и планировщик попробует запланировать под на этот узел.
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 [119]. Изначально данные будут выдаваться в формате простого текста. В будущем может быть добавлена поддержка структурированных форматов вроде 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"]
По аналогии с предыдущим KEP в ключевые компоненты Kubernetes добавляется эндпоинт /flagz. Он будет возвращать информацию о флагах, с которыми был запущен компонент. Изначально данные (имя флага и его значение) будут выдаваться в простом текстовом виде. В будущем может быть добавлена поддержка структурированных форматов. Доступ к /flagz будут иметь члены RBAC-роли system:monitoring.
KEP добавляет поддержку менеджеров CPU, памяти и топологии в kubelet для Windows. Основная задача KEP — адаптировать существующую логику менеджеров ресурсов к особенностям Windows.
KEP добавляет поддержку корректного завершения работы (graceful shutdown) подов на узлах Windows при выключении самого узла. Сейчас при выключении узла Windows поды просто убиваются без возможности подготовиться к завершению работы. Осведомлённость kubelet об отключении Windows-узла позволит инициировать процедуру корректного завершения работы подов с сохранением элементов жизненного цикла (типа хуков PreStop).
KEP 3063 [52] в Kubernetes 1.26 ввёл динамическое распределение ресурсов (DRA).
В Kubernetes v1.32 подход к DRA был существенно переработан. Код, связанный с оригинальной реализацией, будет удалён. KEP 4381 станет «новой» базовой функциональностью.
Решение об изменении существующего подхода было принято из-за его несовместимости с автомасштабированием кластера, поскольку доступность ресурсов была непрозрачной, что усложняло принятие решений как для автомасштабировщика кластера, так и для контроллеров. Новая модель структурированных параметров заменяет эту функциональность. Теперь Kubernetes сможет более предсказуемо обрабатывать требования к оборудованию и заявки на ресурсы.
Тип тома gitRepo признан устаревшим и будет удалён в K8s 1.32. Способствовала этому уязвимость CVE-2024-10220: Выполнение произвольных команд через том gitRepo [126] (см. issue #128885 [127]).
Удалена версия 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 [4].
Читайте также в нашем блоге:
Автор: kubelet
Источник [133]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/obzor/404982
Ссылки в тексте:
[1] выпустили: https://kubernetes.io/blog/2024/12/11/kubernetes-v1-32-release/
[2] блога: https://kubernetes.io/blog/
[3] Kubernetes enhancements tracking: https://github.com/orgs/kubernetes/projects/195/
[4] CHANGELOG-1.32: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.32.md
[5] узлы: #%D0%A3%D0%B7%D0%BB%D1%8B
[6] приложения: #%D0%9F%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F
[7] хранилище: #%D0%A5%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D0%B5
[8] сеть: #%D0%A1%D0%B5%D1%82%D1%8C
[9] API: #API
[10] аутентификация: #%D0%90%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F
[11] CLI: #CLI
[12] планировщик: #%D0%9F%D0%BB%D0%B0%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA
[13] инструментирование: #%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
[14] Windows: #Windows
[15] устаревшие и удалённые фичи: #%D0%A3%D1%81%D1%82%D0%B0%D1%80%D0%B5%D0%B2%D1%88%D0%B8%D0%B5%20%D0%B8%20%D1%83%D0%B4%D0%B0%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5%20%D1%84%D0%B8%D1%87%D0%B8
[16] #3288: https://github.com/kubernetes/enhancements/issues/3288
[17] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3288-separate-stdout-from-stderr
[18] умеет: https://github.com/kubernetes/kubernetes/blob/69cabe778bccfc5f4fa9b6788c9def005e7d959d/pkg/kubelet/kuberuntime/logs/logs.go#L281
[19] #2837: https://github.com/kubernetes/enhancements/issues/2837
[20] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2837-pod-level-resource-spec/README.md
[21] KEP#753: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/753-sidecar-containers/README.md#resources-calculation-for-scheduling-and-pod-admission
[22] #4680: https://github.com/kubernetes/enhancements/issues/4680
[23] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4680-add-resource-health-to-pod-status/README.md
[24] #4800: https://github.com/kubernetes/enhancements/issues/4800
[25] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4800-cpumanager-split-uncorecache/README.md
[26] составил 18%: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4800-cpumanager-split-uncorecache/README.md#motivation
[27] #4817: https://github.com/kubernetes/enhancements/issues/4817
[28] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4817-resource-claim-device-status/README.md
[29] AllocatedDeviceStatus: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4817-resource-claim-device-status/README.md#api---resourceclaimstatus
[30] #2862: https://github.com/kubernetes/enhancements/issues/2862
[31] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2862-fine-grained-kubelet-authz/README.md
[32] #4818: https://github.com/kubernetes/enhancements/issues/4818
[33] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4818-allow-zero-value-for-sleep-action-of-prestop-hook/README.md
[34] KEP 3960: https://habr.com/ru/companies/flant/articles/779700/#3960
[35] Пример: https://github.com/kubernetes/enhancements/issues/3960#issuecomment-2208556397
[36] #4540: https://github.com/kubernetes/enhancements/issues/4540
[37] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4540-strict-cpu-reservation/README.md
[38] #3983: https://github.com/kubernetes/enhancements/issues/3983
[39] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3983-drop-in-configuration
[40] #4369: https://github.com/kubernetes/enhancements/issues/4369
[41] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4369-allow-special-characters-environment-variable/README.md
[42] в обзоре Kubernetes 1.30: https://habr.com/ru/companies/flant/articles/808055/
[43] #4381: https://github.com/kubernetes/enhancements/issues/4381
[44] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4381-dra-structured-parameters
[45] 4381: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4381-dra-structured-parameters/README.md
[46] #1769: https://github.com/kubernetes/enhancements/issues/1769
[47] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1769-memory-manager
[48] #1967: https://github.com/kubernetes/enhancements/issues/1967
[49] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1967-size-memory-backed-volumes
[50] #3545: https://github.com/kubernetes/enhancements/issues/3545
[51] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3545-improved-multi-numa-alignment/README.md
[52] в обзоре Kubernetes 1.26: https://habr.com/ru/companies/flant/articles/703372/
[53] #4368: https://github.com/kubernetes/enhancements/issues/4368
[54] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/4368-support-managed-by-for-batch-jobs
[55] Kueue: https://github.com/kubernetes-sigs/kueue/tree/main
[56] MultiKueue: https://github.com/kubernetes-sigs/kueue/tree/main/keps/693-multikueue
[57] #4026: https://github.com/kubernetes/enhancements/issues/4026
[58] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-apps/4026-crojob-scheduled-timestamp-annotation/README.md
[59] #4017: https://github.com/kubernetes/enhancements/issues/4017
[60] KEP: https://github.com/danielvegamyhre/enhancements/blob/0d2686f50920f29636bbd1c2690772800067e609/keps/sig-apps/4017-pod-index-label/README.md
[61] в обзоре нововведений Kubernetes 1.28: https://habr.com/ru/companies/flant/articles/754398/
[62] #1847: https://github.com/kubernetes/enhancements/issues/1847
[63] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/1847-autoremove-statefulset-pvcs
[64] #1790: https://github.com/kubernetes/enhancements/issues/1790
[65] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/1790-recover-resize-failure/README.md
[66] в обзоре Kubernetes 1.23: https://habr.com/ru/companies/flant/articles/593735/
[67] #3476: https://github.com/kubernetes/enhancements/issues/3476
[68] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3476-volume-group-snapshot/README.md
[69] Proposal: https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3476-volume-group-snapshot/README.md#proposal-for-volumegroupsnapshot
[70] #1710: https://github.com/kubernetes/enhancements/issues/1710
[71] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1710-selinux-relabeling
[72] в обзоре Kubernetes 1.25: https://habr.com/ru/companies/flant/articles/684142/
[73] #4427: https://github.com/kubernetes/enhancements/issues/4427
[74] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/4427-relaxed-dns-search-validation
[75] RFC-1123: https://datatracker.ietf.org/doc/html/rfc1123
[76] 2.3.1 RFC-1035: https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1
[77] #1860: https://github.com/kubernetes/enhancements/issues/1860
[78] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/1860-kube-proxy-IP-node-binding
[79] в обзоре Kubernetes 1.29: https://habr.com/ru/companies/flant/articles/779700/
[80] #3962: https://github.com/kubernetes/enhancements/issues/3962
[81] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3962-mutating-admission-policies
[82] KEP-3488: https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/3488-cel-admission-control/README.md
[83] #4222: https://github.com/kubernetes/enhancements/issues/4222
[84] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/4222-cbor-serializer
[85] #3157: https://github.com/kubernetes/enhancements/issues/3157
[86] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/3157-watch-list/README.md
[87] #4358: https://github.com/kubernetes/enhancements/issues/4358
[88] KEP: https://github.com/kubernetes/enhancements/pull/4359
[89] селекторов полей: https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/field-selectors/
[90] #4420: https://github.com/kubernetes/enhancements/issues/4420
[91] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/4420-retry-generate-name/README.md
[92] #740: https://github.com/kubernetes/enhancements/issues/740
[93] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/740-service-account-external-signing
[94] #3926: https://github.com/kubernetes/enhancements/issues/3926
[95] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3926-handling-undecryptable-resources
[96] #4601: https://github.com/kubernetes/enhancements/issues/4601
[97] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/4601-authorize-with-selectors
[98] #4633: https://github.com/kubernetes/enhancements/issues/4633
[99] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/4633-anonymous-auth-configurable-endpoints
[100] обзор Kubernetes 1.31: https://habr.com/ru/companies/flant/articles/835626/
[101] #3331: https://github.com/kubernetes/enhancements/issues/3331
[102] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3331-structured-authentication-configuration
[103] в заметке: https://habr.com/ru/companies/flant/news/747712/
[104] из статьи: https://habr.com/ru/companies/flant/articles/854914/
[105] #3221: https://github.com/kubernetes/enhancements/issues/3221
[106] KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/3221-structured-authorization-configuration
[107] #4193: https://github.com/kubernetes/enhancements/issues/4193
[108] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/4193-bound-service-account-token-improvements/
[109] #4292: https://github.com/kubernetes/enhancements/issues/4292
[110] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/4292-kubectl-debug-custom-profile/README.md
[111] #4832: https://github.com/kubernetes/enhancements/issues/4832
[112] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4832-async-preemption/README.md
[113] #4247: https://github.com/kubernetes/enhancements/issues/4247
[114] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4247-queueinghint/README.md
[115] 3063: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation
[116] обзор K8s 1.27: https://habr.com/ru/companies/flant/articles/728040/
[117] #4827: https://github.com/kubernetes/enhancements/issues/4827
[118] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/4827-component-statusz/README.md
[119] system:monitoring: https://github.com/kubernetes/kubernetes/blob/release-1.31/staging/src/k8s.io/apiserver/pkg/authentication/user/user.go#L73
[120] #4828: https://github.com/kubernetes/enhancements/issues/4828
[121] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/4828-component-flagz/README.md
[122] #4885: https://github.com/kubernetes/enhancements/issues/4885
[123] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-windows/4885-windows-cpu-and-memory-affinity/README.md
[124] #4802: https://github.com/kubernetes/enhancements/issues/4802
[125] KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-windows/4802-windows-node-shutdown/README.md
[126] CVE-2024-10220: Выполнение произвольных команд через том gitRepo: https://nvd.nist.gov/vuln/detail/CVE-2024-10220
[127] #128885: https://github.com/kubernetes/kubernetes/issues/128885
[128] Kubernetes 1.31: новый VolumeSource, эмуляция старых версий и настройка анонимного доступа к эндпоинтам: https://goo.su/835626k
[129] Kubernetes 1.30: структурированные параметры для DRA, рекурсивное монтирование read-only-томов и другие фичи: https://goo.su/808055k
[130] Kubernetes 1.29: бэкенд на nftables, изменение атрибутов тома и другие фичи: https://goo.su/779700k
[131] Kubernetes 1.28: прощание с Google, оптимизация работы с контейнерами и задачами, новый KEP от «Фланта»: https://goo.su/754398k
[132] Kubernetes 1.27: обзор нововведений: https://goo.su/728040k
[133] Источник: https://habr.com/ru/companies/flant/articles/864988/?utm_source=habrahabr&utm_medium=rss&utm_campaign=864988
Нажмите здесь для печати.