Kubernetes 1.25: обзор нововведений

Этой ночью представят новую версию Kubernetes. Среди главных изменений на первое место разработчики поставили стабилизацию функции CSI Migration — отказ от внутренних плагинов хранилищ в пользу CSI-драйверов. Также в этой версии устаревший контроллер PodSecurityPolicy заменен на новый PodSecurity Admission.

По традиции, в обзоре рассказываем обо всех новых функциях (alpha), а также упоминаем те, что перешли на уровень выше (beta, stable).

09faf8875b0e0caa4e954a8b0bf31829.png

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

Всего в новом релизе 40 изменений. Из них:

  • 15 новых функций (alpha);  

  • 10 продолжают улучшаться (beta);

  • 13 признаны стабильными (stable);

  • 2 устарели.

Примечание

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

Главное изменение: стабилизация CSI Migration

#625; KEP; Stable

Масштабный проект по миграции со встроенных плагинов томов на CSI-драйверы стартовал в 2017-м, когда в Kubernetes 1.9 появилась альфа-версия функции Out-of-Tree Volume Plugins (CSI). С тех пор Kubernetes последовательно отключает встроенные плагины популярных хранилищ — от AWS до Portwox.

В этом релизе в статус GA перешли три миграции: ядро (Core CSI), а также плагины GCE PD и AWS EBS. Как подчеркивают разработчики Kubernetes, это важный шаг на пути к полному избавлению Kubernetes от встроенных плагинов томов.

Узлы

Add support for user namespaces

#127; KEP; Alpha 

Сейчас Kubernetes не поддерживает пользовательские пространства имен (user namespaces). ID пользовательского или группового процесса (UID/GID), который запущен в Pod«е, всегда идентичен ID хоста. Из-за этого могут возникать проблемы. Например, если в контейнере запущен вредоносный привилегированный процесс, под угрозой оказываются и Pod, и хост, на котором этот Pod запущен, потому что для хоста это тоже привилегированный процесс.

Новая функция добавляет в K8s поддержку пользовательских пространств имен. Теперь процессам в контейнерах можно назначать пользовательские и групповые ID, отличные от ID хоста. Это значит, что для контейнера процесс можно сделать привилегированным, а для хоста — обычным. Фича активируется через поле hostUsers в pod.Spec.

Главная цель — еще больше изолировать Pod от хоста. Авторы KEP«а приводят список известных уязвимостей, которые новая функция полностью или частично закрывает.

Forensic Container Checkpointing

#2008; KEP; Alpha

Улучшение, которое буквально переводится как «контрольная точка контейнера для криминалистического анализа», помогает скрыто выявлять подозрительную активность в контейнерах. Контрольная точка контейнера — его состояние на определенный момент времени; она создается из снапшота в виде копии целевого контейнера. Копия разворачивается во внешней среде — например, на другом узле вне кластера K8s — и проверяется на наличие вредоносной активности внешними инструментами. Инструменты проверки остаются за рамками фичи и на усмотрение администратора. Что важно, целевой контейнер не «подозревает» о проверке и существовании своей копии.

Последовательность шагов:

  1. Создается контрольная точка: curl -skv -X POST "https://localhost:10250/checkpoint/default/counters/wildfly"

  2. Архив с контрольной точкой берется из /var/lib/kubelet/checkpoints и перемещается в другую среду, вне K8s.

  3. Выполняется crictl restore --import=, чтобы восстановить копию контейнера в другой среде.

Для реализации фичи расширены API CRI (Container Runtime Interface) и функциональность kubelet. Включается feature gate«ом ContainerCheckpoint.

Kubelet OpenTelemetry tracing

#2831; KEP; Alpha

Взаимодействие API-сервера и kubelet — основной способ коммуникации между управляющим слоем Kubernetes (control plane) и узлами. Это взаимодействие организовано с помощью gRPC- и HTTP API-запросов. Авторы улучшения считают, что трассировка таких запросов расширит возможности поиска и отладки проблем с узлами и kubelet«ом, в том числе при взаимодействии kubelet«а со средой исполнения контейнеров.

Фича помогает обнаруживать источники различных задержек во время:

  • создания, удаления, запуска и остановки контейнеров;

  • монтирования и подключения томов, на которые ссылается Pod;

  • проброса портов контейнеров.

Для реализации трассировки используется имплементация OpenTelemetry для Go. Собирает трейсы специальный агент — collector, который запускается в виде sidecar«а, ​​Deployment«а или DaemonSet«а. Для экспорта спанов применяется связка OTLP exporter, OTLP trace provider и context propagator.

Pod sandbox ready condition

#3085; KEP; Alpha

Создание песочницы Pod«а (Pod sandbox) — критически важная фаза его жизненного цикла. Завершение этой фазы говорит о том, что сеть для Pod«а настроена успешно. Проблема в том, что Kubernetes не отслеживает статус процесса создания песочницы и не сообщает о результате пользователю — по крайней мере так же однозначно, как, например, в случае с ContainersReady при создании контейнеров. Есть состояние Initialized, которое актуально для init-контейнеров, есть PodScheduled, которое показывает, запланирован ли Pod —, но этого недостаточно.

Информация о статусе процесса может быть полезной для сторонних сервисов мониторинга (например, kube-state-metrics) и контроллеров. С ее помощью можно более точно оценивать состояние Pod«ов, выявлять задержки при настройке сети, лучше согласовывать работу Pod«ов и связанных с ними ресурсов вроде PVC.

Авторы улучшения предложили расширить возможности kubelet и добавить новое состояние Pod«а — PodHasNetwork со статусом true или false. Kubelet генерирует PodHasNetwork как часть существующих вызовов generateAPIPodStatus().

Пример отчета о состоянии Pod«а:

status:
  conditions:
  ...
  - lastProbeTime: null
    lastTransitionTime: "2022-12-06T15:33:49Z"
    status: "True"
    type: PodHasNetwork

CPU Manager policy: socket alignment

#3327; KEP; Alpha

В Kubernetes 1.23 появилась альфа-версия функции, которая помогает равномерно распределять ресурсы процессора между NUMA-узлами (Non-Uniform Memory Architecture). Для этого включается политика distribute-cpus-across-numa. В нынешнем релизе представлено улучшение, которое расширяет возможности распределения. 

В CPU Manager добавлена новая политика align-by-socket. Она гарантирует, что приложения могут рассчитывать на выравнивание ресурсов по крайней мере в пределах одного сокета — в дополнение к выравниванию между NUMA-узлами. При этом CPU Manager может задействовать доступные процессорные мощности всех NUMA-узлов, которые входят в сокет. Обе политики — align-by-socket и distribute-cpus-across-numа — обеспечивают более предсказуемую производительность приложений, чувствительных к задержкам.

Beta-фичи

Ephemeral storage quotas улучшает возможности по отслеживанию утилизации локальных эфемерных хранилищ с помощью квот файловой системы. Альфа-версию фичи представили ещё три года назад в Kubernetes 1.15.

Add configurable grace period to probes — новое поле в конфигурации liveness-проверок probe.terminationGracePeriodSeconds. Через этот параметр можно настроить принудительное завершение проверки, если она по каким-то причинам подвисает, и не дожидаться, когда отработает стандартное условие terminationGracePeriodSeconds.

Seccomp by default включает режим seccomp по умолчанию и блокирует неразрешенные системные вызовы. (Подробнее об этой важной для защиты узлов функции читайте в нашем анонсе.)

Stable-фичи

Ephemeral containers — продвинутая отладка ошибок у работающих Pod«ов с помощью тестового эфемерного контейнера. Он запускается в том же пространстве имен, что и Pod.

Cgroup v2 — совместимость K8s c функцией Linux, которая используется для распределения вычислительных ресурсов между контейнерам и их изоляции. Cgroup v2 была объявлена стабильной около трех лет назад, и с тех пор многие дистрибутивы Linux используют ее по умолчанию.

Хранилище

NodeExpansion secret

#3107; KEP; Alpha

Сейчас Kubernetes не поддерживает передачу секретов в RPC-запросах к CSI-драйверам при расширении емкости томов на узле с помощью операции nodeExpandVolume. Хотя такая возможность пригодилась бы в случаях, когда вместе с запросом нужно передать ключ или пароль — например, для расширения тома на узле с зашифрованным LUKS-диском.

Как раз для этого в запрос nodeExpandVolume, которое kubelet отправляет CSI-драйверу, добавлено новое поле secretRef. Фича активируется с помощью двух параметров в настройках storage class. Пример:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-storage-sc
parameters:
  csi.storage.k8s.io/node-expand-secret-name: secret-name
  csi.storage.k8s.io/node-expand-secret-namespace: mysecretsns

Также в объект CSIPersistentVolumeSource добавлен параметр NodeExpandSecretRef, чтобы можно было передавать секрет в PVC-запросах на расширение тома. 

Reconcile default StorageClass in PVCs

#3333; KEP; Alpha 

Если пользователю требуется хранилище, он создает PVC-запрос. При этом есть два режима provisioning«а:

  • Static provisioning, когда уже есть PV, к которому может привязаться PVC. В этом случае указывать storage class не нужно.

  • Dynamic provisioning, когда нет существующего PV, поэтому PVC указывает storage class либо ссылается на существующий storage class, который используется по умолчанию.

Это нормальный сценарий. Однако возможны и проблемные:

  1. Если в кластере уже есть storage class (SC) по умолчанию, трудно заменить его другим SC так, чтобы не возникло ошибок.

  2. Когда пользователь хочет изменить параметры SC по умолчанию, он должен удалить и пересоздать SC, потому что K8s запрещает его изменять. Если, например, для старого SC установлена квота, она пропадет после пересоздания SC, потому что привязывается к его имени.

  3. Инструменты для установки Kubernetes-кластера могут быть интегрированы с облачными провайдерами и дополнениями, которым требуется хранилище. Эти инструменты должны быть достаточно «умными», чтобы уметь создавать SC до того, как какой-нибудь из компонентов не начнет генерировать PVC.

Для решения проблем предложено изменить поведение PV-контроллера. Как только любой SC помечен в качестве SC по умолчанию, контроллер сразу же назначает его всем не привязанным PVC со значением pvc.spec.storageClassName=nil. После того, как администратор создаст SC по умолчанию, вместо nil появится имя этого SC.

SELinux relabeling using mount options

#1710; KEP; Alpha

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

  • контекста, который уникален для каждого контейнера. Например: system_u:system_r:container_t:s0:c309,c383;

  • соответствующих лейблов, которые назначаются каждому файлу на каждом томе хранилища. Например: system_u:object_r:container_file_t:s0:c309,c383

Доступ к файлам с лейблом container_file_t:s0:c309,c383 может получить только процесс с контекстом ...:container_t:s0:c309,c383. Злоумышленник, которому удалось выбраться из контейнера, не сможет получить доступ к данным в других контейнерах, потому что у каждого контейнера свои тома со своими лейблами.

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

Новая функция дает возможность пропустить этап переназначения лейблов, чтобы ускорить монтирование тома. Для этого при монтировании используется опция -o context=XYZ, которая устанавливает общий контекст для всех файлов тома. Поскольку все файлы тома уже снабжены нужным контекстом и соответствующим лейблом, переназначения лейблов не происходит.

Альфа-версия фичи работает только для томов, смонтированных с помощью PVC в режиме ReadWriteOncePod.

Beta- и Stable-фичи

CSI driver migration для томов Portworx и vSphere (Beta) — миграция со встроенных в кодовую базу Kubernetes плагинов хранилищ на CSI-драйверы.

Local ephemeral storage resource management (Stable) — поддержка изоляции общих разделов локального хранилища для Pod«ов и контейнеров. Регулируется через requests.ephemeral-storage и limits.ephemeral-storage аналогично тому, как это реализовано для CPU и памяти.

CSI Ephemeral volumes (Stable) дает возможность использовать CSI-драйверы для создания не только удаленных, но и локальных эфемерных томов. При этом использовать PV или PVC не нужно: определять CSI-том можно прямо в спецификации Pod«а.

Планировщик

Take taints/tolerations into consideration when calculating PodTopologySpread

#3094; KEP; Alpha

Узлы с какими-либо taints сообщают планировщику, что их нельзя использовать для запуска Pod«ов. Исключение делается для Pod«ов, у которых есть «допуск» — toleration. Два этих свойства помогают планировщику правильно распределять Pod«ы по узлам.

Еще один механизм регулировки распределения — набор ограничений на распространение топологии (topology spread constraints), которые указываются в поле topologySpreadConstraints в настройках Pod«а. Одно из этих ограничений — skew, или «перекос». Он указывает, какое количество Pod«ов может быть распределено по узлам неравномерно через параметр maxSkew. Параметр указывает максимальную разницу в количестве Pod«ов между двумя заданными топологическими доменами.

Когда планировщик вычисляет skew, он не отличает узлы с taints от обычных. Это может вызывать неожиданное подвисание Pod«а в статусе Pending, потому что ограничение skew работает только с taint-узлами.

Цель улучшения — сделать так, чтобы планировщик учитывал свойства taints и tolerations при обработке ограничений на распространение топологии, а также — дать пользователям возможность явно указывать, стоит ли учитывать taints. Для этого в TopologySpreadConstraint добавлены два новых поля — NodeAffinity и NodeTaints, которые устанавливаются в значение Ignore / Respect с помощью новой политики NodeInclusionPolicy. Пример того, как это работает:

  • NodeAffinity: Respect означает, что узлы, указанные в nodeAffinity и nodeSelector, будут включены в skew-процесс;

  • NodeAffinity: Ignore (активно по умолчанию) означает, что в skew-процесс будут включены все узлы.

Аналогично работает и политика NodeTaint.

Respect PodTopologySpread after rolling upgrades

#3243; KEP; Alpha

Еще одно улучшение, связанное с топологией распределения Pod«ов. На этот раз решается проблема с несбалансированным распределением Pod«ов при плавающих обновлениях Depolyment«а (на эту тему есть соответствующие issues: #98215, #105661 — и обсуждение на StackOverflow).

В TopologySpreadConstraint вводится новое поле MatchLabelKeys в качестве дополнения к существующему labelSelector. В новом поле передается набор ключей для лейблов Pod«ов — и это еще одно ограничение, которое планировщик учитывает при распределении. Пример:

     topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          matchLabelKeys:
            - app
            - pod-template-hash

Плагин PodTopologySpread ищет лейблы по ключам в matchLabelKeys. Полученные лейблы объединяются с данными в поле labelSelector для фильтрации и группировки Pod«ов. В результате Pod«ы, которые принадлежат одной группе, участвуют в распределении PodTopologySpread

Фича позволяет применять ограничения PodTopologySpread только в границах новой ревизии Depolyment«а, а не во всех ревизиях, как это происходит сейчас.

Beta- и Stable-фичи

Min domains in PodTopologySpread (Beta) добавила новое поле minDomains в настройки PodSpec.TopologySpreadConstraint. Поле ограничивает минимальное количество доменов, через которые могут распределяться Pod«ы. Функция появилась в прошлом релизе K8s (подробности — в нашем обзоре).

Graduate the kube-scheduler ComponentConfig to GA (Stable) — стабилизация KubeSchedulerConfiguration. Поддержка v1beta2 в apiVersion признана устаревшей; вместо нее нужно использовать v1beta3 или v1. Также удален плагин SelectorSpread, вместо которого используется PodTopologySpread.

Сеть

Cleaning up IPTables Chain Ownership

#3178; KEP; Alpha

Kubelet при запуске создает цепочки iptables. Некоторые из этих цепочек kubelet«у больше не нужны в связи с удалением модуля dockershim. Другие же дублируют цепочки, которые создает kube-proxy. 

Решение — отказаться от большинства цепочек iptables, создаваемых kubelet«ом. Для этого добавлена опция IPTablesOwnershipCleanup, которая:

  1. Запрещает kubelet«у создавать цепочки KUBE-MARK-DROP, KUBE-MARK-MASQ, KUBE-POSTROUTING и KUBE-KUBELET-CANARY (остается лишь KUBE-FIREWALL для обработки марсианских пакетов).

  2. Предупреждает, что аргументы kubelet«а --iptables-masquerade-bit и --iptables-drop-bit устарели и больше не работают.

Нельзя сказать, что улучшение сильно расширяет функциональность K8s, скорее — способствует «гигиене» кластера.

Multiple ClusterCIDRs

#2593; KEP; Alpha

NodeIPAM-контроллер (IP Address Management) распределяет диапазоны IP-адресов между кластерами таким образом, что одному кластеру достается строго определенный набор IP-адресов — cluster CIDRs (Classless Inter-Domain Routing). Этот набор нельзя изменить, что ограничивает возможности распределения IP-адресов для Pod«ов. Например, когда нужно расширить кластер, для запуска новых Pod«ов может не хватить IP-адресов.

Новый ресурс ClusterCIDRConfig реализует механизм распределения CIDRs для узлов, при котором пользователи могут менять диапазоны IP-адресов для Pod«ов (CIDR«ов) динамически и даже заранее настраивать их размер.

Также вместе с фичей добавлена поддержка нового NodeIPAM-контроллера, который «наблюдает» за объектами ClusterCIDRConfig и узлами.

Beta-  и Stable-фичи

Reserve Service IP Ranges For Dynamic and Static IP Allocation (Beta) — фича, которую представили в прошлом релизе Kubernetes. Жестко закрепляет определенный диапазон IP-адресов для статической и динамической раздачи clusterIP сервисам. Цель — снизить вероятность конфликтов при создании сервисов со статическими IP (см. наш обзор).

NetworkPolicy port range (Stable) добавила возможность определять в объекте NetworkPolicy диапазон портов, в то время как раньше нужно было определять каждый порт по отдельности. Функция помогает более гибко настраивать обработку ingress- и egress-трафика приложений. Пример настройки:

spec:
  egress:
  - ports:
    - protocol: TCP
      port: 32000
      endPort: 32768

Разное

Auto-refreshing Official CVE Feed

#3203; KEP, Alpha

По мере роста популярности Kubernetes увеличивается количество связанных с технологией уязвимостей (CVE). И хотя большинство из них оперативно закрываются, единого места, где хранилась бы актуальная информация о CVE, нет. Меж тем среди пользователей Kubernetes, включая K8s-провайдеров, немало тех, кому такая информация была бы полезна.

Авторы улучшения предлагают создать автоматически обновляемый список Kubernetes CVEs и разместить его по адресу https://kubernetes.io/docs/reference/issues-security/official-cve-feed со ссылкой на странице Kubernetes Security and Disclosure Information. Список будет пополняться issues, которым присвоен лейбл official-cve-feed.

KMS v2 Improvements

#3299; KEP; Alpha

Фича подразумевает многоэтапное улучшение сервиса Key Management Service (KMS), который используется для шифрования данных etcd по схеме envelope encryption. Глобальная цель фичи — упростить работу с KMS; также:

  • сократить время готовности кластеров с большим количеством зашифрованных ресурсов;

  • уменьшить вероятность превышения допустимого лимита для KMS-плагина;

  • улучшить наблюдаемость envelop-операций kube-apiserver«ом, KMS-плагинами и самим сервисом KMS.

Авторы KEP«а приводят подробный план реализации улучшения, включая примеры диаграмм запросов на шифрование и дешифрование. 

Retriable and non-retriable Pod failures for Jobs

#3329; KEP; Alpha

Чтобы ограничить время выполнения Job, используются два параметра:  

  • activeDeadlineSeconds — максимальное время выполнения Job«а;

  • backoffLimit — количество попыток запуска Job«а за отведенное (в предыдущем параметре) время.

Если Job не запускается, и политика перезапуска установлена в OnFailure, Kubernetes попытается заново запустить Job — столько раз, сколько указано в backoffLimit.

Job может не запускаться по разным причинам, и параметр backoffLimit это не учитывает. В некоторых случаях могут возникать нежелательные перезапуски Job«а и, как следствие, Pod«а — например, когда есть ошибки в коде приложения, а в backoffLimit указано 5. В идеале такому Pod«у лучше бы вообще не запускаться, но Job руководствуется тем, что прописано в backoffLimit, и перезапускает Pod. Проблема усугубляется в больших кластерах: перезапуск тысяч Pod«ов съедает немало времени и вычислительных ресурсов.

Нововведение помогает учитывать некоторые причины незапуска Job«а и, при необходимости, завершать его досрочно, игнорируя backoffLimit. Для этого в Job API добавлено новое поле podFailurePolicy. Ниже — пример для случая, когда требуется завершить Job, который не запускается из-за ошибок в исполняемом файле:  

apiVersion: v1
kind: Job
spec:
  template:
    spec:
      containers:
      - name: job-container
        image: job-image
        command: ["./program"]
  backoffLimit: 6
  podFailurePolicy:
    rules:
    - action: Terminate
      onExitCodes:
        operator: NotIn
        values: [40,41,42]

В параметре values указаны допустимые коды завершения работы контейнера. Если контейнер завершает работу с другими кодами, Job завершается досрочно, не учитывая установленный backoffLimit.

Beta-фичи

CRD Validation Expression Language предлагает упрощенный вариант проверки пользовательских ресурсов в CRD (Custom Resource Definition). Теперь, помимо вебхуков, для описания правил можно использовать скриптовый язык CEL.

Server Side Unknown Field Validation перекладывает функцию проверки неизвестных и дублирующих полей в запросах к API-серверу с клиентской части (пользователя) на серверную. Мотив: проверку на стороне клиента организовать значительно сложнее, чем на стороне сервера.

TimeZone support in CronJob добавляет новое поле в CronJob API — .spec.timeZone, где можно заранее установить часовой пояс для запуска Job«а. Помогает избежать возможной несогласованности между часовыми поясами kube-controller-manager«а и Job«а, который он запускает.

Stable-фичи

MaxSurge support for DaemonSets позволяет обновлять рабочие нагрузки DaemonSet«а во время плавающих обновлений без простоя: старый Pod отключается только после того, как запускается новый. Функция регулируется параметром updateStrategy.rollingUpdate.maxSurge в поле updateStrategy, где указывается, сколько новых Pod«ов нужно создать на замену старым.

Add minReadySeconds to Statefulsets — фича добавила в настройки StatefulSet«а новое поле minReadySeconds. В нем определяется количество секунд, по истечении которых созданный Pod может считаться готовым к работе. Функция аналогична уже реализованным для Deployment«а, DaemonSet«а и ReplicasSet«а.

Identify Windows pods at API admission level authoritatively — нововведение, призванное улучшить процесс идентификации ОС Pod«а при его подключении к API-серверу.

PodSecurity admission (PodSecurityPolicy replacement) — новый контроллер доступа, который заменил устаревший PodSecurityPolicy. PodSecurity admission определяет стандарты безопасности Pod«ов на уровне пространства имен, ориентируясь на лейблы. Подробнее о работе нового контроллера мы писали в обзоре K8s 1.22. Для тех, кто пока еще использует PodSecurityPolicy, есть инструкция по миграции на PodSecurity Admission Controller.

Некоторые из удаленных фич

  • Контроллер PodSecurityPolicy.

  • Флаг --service-account-api-audiences в запросе к API-серверу заменен на --api-audiences.

  • VSphere версии ниже 7.0 U2.

  • Windows winkernel Kube-proxy больше не поддерживает Windows HNS v1 APIs.

  • Встроенные плагины томов GlusterFS, flocker, quobyte, storageos.

  • Неиспользуемые флаги в kubectl run.

  • Ряд аннотаций seccomp.

Обновления в зависимостях Kubernetes

  • containerd v1.4.9;

  • Go 1.18.3;

  • etcd v3.5.4;

  • cri-tools v1.24.2.

P.S.

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

© Habrahabr.ru