Сегодня официально выпустили новую версию Kubernetes — 1.31. Среди главных нововведений — VolumeSource
, поддерживающий OCI-образы и/или OCI-артефакты и поле SupplementalGroupsPolicy
для контроля дополнительных групп, которые присоединяются к первому процессу в контейнере, а также флаг --emulation-version
для эмулирования возможностей предыдущих версий Kubernetes и механизм, который позволяет пользователям настраивать, к каким эндпоинтам возможен анонимный доступ.
Для подготовки статьи мы использовали информацию из таблицы Kubernetes enhancements tracking, CHANGELOG-1.31, а также конкретные Issues, Pull Requests и Kubernetes Enhancement Proposals (KEPs).
Мы разбили все изменения на следующие разделы:
Внутри каждого раздела упорядочили изменения по уровню их готовности к использованию. Всего в новом релизе 45 изменений. Из них:
-
Alpha — 12 новых функций;
-
Beta — 21 продолжают улучшаться;
-
Stable — 11 признаны стабильными.
Примечание
Мы сознательно не переводим названия фич на русский. Они в основном состоят из специальной терминологии, с которой инженеры чаще сталкиваются в оригинальной формулировке.
Узлы
Alpha-фичи
DRA: control plane controller ("classic DRA") и DRA: structured parameters
#3063; KEP 3063 и #4381; KEP 4381
Изначально KEP 3063 привнёс динамическое распределение ресурсов в Kubernetes 1.26. При этом KEP «Динамическое распределение ресурсов с помощью структурированных параметров» (4381) выступил в качестве расширения — реализовал дополнительную функциональность (структурированные параметры). Теперь роли поменялись местами: 4381 определяет базовую функциональность, а 3063 становится необязательным расширением. Подробности — в нашем обзоре Kubernetes 1.30.
С момента предыдущего релиза KEP 3063 и KEP 4381 были доработаны с учётом обратной связи от сообщества и тестирования. Разработчики доработали API для управления динамическим распределением ресурсов и добавили новые структурированные параметры для более точного управления перераспределением ресурсов, а также улучшили документацию и добавили примеры использования.
New Static Policy Proposal — Spread HT across physical CPUs
KEP реализует новую статическую политику менеджера CPU, которая распределяет гиперпотоки по физическим ядрам. В ней изменили алгоритм сортировки процессоров: сначала идёт сортировка по сокету, затем — по процессорам без учёта физических ядер. Подробнее о политиках управления CPU на узлах — в документации.
Мотивация
Опция full-pcpus-only
статической политики решает проблему совместного использования разными контейнерами одних и тех же физических ядер. Речь идёт о так называемой проблеме «шумных соседей», когда одно приложение или под использует чрезмерное количество ресурсов, например CPU, памяти, дискового ввода-вывода. Это может негативно сказываться на производительности других приложений или подов, работающих на том же узле.
Опция distribute-cpus-across-numa
распределяет процессоры по NUMA-узлам, чтобы гарантировать, что ни один воркер не страдает от недостатка NUMA больше других, улучшая общую производительность приложений такого типа.
Два этих варианта и поведение по умолчанию не могут удовлетворить требования некоторых приложений, которым необходимо использовать преимущества кэша L2. В этом случае гиперпотоки необходимо распределять по физическим ядрам без учёта NUMA. Идея в том, что одно физическое ядро с двумя приложениями не будет занято постоянно. Поэтому можно воспользоваться преимуществами кэша CPU и повысить производительность этих приложений.
KEP добавляет опцию spread-physical-cpus-preferred
в статическую политику CPU Manager. После её активации менеджер будет стараться максимально эффективно распределить процессоры между физическими узлами.
Пример. Оптимизация производительности базы данных
Инстансы БД запускаются в Kubernetes, по умолчанию используется статическая политика. Однако производительность инстансов БД нестабильна. В изначальном варианте нагруженный инстанс получал два cpu
из одного физического ядра. При этом некоторые инстансы простаивали. Исследование показало, что ограничивающим фактором являлся кэш процессора. Если гиперпотоки распределять по разным физическим ядрам, инстансы смогут использовать больше кэша процессора, и производительность значительно повысится.
VolumeSource: OCI Artifact and/or Image
KEP добавляет в Kubernetes новый VolumeSource
, поддерживающий OCI-образы и/или OCI-артефакты. Теперь пользователи смогут упаковывать файлы и шарить их в контейнерах пода, не включая в основной образ. Это позволит снизить уязвимости и упростит создание образов.
Поддержка образов OCI уже достаточно отлажена в Kubernetes и CRI. Этот KEP расширяет её на OCI-артефакты. Теперь пользователи смогут пробрасывать новые медиатипы (media types) в рантаймы контейнеров, пользуясь всеми преимуществами, реализованными в подходе OCI (кастомное управление жизненным циклом, валидация, безопасность и так далее).
Пример 1
DevOps-инженеры смогут упаковывать и распространять бинарные артефакты, используя стандарты спецификации образов и дистрибутивов OCI, и монтировать их непосредственно в поды Kubernetes, оптимизируя CI/CD-пайплайны. Плюсы такого подхода — небольшой набор базовых образов, которые можно использовать, прикрепляя к ним CI/CD-артефакты.
Пример 2
Специалисты по Data Science, инженеры MLOps или разработчики ИИ смогут монтировать файлы с весами языковых моделей / ML-моделей в поды, не включая их в образ модели-сервера. Упаковка в объекты OCI позволит воспользоваться преимуществами инициативы OCI и обеспечит эффективное развёртывание модели. Спецификации/содержание моделей будут отделены от исполняемых файлов, которые их обрабатывают.
Fine-grained SupplementalGroups control
KEP предлагает ввести в API новое поле SupplementalGroupsPolicy
. Оно позволит контролировать, какие дополнительные группы навешиваются на первый процесс в контейнере, следуя «принципу наименьшей неожиданности». Администраторы кластера смогут настраивать политики безопасности на защиту SupplementalGroupsPolicy
в кластере, что позволит устранять проблему неожиданного обхода SupplementalGroups
(см. ниже). Также пользователи смогут определять, какие группы на самом деле навешены на процессы в контейнерах.
В Kubernetes присоединение дополнительных групп к процессам в контейнере осуществляется на двух уровнях: на уровне образа OCI и на уровне API Kubernetes.
В спецификации образов OCI конфигурация образа OCI config.User
(зеркальное отражение директивы USER
в Dockerfile) определяется следующим образом.
Имя пользователя или UID, которое является специфической для платформы структурой, позволяющей контролировать, от имени какого пользователя запускается процесс. Это значение используется по умолчанию, если оно не указано при создании контейнера. Для систем на базе Linux допустимы все следующие варианты: user, uid, user:group, uid:gid, uid:group, user:gid
. Если group/gid
не указана, применяется группа по умолчанию и дополнительные группы данного user/uid
в /etc/passwd
из контейнера.
На уровне API Kubernetes за это отвечает PodSecurityContext.{RunAsUser, RunAsGroup, SupplementalGroups}
. Этот API был разработан для переопределения конфигурации config.User
образов OCI. Однако в текущей реализации, как описано в #112879, даже если в манифесте определены обе RunAsGroup
, членство в группах из образа контейнера для UID привязывается к процессу контейнера. Такое поведение явно расходится со спецификацией OCI, особенно со следующим предложением из раздела о конфигурации образов:
Если
group/gid
не указана, применяется группа по умолчанию и дополнительные группы данногоuser/uid
в/etc/passwd
контейнера.
Как описано в #112879, такое поведение не документировано должным образом и не известно большинству администраторов и пользователей Kubernetes. Более того, в некоторых случаях оно может привести к проблемам с безопасностью.
Пример
# Dockerfile
FROM ubuntu:22.04
# Генерируется запись в /etc/group --> "group-in-image:x:50000:alice"
RUN groupadd -g 50000 group-in-image
&& useradd -m -u 1000 alice
&& gpasswd -a alice group-in-image
USER alice
spec:
# Здесь переопределяется директива
# - USER из Dockerfile выше с помощью runAsUser и runAsGroup с "1000:1000"
# - и установки supplementalGroups.
# В результате gid'ы, заданные в образе (/etc/group)
# НЕ должны навешиваться на процесс в контейнере
# поскольку runAsGroup задает gid явно.
securityContext: { runAsUser:1000, runAsGroup:1000, supplementalGroups:[60000]}
containers:
# Ожидаемый результат: "uid=1000(alice) gid=1000(alice) groups=1000(alice),60000"
# Примечание: "group-in-image" не включен в ожидаемый вывод,
# поскольку группы, заданные в /etc/group, не должны навешиваться,
# когда gid'ы задаются с помощью runAsGroup.
- image: the-image-above
sh: ["id"]
Результат:
uid=1000(alice) gid=1000(alice) groups=1000(alice),50000(group-in-image),60000
Add Resource Health Status to the Pod Status for Device Plugin and DRA
KEP дополняет текущую информацию о состоянии пода новыми данными о здоровье используемых ресурсов. Пользователи и системы мониторинга получат более полное представление о работе подов и смогут быстрее выявлять проблемы, связанные с ресурсами.
Плагины устройств и DRA лишены проработанной стратегии обработки сбоев. С ростом спроса на рабочие нагрузки, использующие GPU и другие ресурсы, всё чаще возникают случаи, когда эти ресурсы выходят из строя временно или постоянно. K8s должен обрабатывать такие случаи нативно.
Существующий подход базируется на том, что задачи (job), использующие отказавшее устройство, по возможности завершаются с определённым кодом ошибки. В случае долгосрочных рабочих нагрузок K8s будет пытаться перезапустить задачу, а не перенести на другое устройство. Контейнер зависнет в цикле crash loop backoff, а информацию о причинах сбоя взять будет неоткуда.
Проброс информации о том, что ресурс нездоров, в статус пода позволит понять, что сбой вызван отказавшим устройством.
KEP добавляет новое поле resourceHealth
в секцию status спецификации пода. Оно будет содержать информацию о здоровье используемых подом ресурсов. resourceHealth
будет принимать одно из следующих значений: Healthy
, Unhealthy
или Unknown
.
Пример
Пользователь запустил под с GPU. Из-за сбоя GPU под оказывается в состоянии crash loop backoff. Пользователь просматривает статус пода с помощью kubectl describe pod
и видит, что устройство GPU нездорово (функциональность, которую реализует данный KEP). Другой вариант развития событий — контроллер удаляет под, а replicaSet перезапускает его на другом GPU.
Beta-фичи
Discover cgroup driver from CRI
KEP позволяет среде исполнения контейнеров указывать, какой драйвер cgroup использовать для kubelet. Теперь не нужно указывать драйвер cgroup в самой конфигурации kubelet. Это исключает возможность того, что настройки драйвера cgroup для kubelet и CRI будут отличаться.
KEP-4622: Add a TopologyManager policy option for MaxAllowableNUMANodes
KEP вводит новый параметр политики TopologyManager под названием max-allowable-numa-nodes
для настройки значения maxAllowableNUMANodes в TopologyManager. Текущее строго заданное на уровне кода значение (8) добавили как временную меру четыре года назад. Теперь пользователи смогут увеличить этот предел при необходимости.
KEP не меняет существующие политики TopologyManager и просто вводит новый параметр (по сути, реализуя поддержку CPU с более чем 8 NUMA-узлами).
Kubelet support for Split Image Filesystem
KEP добавляет функциональность, которая позволит kubelet правильно обрабатывать сценарии, когда файловые системы для образов и контейнеров находятся на разных дисках. Подробнее в обзоре K8s 1.30.
Deprecate status.nodeInfo.kubeProxyVersion field
Предлагается признать поле kubeProxyVersion
в NodeStatus устаревшим (deprecated). Оно использовалось облачным провайдером GCP до версии 1.28 для устаревшего встроенного cloud-provider-gcp (#117806), а до версии 1.29 — для внешнего cloud-provider-gcp (#533). Поле может использоваться и другими компонентами, поэтому авторы на всякий случай предусмотрели соответствующий переключатель функциональности DisableNodeKubeProxyVersion.
add ProcMount option
KEP добавляет поле procMount
в секцию securityContext
. Оно позволяет сделать директорию /proc
контейнера Unmasked
или смонтировать её как доступную для чтения/записи процессом контейнера. Подробнее — в обзоре Kubernetes 1.30.
Recursive Read-only (RRO) mounts
Монтирование read-only-томов появилось в Kubernetes с самого начала. Проблема в том, что в Linux read-only-тома при определённых условиях являются не совсем read-only.
Например, мы можем ожидать, что после применения приведённого ниже манифеста директория /mnt
и все её субдиректории в контейнере станут read-only. Но это не так:
```yaml
---
apiVersion: v1
kind: Pod
spec:
volumes:
- name: mnt
hostPath:
path: /mnt
containers:
- volumeMounts:
- name: mnt
mountPath: /mnt
readOnly: true
Попытки записи в /mnt*
будут отклонены, в то время как /mnt/my-nfs-server/*
останется доступной для записи.
Параметр recursiveReadOnly
в v1.30 исправляет этот недочёт, чем позволяет проводить read-only-монтирования рекурсивно. Для обратной совместимости поле recursiveReadOnly
не заменяет readOnly
, а используется совместно с ним. То есть для того, чтобы включить рекурсивный режим read-only, необходимо задать оба поля (readOnly: true
и recursiveReadOnly: Enabled
).
Quotas for Ephemeral Storage
KEP добавляет квоты файловой системы в ephemeral-storage, что позволяет разграничивать для конкретных подов/контейнеров объём общего разделяемого пространства (shared storage). Новый механизм использует квоты на проект (project quotas), доступные в XFS и ext4, обеспечивая мониторинг потребления ресурсов и опциональное накладывание лимитов на них. Функциональность появилась в Kubernetes 1.15 и теперь переходит в долгожданный бета-статус. Среди прочего был добавлен CI для мониторинга квот test-infra (#28614), исправлен мониторинг квот fs на томах Kubernetes (#115314) и дополнена документация.
Stable-фичи
Add CDI devices to device plugin API
KEP добавляет поле с ID устройств Container Device Interface (CDI) в AllocateResponse
и тем самым расширяет API плагинов устройств. Оно дополняет существующие поля, такие как аннотации, и позволяет различным реализациям плагинов ссылаться на ресурсы однозначно, используя полные имена CDI-устройств.
Move cgroup v1 support into maintenance mode
KEP обеспечивает плавный переход от cgroup v1 к cgroup v2 и при этом сохраняет возможность использовать cgroup v1 для существующих приложений и рабочих нагрузок. Поддержка cgroup v1 в Kubernetes переводится в режим обслуживания (maintenance mode). Это подчёркивает переход отрасли на cgroup v2 в качестве стандартного инструмента для управления ресурсами и изоляции ядра Linux.
AppArmor support
В Kubernetes 1.4 была добавлена поддержка AppArmor. AppArmor — это модуль безопасности ядра Linux, который расширяет стандартный набор разрешений Linux, чем позволяет ограничивать доступ программ к ресурсам. AppArmor можно настроить для любого приложения, что уменьшит потенциальную поверхность атаки и повысит защиту. Настройка осуществляется с помощью профилей и белых списков — конкретная программа или контейнер получает, например, доступ к возможностям Linux, к сети и тому подобное. Профиль может быть запущен в жёстком режиме — в этом случае попытки доступа к запрещённым ресурсам блокируются — или в мягком режиме — тогда о нарушениях только сообщается.
Kubernetes 1.31 принёс ряд незначительных изменений, связанных с поддержкой AppArmor: были удалены переключатели функциональности, дополнена документация и прочее.
Приложения
Alpha-фичи
Job API managed-by mechanism
Поле managedBy
в спецификации задачи (job) позволяет делегировать её синхронизацию внешнему контроллеру.
В рамках проекта Kueue ведётся работа над мультикластерным диспетчером задач MultiKueue. В MultiKueue, построенном по архитектуре менеджер-воркер, пользователь заводит задачу в управляющем кластере, а её зеркальная копия создаётся и выполняется в одном из кластеров-воркеров. Контроллер Kueue доносит обновления статуса задачи из воркера до управляющего кластера — они отражаются в статусе оригинальной задачи, созданной пользователем.
Такой рабочий процесс нуждается в механизме, который позволял был отключать основной контроллер задач и передавать синхронизацию статусов контроллеру Kueue.
В этом релизе фича повторно выступает в качестве альфы. Авторы исправили ошибку: задача (job) могла закончить работу с ненулевыми статусами для Ready и Terminating, см. #123775, #125089, #125510. Это создавало проблемы для контроллеров более высокого уровня, которые используют условия Failed/Completed для учёта потребления ресурсов. Также была дополнена документация (#46808).
Beta-фичи
Job success/completion policy
У задач в Kubernetes есть два способа определения успешного завершения:
-
NonIndexed
(по умолчанию): задача считается завершённой, если количество успешно завершённых подов равно числу, указанному в.spec.completions
. Другими словами, все события завершения работы подов гомологичны друг другу. -
Indexed:
задача считается завершённой, если с каждым индексом от 0 до.spec.completions
– 1 связан один успешно завершённый под. Индекс навешивается на под с помощью аннотацииbatch.kubernetes.io/job-completion-index
и переменной окруженияJOB_COMPLETION_INDEX
.
KEP дополняет API Job, позволяя задавать кастомные условия, при которых индексированная задача может быть объявлена успешной.
В некоторых случаях пакетные рабочие нагрузки требуют индексированных задач, при этом при определении успеха или неудачи задачи учитываются только отдельные «ведущие» индексы. В настоящее время это невозможно реализовать, поскольку индексированная задача помечается как завершённая только в том случае, если все индексы завершаются успешно.
Stable-фичи
PodHealthyPolicy for PodDisruptionBudget
KEP добавляет поле podHealthyPolicy
. С его помощью можно указать, что поды «здоровы» и, следовательно, подпадают под ограничения Pod Disruption Budget, либо их следует рассматривать как уже отключённые, и поэтому они могут быть проигнорированы PDB. Новые статусы для подов: status.currentHealthy
, status.desiredHealthy
и spec.unhealthyPodEvictionPolicy
.
Retriable and non-retriable Pod failures for Jobs
KEP помогает учитывать нежелательные причины перезапуска задачи (job) и, если необходимо, завершать её досрочно, игнорируя параметр backoffLimit
. Подробнее — в обзоре Kubernetes 1.25.
Elastic Indexed Jobs
Индексированные задачи (job) появились в Kubernetes 1.21, чтобы облегчить планирование высокопараллелизуемых заданий. Однако после их создания невозможно изменить количество (spec.completions
) или допустимое число параллельных задач (spec.parallelism
). Это довольно проблематично для некоторых рабочих нагрузок, например связанных с глубоким обучением.
Данный KEP делает эти поля (spec.completions и spec.parallelism
) изменяемыми (mutable) при условии, что они равны.
Allow StatefulSet to control start replica ordinal numbering
Цель KEP — разрешить миграцию StatefulSet между пространствами имён, между кластерами, а также разбивать его на сегменты без простоев в работе приложения. Подробности — в обзоре Kubernetes 1.26.
Random Pod selection on ReplicaSet downscaling
Текущий алгоритм масштабирования вниз для ReplicaSet’ов предпочитает удалять самые «молодые» поды — то есть поды с наибольшим индексом: pod-5, затем pod-4 и так далее. Идея в том, чтобы минимизировать перебои в работе, исходя из предположения, что у «молодых» подов, скорее всего, будет меньше клиентов. Однако такой подход может навредить требованиям высокой доступности: когда ReplicaSet оказывается в несбалансированном состоянии по доменам отказов (например, зонам доступности или узлам), этот подход имеет склонность сохранять дисбаланс после повторяющегося масштабирования вверх и вниз (то есть в одном домене отказа останется много подов, а в другом — слишком мало).
KEP реализует рандомизированный подход к алгоритму выбора пода-жертвы при масштабировании вниз контроллера ReplicaSet для уменьшения дисбаланса ReplicaSet в доменах отказов. В спецификацию ReplicaSet вводится параметр podSelectionPolicy
, который позволит пользователям выбирать политику удаления подов, например RandomSelect
или OldestFirst
.
Хранилище
Beta-фичи
Portworx file in-tree to CSI driver migration
KEP обеспечивает миграцию встроенного в кодовую базу Kubernetes (in-tree) драйвера Portworx в самостоятельный CSI-драйвер. Драйвер вошел как бета-фича в K8s 1.25, однако он был по умолчанию выключен. Начиная с этой версии Kubernetes, он будет по умолчанию включён.
Always Honor PersistentVolume Reclaim Policy
Политика возврата (reclaim policy) томов типа Persistent Volume (PV) может не соблюдаться, если PV работает в связке с PVC (Persistent Volume Claim): PV соблюдает политику, если PVC удаляется до удаления PV.
Если первым из пары удаляется PV, политика возврата не выполняется, а связанный с PV внешний ресурс хранения не удаляется. KEP обеспечивает соблюдение политики возврата PV, если его удаление происходит раньше, чем удаление PVC:
-
добавляется метка
deletionTimestamp
, которая вызывает обновление; -
если обновление обрабатывается до того, как PVC удалён, удаление связанного PV игнорируется.
Kubernetes VolumeAttributesClass ModifyVolume
Облачные провайдеры и поставщики систем хранения предлагают тома, которые позволяют задавать параметры качества IO-обслуживания (Performance): IOPS или пропускная способность. Также эти тома позволяют настраивать их по мере эксплуатации рабочих нагрузок (1, 2, 3, 4, 5, 6). Эти параметры можно указать при инициализации, однако API Kubernetes не умеет их изменять. Изменить можно только объём через API-расширения тома. KEP дополняет API Kubernetes Persistent Volume, позволяя управлять этими параметрами тома динамически.
В API Kubernetes добавляется новый объект VolumeAttributesClass
, новый admission-контроллер и контроллер защиты VAC. Подробнее — в обзоре Kubernetes 1.29.
Stable-фичи
PersistentVolume last phase transition time
KEP добавляет новое поле PersistentVolumeStatus, которое содержит временную метку последнего изменения фазы PersistentVolume. Это позволит любому пользователю, в том числе и тестам производительности, измерять время, например, между PV Pending и Bound. Ещё такая метка может пригодиться для метрик и SLO. Подробности смотрите в обзоре K8s 1.29.
Сеть
Beta-фичи
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.
Multiple Service CIDRs
KEP реализует новую логику работы аллокатора IP-адресов на базе двух новых объектов API: ServiceCIDR
и IPAddress
— и создаёт новые ServiceCIDR
, тем самым позволяя динамически увеличивать количество доступных IP-адресов для сервиса.
Новый аллокатор сможет «автомагически» потреблять IP-адреса из любого доступного ServiceCIDR. Эту модель можно сравнить с добавлением дополнительных дисков в систему хранения данных для увеличения её емкости. Дополнительная информация — в обзоре K8s 1.29.
Stable-фичи
Kube-proxy improved ingress connectivity reliability
KEP реализует механизм разгрузки соединений (connection draining) для terminating-узлов и добавляет путь /livez
в сервер проверки работоспособности kube-proxy (proxier_health.go
) (подробнее — в обзоре K8s 1.28). Также планируется выпустить рекомендации для поставщиков облачных услуг с перечнем более эффективных способов проверки работоспособности кластеров Kubernetes.
Примечание: KEP затрагивает только kube-proxy, так как это единственный сервисный прокси, который находится в ведении проекта Kubernetes.
API
Alpha-фичи
Introduce compatibility version for Kubernetes control-plane upgrades
KEP вводит опции совместимости версий и эмуляции для компонентов управляющего слоя Kubernetes, чтобы сделать обновление более безопасным, увеличив гранулярность шагов, доступных администраторам кластеров.
Новый флаг --emulation-version
позволит эмулировать возможности (API, функции и т. п.) предыдущей версии Kubernetes. При его использовании доступные возможности будут соответствовать эмулируемой версии. Любые возможности, которые появились в последующих версиях, будут недоступны. Возможности, которые были удалены в последующих версиях, наоборот, будут доступны.
Ещё один новый флаг, --min-compatibility-version
, позволит указывать минимальную версию, с которой совместим компонент управляющего слоя (с точки зрения версий хранилищ, правил валидации и так далее). При его использовании компонент допускает рабочие нагрузки, которые ожидают поведения указанной минимальной совместимой версии, диапазоны перекосов компонента расширяются на основе минимальной совместимой версии, а откат может быть выполнен до указанной минимальной совместимой версии.
Пример
В кластере работает Kubernetes 1.30.12. Администратор решает аккуратно обновить версию оркестратора до 1.31.5, используя минимально возможные шаги обновления, проверяя работоспособность кластера на каждом шаге.
Для каждого компонента управляющего слоя он в рекомендуемом порядке:
-
обновляет исполняемый файл до kubernetes-1.31.5, но задаёт
--emulation-version=1.30
; -
проверяет работоспособность кластера.
Далее для каждого компонента управляющего слоя администратор:
-
задаёт
--emulation-version=1.31
; -
проверяет работоспособность кластера.
Предположим, что администратор кластера обнаружил, что функция, от которой зависит рабочая нагрузка, была удалена, и необходимо откатиться на предыдущую версию. Для этого он просто перезапускает компонент с установленным параметром --emulation-version=1.30
, то есть физически откатываться на предыдущую версию больше не нужно.
Coordinated Leader Election
Предлагается более безопасный механизм выборов лидера на основе lease’ов, но с двумя ключевыми изменениями:
-
Вместо конкуренции за lease инстансы будут «выдвигать» свои кандидатуры на lease, а координатор выборов закрепит lease за лучшим из доступных кандидатов.
-
Координатор выборов может пометить lease как «заканчивающуюся» (end of term), что тем самым послужит сигналом текущему лидеру прекратить её продление. В результате текущий лидер будет отстранён и заменён лучшим.
Мотивация
Наиболее распространённым подходом к обновлению компонентов управляющего слоя Kubernetes является подход «узел за узлом», при котором все компоненты узла терминируются одновременно, а затем перезапускаются в новой версии.
Такой подход применяется при обновлении API кластера, kubeadm и kind.
Для соблюдения skew-политики (определяет, какие версии различных компонентов могут использоваться совместно без нарушения совместимости):
-
При обновлении — менеджеры контроллеров и планировщики должны оставаться на старой версии до тех пор, пока все серверы API не будут обновлены.
-
При откате — менеджеры контроллеров и планировщики должны откатываться до старой версии перед серверами API.
Однако обновления или откаты по принципу «узел за узлом» в настоящее время могут нарушать эти правила.
При обновлении управляющего слоя из трёх узлов вероятность того, что новая версия контроллера будет запущена при работающих старых версиях серверов API, составляет около 25%. То есть существует достаточно высокий риск нарушить skew-политику. При откате она будет нарушена почти наверняка.
Также существует вероятность того, что lease будет потеряна одним из лидеров во время обновления или отката. Это приведёт к чередованию старых и новых версий контроллера.
Для решения этих проблем KEP вносит ряд изменений в определение LeaseCandidate (в частности, удаляются поля LeaseTransitions
и HolderIdentity
). Кроме того, новый контроллер Coordinated Election Controller будет согласовывать lease’ы лидеров компонентов (первичный ресурс) и lease’ы кандидатов (вторичный ресурс, изменения которого запускают согласование соответствующих lease’ов лидеров).
Move Storage Version Migrator in-tree
Kubernetes полагается на активную перезапись данных в ресурсах при работе с at-rest-хранилищами. Два ярких примера, когда такая перезапись необходима:
-
обновление предпочтительной схемы хранения для ресурса, например переход с
v1beta1
наv1
; -
обновление способа шифрования at-rest-данных, например перезапись stale-данных с учётом изменившегося метода шифрования.
Самый простой способ переписать данные — использовать команды kubectl get
и kubectl replace
. Однако это проблематично для ресурсов, содержащих большой объём данных, вроде секретов Kubernetes. Выполнять миграцию хранилищ вручную также нецелесообразно, поскольку количество нуждающихся в миграции ресурсов постоянно растёт.
Основная цель KEP — облегчить пользователям выполнение таких миграций хранилищ, не заботясь о технических деталях, сделать процесс более автоматизированным и простым. Для это предлагается:
-
перенести существующую логику контроллера SVM in-tree в KCM;
-
перенести существующие API SVM REST in-tree (возможно, в новую группу API, чтобы избежать конфликтов со старыми API, работающими параллельно).
Alpha-версия не предусматривает автоматическую миграцию версий хранилищ — решение остаётся за пользователем.
Beta-фичи
[Beta: 1.31] Consistent Reads from Cache
Запросы Get
и List
гарантированно являются «согласованными операциями чтения» (consistent reads), если не указан параметр resourceVersion
. Такие операции производятся из etcd с использованием «кворумного чтения». При этом watch-кэш часто содержит достаточно актуальные данные для ответа на запрос на чтение и может удовлетворить его гораздо эффективнее.
KEP предлагает механизм, позволяющий удовлетворять большинство запросов на чтение с помощью watch-кэша, обеспечивая при этом те же гарантии согласованности, что и при получении данных из etcd.
Custom Resource Field Selectors
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
KEP вносит ряд изменений в apiserver, которые предписывают повторять попытки генерации новых имён в случае, если create-запрос с использованием generateName
заканчивается ошибкой «конфликт имён». Подробнее — в обзоре K8s 1.30.
Resilient Watchcache Initialization
Есть ряд проблем, которые могут привести к значительной перегрузке kube-apiserver и etcd (или — в худшем случае — даже к его падению) во время инициализации или реинициализации слоя watchcache. KEP предлагает решение для смягчения этих проблем и стартует сразу как бета.
Мотивация
Watchcache — это кэширующий слой внутри kube-apiserver для консистентного хранения состояния кластера из etcd (как самого состояния, так и недавней истории журнала транзакций). Он критически важен для масштабирования управляющего слоя (control plane) благодаря встроенной индексации, устраняя лишнюю работу, которая в ином случае потребовалась бы, например, для распределения одного события watch на множество watch’ей.
Однако существует ряд проблем, когда watchcache либо ещё не инициализирован при запуске kube-apiserver, либо требует повторной инициализации из-за того, что не успевает за нагрузкой. Оба эти случая могут привести к значительной перегрузке всего управляющего слоя (включая etcd), в худшем случае — даже к её отказу.
Цель данного KEP — описать текущие проблемы и предложить пути их решения или по крайней мере смягчения, чтобы избежать таких перебоев в работе управляющего слоя.
Аутентификация
Alpha-фичи
Authorize with Field and Label Selectors
KEP предлагает новый механизм авторизации в Kubernetes на базе селекторов для управления доступом к ресурсам.
Запросы List
, Watch
и DeleteCollection
смогут использовать селекторы полей и лейблов для более точной фильтрации ресурсов, которые возвращаются в ответ на запрос.
Атрибуты авторизации получат упрощённый доступ к параметрам запроса для селекторов полей и лейблов. Селекторы не будут включаться в атрибуты авторизации для запросов, для которых селектор поля не имеет смысла (например, запросы с методами Create
или Update
).
API-объект SubjectAccessReview
теперь будет использовать разные сериализации для различных случаев использования, таких как вызовы вебхуков и авторизационные проверки от клиентов. Это повысит совместимость и упростит обработку запросов.
Node Authorizer будет модифицирован, чтобы авторизовать только тех клиентов, которые могут перечислять и наблюдать поды с селекторами полей, содержащими spec.nodeName=$nodeName
.
Определённые изменения коснутся и CEL Authorizer — он будет поддерживать использование селекторов полей и лейблов для авторизационных проверок, делая управление доступом более гибким.
Only allow anonymous auth for configured endpoints
В настоящее время анонимная аутентификация в Kubernetes включена по умолчанию. Это означает, что запросы без токена аутентификации автоматически обрабатываются как анонимные. Однако администраторы не могут настраивать, к каким именно ресурсам разрешён анонимный доступ, а могут лишь включить или выключить это поведение с помощью логического флага --anonymous-auth
(по умолчанию он установлен в true
).
KEP реализует механизм, который позволяет пользователям настраивать, к каким эндпоинтам возможен анонимный доступ, и отключать анонимную аутентификацию для всех остальных эндпоинтов.
Авторы предлагают для anonymous-auth
три состояния:
Отключено. Аутентификация не проходит для любых анонимных запросов:
apiVersion: apiserver.config.k8s.io/v1alpha1
kind: AuthenticationConfiguration
anonymous:
enabled: false
Включено. Аутентификация проходит успешно для анонимных запросов:
apiVersion: apiserver.config.k8s.io/v1alpha1
kind: AuthenticationConfiguration
anonymous:
enabled: true
Включено для некоторых эндпоинтов. Аутентификация анонимных запросов проходит только для определённых конечных точек:
apiVersion: apiserver.config.k8s.io/v1alpha1
kind: AuthenticationConfiguration
anonymous:
enabled: true
conditions:
- path: "/healthz"
- path: "/readyz"
- path: "/livez"
Примечание
Пути чувствительны к регистру.
Пример
Представьте администратора кластера, думающего о безопасности. Он хочет отключить анонимную аутентификацию, но при этом оставить неаутентифицированный доступ к health-эндпоинтам, чтобы не перенастраивать внешние сервисы, например балансировщики нагрузки. Для этого он выбирает третий вариант — анонимную аутентификацию для определённых эндпоинтов.
Beta-фичи
Bound service account token improvements
KEP дополняет генерируемые токены при обработке вызова TokenRequest create
kube-apiserver-функциями для автоматического включения name
и uid
узла, с которым ассоциирован под (через spec.nodeName
).
Так как в этой области кода уже есть под, который содержит имя узла, необходимо пробросить геттер (get
) для объектов Node на уровень хранения TokenRequest. Это нужно, чтобы можно было получать UID узла аналогично тому, как это делается для объектов Pod и Secret.
CLI
Beta-фичи
Transition from SPDY to WebSockets
Предлагается перейти с протокола SPDY/3.1 на WebSockets для kubectl exec
, kubectl attach
и kubectl cp
в части взаимодействия между kubectl
и сервером API. Также предлагается расширить участок, на котором коммуникация ведётся по протоколу WebSockets от сервера API до kubelet. После этого между kubectl
и kubelet будет происходить потоковая передача данных по WebSockets, проксируемая через сервер API. Подробнее — в обзоре Kubernetes 1.29.
Custom profile in kubectl debug
KEP добавляет кастомное профилирование поверх предопределённых профилей в команде kubectl debug
, избавляя от необходимости открывать Issue для очередного «нового» флага.
У kubectl debug
есть набор предопределённых профилей. Пользователи могут выбрать подходящий в соответствии со своими потребностями и ролями. Однако в некоторых случаях — возможно, даже в большинстве — требуется настроить эти профили, добавив:
-
секреты для извлечения образов (
imagePullSecret
).
Преодолеть эти сложности можно вручную, правя спецификации подов (если только такое вмешательство не препятствует их доступности). Но это непрактично, особенно если приходится делать так постоянно. В подобных случаях пользователи обычно открывают Issue или готовят Pull Request, в котором предлагают очередной флаг для управления определёнными полями в спецификациях подов. В итоге команда debug
рискует превратиться в нечто неуправляемое — её будет сложно поддерживать хранителям, да и пользователям будет тяжело разобраться в её нюансах. Но KEP предлагает более изящный способ решения этой проблемы.
Планировщик
Beta-фичи
Introduce MatchLabelKeys to Pod Affinity and Pod Anti Affinity
KEP вводит дополнительные поля MatchLabelKeys
и MismatchLabelKeys
в PodAffinityTerm
. Это позволит пользователям контролировать применимость PodAffinity
или PodAntiAffinity
для подов в дополнение к существующему LabelSelector. Подробнее — в обзоре Kubernetes 1.29.
Разное
Stable-фичи
Metric cardinality enforcement
Метрики с неограниченными измерениями могут вызывать проблемы с памятью в инструментируемых компонентах. KEP добавляет возможность динамически настраивать список допустимых значений лейблов для метрики во время работы.
Список устаревших или удалённых фич
Ниже приведён список фич, которые признаны устаревшими в Kubernetes 1.31.
-
Cgroup v1 переходит в режим поддержания (maintenance). Рекомендуется перейти на cgroup v2 как можно скорее.
-
В go1.18 библиотека crypto/x509 начала отклонять сертификаты, подписанные с помощью хэш-функции SHA-1. Тем, кто использует в работе сертификаты, основанные на SHA-1, необходимо явно отказаться от их поддержки, установив в своём окружении
GODEBUG=x509sha1=1
. Политика совместимости в отношении GODEBUG’ов предписывает удалениеGODEBUG x509sha1
и поддержки сертификатов SHA-1 в go1.24, который выйдет в первой половине 2025 года — самое время задуматься о миграции. Подробности смотрите в #125689. -
Поле
.status.nodeInfo.kubeProxyVersion
было признано устаревшим в Kubernetes v1.31 и будет удалено в одном из следующих релизов. Разработчики решили отказаться от него из-за отсутствия механизма, который обеспечивал бы его корректность. Дело в том, что поле устанавливается kubelet’ом, который не имеет надёжной информации о версии kube-proxy или о том, запущен ли он. В K8s 1.31 переключатель функциональностиDisableNodeKubeProxyVersion
будет по умолчанию установлен в true, и kubelet более не будет пытаться установить поле.status.kubeProxyVersion
для связанного с ним узла. -
Были удалены все оставшиеся in-tree-интеграции для облачных провайдеров и соответствующие переключатели функциональности.
-
Был удалён флаг kubelet
--keep-terminated-pod-volumes
(см. #122082). -
Были удалены плагины томов CephFS и Ceph RBD.
Перед обновлением рекомендуем ознакомиться с changelog.
P. S.
Читайте также в нашем блоге:
Автор: kubelet