Этой ночью, 5 августа, состоится новый релиз Kubernetes — 1.22. Рассказываем о наиболее значимых изменениях в новой версии.
Для подготовки материала использовалась информация из таблицы Kubernetes enhancements tracking, CHANGELOG-1.22, обзора Sysdig, а также соответствующих issues, pull requests и Kubernetes Enhancement Proposals (KEPs).
В новом релизе 56 улучшений. Из них:
-
16 новых функций (alpha);
-
24 продолжают улучшаться (beta);
-
13 признаны стабильными (stable);
-
3 перешли в статус «устаревших» (deprecation).
Достаточно много фич прямо или косвенно относятся к повышению уровня безопасности в Kubernetes — с них и начнем.
Безопасность
Pod Security Admission Control
На смену устаревшей в 1.21 PodSecurityPolicy пришел контроллер доступа PodSecurity admission controller, пока в альфа-версии. Теперь именно он определяет стандарты безопасности pod’ов на уровне пространства имен, ориентируясь на лейблы.
Новые политики работают в трех режимах:
-
принудительный (
enforce
): нарушение политик приводит к отказу в запуске pod’а; -
проверочный (
audit
): нарушения вызывают добавление аннотации аудита, но допускаются; -
предупредительный (
warn
): пользователь предупреждается о нарушениях, но они допускаются.
В одном пространстве имен можно применять несколько политик одновременно.
Пример настройки ресурса AdmissionConfiguration
:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
defaults: # Значения по умолчанию, если лейбл с режимом не задан
enforce: <default enforce policy level>
enforce-version: <default enforce policy version>
audit: <default audit policy level>
audit-version: <default audit policy version>
warn: <default warn policy level>
warn-version: <default warn policy version>
exemptions: # Исключения из правил
usernames: [ <array of authenticated usernames to exempt> ]
runtimeClassNames: [ <array of runtime class names to exempt> ]
namespaces: [ <array of namespaces to exempt> ]
...
В KEP перечислены основные причины, из-за которых пришлось отказаться от PodSecurityPolicy. Об этом также писали в блоге Kubernetes.
Seccomp by default
Seccomp by default — важная и долгожданная фича в статусе альфа, которая повышает безопасность «ванильного» Kubernetes. Теперь фильтрация системных вызовов автоматически включается при запуске любых контейнеров (в предыдущих версиях K8s это нужно делать вручную).
Seccomp — режим, при котором все неразрешенные системные вызовы блокируются. Это помогает избегать атак на узел или целый кластер через контейнер, а также повышает устойчивость K8s к zero day-уязвимостям. Подробнее об алгоритме работы новой фичи мы писали в этой новости.
Kubelet-in-UserNS (aka Rootless mode)
Kubelet-in-UserNS, он же rootless mode, — еще одна функция, которая помогает защищать от угроз, связанных с потенциальными уязвимостями в базовых компонентах Kubernetes, работающих на хосте (KEP). В rootless-режиме можно запускать kubelet, CNI, CRI, OCI и любые компоненты с приставкой «kube-» от имени обычных пользователей (т. е. не root). Пользователи shared-машин (отдельно упоминаются HPC-узлы — High Performance Computing) теперь могут разворачивать кластер и не переживать за безопасность коллег. Эксперименты для появления этой фичи проводились в рамках проекта Usernetes — в частности, его наработки используются в k3s.
Stable-фичи
Также некоторые функции, относящиеся к безопасности, достигли стабильного уровня:
-
поддержка внешних поставщиков учетных записей, таких как системы управления ключами (KMS), модули TPM и HSM, а также поставщики краткосрочных токенов;
-
более безопасный API для работы с JWT-токенами;
-
поддержка Service Account Token для CSI-драйверов (Container Storage Interface).
Узлы
Node system swap support
Предложение включить в K8s поддержку свопинга памяти (подкачки страниц) для контейнеров появилось еще в 2015-м, но было отвергнуто. Повторно вопрос поднимали в 2017-м — с тем же итогом. К 2021-му сообщество наконец-таки созрело до того, чтобы реализовать альфа-версию Node system swap support (KEP-2400). Она помогает более гибко управлять производительностью узлов и контейнеров: swapping доступен на уровне хоста, узлов и конкретных рабочих нагрузок, а контролируется kubelet’ом.
Важную роль в добавлении функции сыграло расширение сценариев использования свопинга. В частности, авторы указывают на появление алгоритмов управления памятью вроде oomd, которые решают проблему out of memory в пользовательском пространстве (userspace). Для его корректной работы нужна поддержка свопинга.
Еще один распространенный сценарий — длительно работающее ПО (long-running applications). Например, среды выполнения Java и Node.js используют свопинг для улучшения производительности приложений.
Где еще может быть полезен свопинг:
-
on-premise и bare metal-инсталляции, когда наращивание памяти — недешевая и негибкая процедура;
-
развертывание кластера локально на хосте с быстрыми дисками — например, на ноутбуке с SSD;
-
развертывание кластера на устройствах с малым объемом ОЗУ.
Также подкачка страниц помогает снизить издержки при запуске кластера на виртуальных машинах (ВМ), например, через kubevirt. Некоторые рабочие нагрузки на ВМ периодически требуют дополнительной памяти, которая выделяется автоматически и иногда в больших количествах. Свопинг помогает избежать необязательного overhead’а во время скачкообразного потребления RAM.
New CPU Manager Policies
Важное обновление в политиках управления ресурсами ЦПУ: с помощью опций CPU Manager теперь можно более тонко распределять ресурсы процессора между рабочими нагрузками. В первую очередь новая фича пригодится для развертывания ПО, которое чувствительно к задержкам — например, приложений типа DPDK (Data Plane Development Kit). В то же время у приложений, которые не адаптированы под SMT (одновременную многопоточность), будет меньший приоритет, чем у SMT-native.
Текущая политика static
распределяет ядра процессора между контейнерами без надежной гарантии того, что определенный контейнер действительно получит необходимые ресурсы. При этом, если разные контейнеры делят одно и то же физическое ядро, распределение его ресурсов между контейнерами невозможно предсказать — как и возникновение задержек. Для подобных ситуаций придумали метафору «шумные соседи» (noisy neighbors). Новые политики CPU Manager решают эту проблему.
Фича пока представлена в альфа-версии. Планируется, что она станет бета-версией в 1.24, стабильной — в 1.25. Инициатор KEP’а — сотрудник Red Hat Франческо Романи (Francesco Romani) — в этом треде подробно обосновывает необходимость нововведения.
Memory QoS with cgroups v2
В релизе 1.22 появились сразу две функции в статусе альфа, которые связаны с механизмом организации процессов cgroups v2: его непосредственная поддержка, а также поддержка Memory QoS. (Об особенностях cgroups v2, представленных в Linux 2.6.24, можно почитать, например, здесь.)
Первые наработки по поддержке cgroups v2 появились ещё раньше, во времена релиза Kubernetes 1.18, но только теперь они получили всё необходимое (включая правки в документации) для начала применения.
QoS же ранее был доступен только для регулирования ресурсов CPU (например, через параметр cpu_shares
), а теперь — и для памяти.
Для настройки Memory QoS доступно несколько параметров:
-
memory.min
— минимальный объем памяти, который cgroups всегда должен сохранять; -
memory.max
— максимальный, жёсткий предел по использованию памяти (финальный механизм защиты); -
memory.low
— защита памяти типа best-effort, т.е. «мягкая гарантия» того, что, если cgroup и все его потомки находятся ниже этого порога, эта память cgroup не будет освобождена (если только она не может быть получена из незащищенных cgroup); -
memory.high
— если использование памяти превышает этот уровень, процессы cgroup throttle’ятся и принудительно высвобождаются.
Beta- и Stable-фичи
В предыдущем релизе появилась возможность менять размер томов emptyDir
, которые хранятся в оперативной памяти. Теперь эта функция перешла в бета-версию.
Поддержка HugePages в downward API (KEP-1967) тоже получила повышение до уровня бета.
Функции, которые достигли версии stable:
-
поддержка HugePages на уровне контейнеров и возможность запрашивать страницы разного размера;
-
возможность задавать FQDN (Fully Qualified Domain Name) для хоста pod'а, что улучшает совместимость устаревших приложений с K8s.
Сеть
Expanded DNS configuration
Новая функция Expanded DNS configuration в альфа-версии расширяет возможности для настройки DNS. Теперь в K8s можно использовать больше путей поиска DNS и увеличить список этих путей, чтобы не отставать от последних тенденций DNS-сервисов в преобразовании доменных имен.
После активации feature gate MaxDNSSearchPathsExpanded
меняются два параметра в настройках DNS:
-
MaxDNSSearchPaths
увеличивается с 6 до 32; -
MaxDNSSearchListChars
увеличивается с 256 до 2048.
Kube-proxy handling terminating endpoints
Сейчас, если сервис сконфигурирован с параметром externalTrafficPolicy=Local
, и на узле нет endpoint'ов в статусе Ready, то внешний трафик до сервиса, попавший на узел, будет отброшен. При таком подходе во время непрерывных обновлений (rolling updates) возможны простои.
Проблема решена благодаря реализации новой фичи «мягкого» управления трафиком — Graceful Termination for Local External Traffic Policy (пока тоже в альфе). Теперь во время обновления приложения внешний трафик до сервиса, попавший на узел, направляется на endpoint'ы в статусе Ready, а если таковых нет — на Not ready (Terminating) endpoint'ы. Это гарантирует, что трафик не будет отброшен между моментом, когда узел не проходит проверку работоспособности (нет endpoint’ов), и моментом, когда он удаляется из пула узлов балансировщика нагрузки.
Beta- и Stable-фичи
Бета-версий достигли два улучшения для сервисов типа LoadBalancer: возможность отключать NodePorts и возможность назначать один порт разным протоколам.
Поддержка режима dual-stack IPv4/IPv6 (KEP-563) также повысилась в статусе до бета.
Функции, которые перешли на уровень stable:
-
API EndpointSlice, который заменил предыдущий Core/V1 Endpoints;
-
поле
AppProtocol
в Services и Endpoints (реализация была полностью готова в прошлых релизах, но теперь завершили формальную стабилизацию, убрав соответствующий feature gate).
Также обратите внимание, что версия v1beta1 для Ingress API объявлена устаревшей (теперь используется v1).
Приложения
Job tracking without lingering Pods
Существующий Job-контроллер завершает job’ы постепенно, не удаляя pod’ы до тех пор, пока job’ы окончательно не завершатся. Это помогает контроллеру точнее отслеживать статус job. Ресурсы кластера освобождаются только после окончательного удаления pod’ов.
С новой функцией в альфа-версии job’ы получили возможность сразу удалять неиспользуемые pod’ы, чтобы быстрее освобождать ресурсы. Подробнее о новом алгоритме можно узнать в KEP-2307.
Allow DaemonSets to surge during update like Deployments
Поддержка опции Surge, т.е. «наращивания», для плавающих обновлений DaemonSet (RollingUpdateStrategy
) появилась недавно, в релизе Kubernetes 1.20. Теперь фича перешла в статус бета. Работает функция примерно по тому же принципу, что в Deployment’е: при обновлениях типа RollingUpdate
в дополнение к рабочим pod’ам запускаются «запасные», которые минимизируют возможный простой DaemonSet’ов. Простой может возникнуть, например, при скачивании и установке нового образа, потому что происходит это не мгновенно. Нужное количество дополнительных pod’ов задается в поле maxSurge
— в «штуках», либо в процентах.
Add minReadySeconds to Statefulsets
И ещё одно новшество в альфа-версии — опция minReadySeconds для StatefulSets. Она позволяет указывать минимальное количество секунд, за которое новый созданный Pod должен стать Ready (при условии, что ни один из его контейнеров не упал).
Stable-фичи
-
CronJob API наконец-то признан стабильным (спустя 4 года с момента релиза в Kubernetes 1.8). По итогам продолжительного использования функции в альфа- и бета-статусах код CronJob API оптимизировали, чтобы улучшить масштабируемость и добавить новые метрики.
-
PodDisruptionBudget — еще одна фича-«ветеран», представленная как альфа-версия в Kubernetes 1.4 и стабилизированная только в 1.21. В нынешнем релизе стабильным признан родственный подресурс
Eviction
, который отвечает за вытеснение pod’ов. Именно он используется компонентами, которые хотят удалить pod’ы из-за нарушения ими бюджета.
Другие улучшения
API Server Tracing
Сейчас трассировка API-сервера в K8s довольно ограниченная: можно анализировать задержки операций и выявлять те, что превышают установленный лимит. Новая фича в альфа-версии — API Server Tracing (KEP-647) — предлагает расширить эти возможности с помощью стандарта распределенного трейсинга и мониторинга OpenTelemetry. Коллектор OpenTelemetry умеет собирать метрики и трейсы из множества источников и транслировать их в нужный пользователю формат: Prometheus, Jaeger, VictoriaMetrics и т. д.
Реализация в K8s подразумевает запуск коллектора OpenTelemetry в отдельном контейнере в качестве sidecar’а, DaemonSet’а или Deployment’а для API Server. Возможна комбинация, при которой DaemonSet собирает трейсы и пересылает их в Deployment для дальнейшего агрегирования в БД.
Появление фичи логично и ожидаемо: сложно добиться приемлемого уровня observability компонентов кластера, анализируя только лишь метрики и логи. Полноценная трассировка API Server облегчит диагностику проблем.
New RWO access mode
Одно из нововведений, которое относится к хранилищам, — режим доступа ReadWriteOncePod PersistentVolume (KEP-2485). RWOP работает для PersistentVolumes
, которым нужно ограничить доступ к одиночному pod’у на одиночном узле. Для сравнения, существующий режим ReadWriteOnce (RWO) ограничивает доступ к одиночному узлу, но разрешает одновременный доступ к этому узлу из нескольких pod’ов.
Windows Privileged Containers and Host Networking Mode
Привилегированные контейнеры и возможность назначать таким контейнерам сеть хоста — опции, которые давно доступны в Kubernetes пользователям Linux. Привилегированные контейнеры используются, например, для запуска kube-proxy (через kubeadm), для некоторых задач хранения и сетевого взаимодействия, а также в других сценариях, когда нужен root-доступ к хосту. Многие из этих сценариев актуальны и для пользователей Windows. Новая фича Windows Privileged Containers and Host Networking Mode (KEP-1981) призвана удовлетворить этот запрос (пока в альфа-версии).
Kubeadm Config file graduation
Продолжается оптимизация формата конфигурационного файла kubeadm (KEP-970). Основная проблема с конфигом была в том, что количество опций, которые в нем настраиваются, со временем сильно выросло; в то же время количество параметров, которые можно регулировать через CLI, осталось прежним. В результате файл конфигурации был единственным способом создать кластер с несколькими специфическими вариантами использования.
Фича, которая расширила возможности настройки kubeadm, была представлена в альфа-версии в 1.15, и теперь получила очередные улучшения в рамках бета-версии (v1beta3). Среди изменений, которые появились в обновленной версии:
-
удалены устаревшия поля
ClusterConfiguration.useHyperKubeImage
иClusterConfiguration.DNS.Type
; -
добавлены поля
InitConfiguration.SkipPhases
иJoinConfiguration.SkipPhases
, чтобы пропускать ряд фаз во время выполнения команд для инициализации узла и присоединения к кластеру K8s (kubeadm init/join
); -
добавлены поля
InitConfiguration.Patches.Directory
иJoinConfiguration.Patches.Directory
. В них можно указывать директорию с патчами для компонентов, которые разворачиваются с помощью kubeadm.
Beta- и Stable-фичи
Статус бета получила функция Priority and Fairness for API Server Requests (KEP-1040). Она улучшила механизм приоритизации и обработки запросов, которые поступают в API Server. Предыдущий механизм был слишком грубый, из-за чего могли отфильтровываться важные запросы.
Новый алгоритм активируется с помощью feature gate APIPriorityAndFairness
. Типы запросов и приоритеты определяются в объекте FlowSchema
. Пример настройки для низкоприоритетного сервиса (сборщика мусора):
kind: FlowSchema
meta:
name: system-low
spec:
matchingPriority: 900
requestPriority:
name: system-low
flowDistinguisher:
source: user
match:
- and:
- equals:
field: user
value: system:controller:garbage-collector
Функции, которые достигли версии stable в Kubernetes 1.22:
-
Server-side Apply, которая перенесла логику работы
kubectl apply
и декларативного управления объектами в apiserver; -
механизм предупреждений, который реализован в виде информационных заголовков в API server: когда API был представлен, когда — устареет, когда — будет удален;
-
автоматически назначаемые неизменные лейблы вида
kubernetes.io/metadata.name
для пространств имен, чтобы можно было гарантированно выбирать их при любых обстоятельствах; -
поддержка CSI-плагинов для Windows.
Прочие изменения
Обновления в зависимостях Kubernetes:
-
cri-tools 1.21.0;
-
плагины CNI (Container Networking Interface) 0.9.1, Calico 3.19.1, CoreDNS 1.8.4;
-
etcd 3.5.0;
-
используемая версия Go — 1.16.6.
P. S.
Читайте также в нашем блоге:
Автор: Oleg Zinovyev