Kubernetes 1.20: обзор основных новшеств

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



Информация, использованная для подготовки этого материала, взята из таблицы Kubernetes enhancements tracking, CHANGELOG-1.20, обзора Sysdig, а также соответствующих issues, pull requests, Kubernetes Enhancement Proposals (KEP).

Docker как deprecated


Пожалуй, главной темой этого релиза стал отказ от Docker в kubelet, о чем стало известно широкой общественности благодаря твиту Davanum Srinivas — инженера из VMware, который и стал непосредственным автором самого изменения:


Если говорить о технической сути изменения и очень кратко, то, пожалуй, достаточно демонстрации таких двух схем (заимствованы из публикации Tariq Islam — Cloud Solutions Engineer из Google).

Запуск контейнеров в Kubernetes до сих пор выглядел так:



Но мир не стоит на месте, а уж cloud native-мир со всеми его контейнерами, механизмами взаимодействия с ними и стандартами — подавно. Поэтому длинная цепочка упрощается до следующей:



Подробнее останавливаться на этом событии не будем, поскольку уже переводили для своего блога официальное заявление проекта Kubernetes по этому поводу: «Не паникуйте: Kubernetes и Docker». Кроме того, в интернете легко найти другие многочисленные материалы по теме. Среди них:

  • развёрнутый комментарий Tim Hockin (одного из самых известных разработчиков Kubernetes) на Reddit;
  • лаконичный ответ Benjamin Elder (другого разработчика Kubernetes) на GitHub;
  • заявление самой Docker Inc;
  • анонс от Mirantis, которая год назад купила бизнес Docker Enterprise, а теперь собирается продолжить развитие dockershim в Kubernetes своими силами.

Узлы Kubernetes (kubelets)


И продолжим со связанного с dockershim изменения — повышения статуса поддержки CRI (Container Runtime Interface) до бета-версии (KEP-2040). Исполняемые среды для контейнеров на базе интерфейса CRI — CRI-O и containerd — уже долгое время (более года) используются разными компаниями в production с текущим API, поэтому авторы данного изменения «хотят показать пользователям, что CRI API готово к production и можно не бояться переходить с dockershim, который признан deprecated». Когда же CRI планируют перевести на итоговый уровень стабильности (stable/GA), пока не сообщается.

Попутно стоит отметить, что поддержка cri-containerd для Windows объявлена стабильной (GA для Linux-версии была объявлена более 2 лет назад).

Новая возможность для kubelet'ов — Graceful Node Shutdown (KEP-2000) — призвана сообщать им о завершении работы узла и вызывать корректное, «мягкое» (graceful) выключение соответствующих pod'ов. Предусматривается обработка команд shutdown -h, systemctl poweroff, физического нажатия на кнопку питания и его аналогов для виртуальных машин и облачных инстансов (например, gcloud compute instances stop). В реализации отслеживаются ACPI-сигналы, предусмотрено взаимодействие с systemd-logind, а в конфигурации kubelet для этого появился параметр ShutdownGracePeriod (по умолчанию равен 0). Текущая версия — альфа, повышение до беты ожидается в Kubernetes 1.21.

Другая новая фича в альфа-версии — изменяемый размер томов, хранимых в оперативной памяти (KEP-1967). Сейчас размер для томов emptyDir, которые хранятся в оперативной памяти (tmpfs), по умолчанию выделяется в объеме 50% памяти Linux-хоста. Однако это вызывает ряд сложностей (при активном использовании /dev/shm и других задач вроде AI/ML, а также в переносимости), которые призвано решить нововведение. Оно устанавливает размер таких томов по умолчанию равным объёму выделяемой pod'у памяти и позволяет изменять это значение на меньшие.

Многие фичи переведены в статус стабильных (GA):

  • ресурс RuntimeClass с параметрами исполняемой среды для контейнеров;
  • поддержка в kubelet сторонних плагинов для мониторинга устройств;
  • изоляция PID'ов от узла к pod'ам;
  • проба startupProbe.

Но и это ещё не всё:

  • kubelet научили учитывать таймаут для вызова проб (альфа-версия, KEP-1972);
  • Node Topology Manager, хоть и остался в бета-версии, получил новую возможность — scope, — определяющую уровень, на котором требуется выравнивать ресурсы (например, pod или container);
  • добавлена поддержка HugePages в downward API (KEP-2053): теперь этот ресурс виден pod'ам так же, как и CPU, память и другие (пока в альфа-версии).

Аутентификация и безопасность


Новая возможность на пересечении sig-auth и sig-storage — альфа-версия поддержки Service Account Token для CSI-драйверов (KEP-1855). Идея в том, чтобы CSI-драйверы могли запрашивать и получать у kubelet'а токены ServiceAccount для pod'ов, которым они монтируют тома, — в противовес существующему подходу с прямым считыванием токенов из файловой системы. Эти токены действительны ограниченное время, поэтому у драйверов также предусмотрена возможность повторного вызова NodePublishVolume для монтирования томов.

Другое улучшение безопасности затрагивает инфраструктуру для сборки и релизов Kubernetes: представлена защита от логирования секретов на основе статического анализа (KEP-1933). Появление такого механизма мотивируется результатами аудита безопасности кодовой базы K8s, проведенного американской компанией Trail of Bits в прошлом году на версии K8s 1.13.4. Его авторы заключают, что конфиденциальная информация не должна открыто появляться в логах. Для реализации соответствующего статического анализа используется утилита go-flow-levee от Google, вызываемая в системе Prow при тестировании pull-запросов, поступающих в репозитории Kubernetes.


Фрагмент итогов аудита Kubernetes от Trail of Bits

Другая инициатива, связанная с логами и безопасностью, — logs sanitization (KEP-1753), т.е. постоянная очистка логов от потенциально опасных данных. В его рамках решаются следующие задачи: предотвращение попадания в логи известных видов конфиденциальных данных, упрощённая возможность добавлять новые источники таких данных в фильтры и ограничение влияния этих процессов на общую производительность.

Для client-go credential plugins добавили поддержку переменной окружения KUBERNETES_EXEC_INFO: через неё можно (опционально) передавать информацию о кластере, для которого плагин получает учётные данные. Сама поддержка таких внешних провайдеров осталось в бета-версии, их стабилизация отложена до следующих релизов Kubernetes.

Наконец, поддержка TokenRequest и TokenRequestProjection (из KEP-1205) для того, чтобы pod'ы могли запрашивать ServiceAccount-токены, объявлена стабильной. Но работа над интеграцией TokenRequest API и Kubelet в целом ещё не завершена: другие её изменения ждут более стабильных версий.

Сети


В альфа-версии стало возможным отключать NodePorts для сервисов с типом LoadBalancer (KEP-1864). До сих пор для каждого порта сервиса LoadBalancer в Kubernetes автоматически выделялся порт узла. Хотя это действительно, как правило, необходимо, но в жизни так происходит не всегда: примерами подобных исключений являются MetalLB и kube-router. Теперь в Service.Spec есть специальное булево поле allocateLoadBalancerNodePort, регулирующее соответствующую настройку.

Достигла своей альфа-версии и другая возможность, связанная с LoadBalancer'ами и развиваемая с начала этого года. Теперь в сервисах LoadBalancer можно определять одни и те же порты для разных протоколов (KEP-1435). Например, стала доступной такая конфигурация:

apiVersion: v1
kind: Service
metadata:
  name: mixed-protocol
spec:
  type: LoadBalancer
  ports:
    - name: dns-udp
      port: 53
      protocol: UDP
    - name: dns-tcp
      port: 53
      protocol: TCP
  selector:
    app: my-dns-server

Набор допустимых протоколов при этом определяется облачным провайдером.

Работа над поддержкой двойного сетевого стека IPv4/IPv6 продолжается. Хоть эта фича и осталась в альфа-версии, она принесла значительные обновления, которые появились как ответ на запросы сообщества. В частности, появилась возможность переключения сервисов с single-stack на dual-stack — параметром ipFamilyPolicy в спецификации, который принимает говорящие за себя значения: SingleStack, PreferDualStack, RequireDualStack. Пример конфигурации для сервиса с dual-stack:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app: MyApp
spec:
  ipFamilyPolicy: PreferDualStack
  ipFamilies:
  - IPv6
  type: LoadBalancer
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80

Подробности по использованию dual-stack см. в KEP и документации.

В EndpointSlice API добавлена возможность отслеживания endpoint'ов, которые завершают свою работу (KEP-1672). Для этого в структуру EndpointConditions вводится новое поле (terminating), информирующее о том, что endpoint сейчас прекращает свою работу, — вместо отслеживания статусов pod'ов, связанных с endpoint'ом, как было раньше.

Среди других сетевых новшеств:

  • возможность определять имя хоста pod'а как FQDN (KEP-1797, поле setHostnameAsFQDN) переведена в бета-версию;
  • поддержка протокола SCTP объявлена стабильной (GA) — см. документацию на сайте;
  • поддержка поля AppProtocol (KEP-1507) как унифицированного способа определять протокол у приложения объявлена стабильной (документация на сайте).

Хранилища


Функция создания/восстановления снапшотов томов для CSI-драйверов (KEP-177) объявлена стабильной. Документация не изменилась и доступна на прежнем месте.

Других изменений в sig-storage не так много:

  • возможность для CSI-драйверов определять права доступа на основе FSGroup перешла в бета-версию;
  • возможность пропускать рекурсивную смену владельца/прав перед bind-монтированием тома в контейнер (для лучшей производительности) тоже объявлена бетой.

Прочие изменения


Новое улучшение для Horizontal Pod Autoscaler добавляет возможность учёта потребления ресурсов отдельными контейнерами для принятия решений о масштабировании. Сейчас вместо этого для горизонтального масштабирования используются общие значения со всех pod'ов, однако бывают сценарии, где подобные решения не являются оптимальными, т.е. нет прямой корреляции потребления ресурсов отдельными контейнерами на общее. Авторы приводят такие примеры:

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

Новый подход, пока реализованный как альфа-версия и описанный в этом KEP, вводит дополнительный источник метрики ContainerResourceMetricSource (вдобавок к существующему ResourceMetricSource).

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

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: mission-critical
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mission-critical
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: ContainerResource
    resource:
      name: cpu
      container: application
      target:
        type: Utilization
        averageUtilization: 30

Пополнение в метриках — альфа-версия Pod Resource Request Metrics (KEP-1748). Идея заключается в создании достаточного количества метрик «из коробки», необходимых для планирования ресурсов кластера и простого представления модели ресурсов Kubernetes. Для её реализации в kube-scheduler появились новые метрики по запрашиваемым ресурсам (kube_pod_resource_requests) и желаемым лимитам (kube_pod_resource_limits) для всех запущенных pod'ов — они активируются по HTTP на /metrics/resources при использовании флага --show-hidden-metrics-for-version=1.20.

С новой фичей, названной Kubelet Credential Provider или Out-of-Tree Credential Providers (KEP), Kubelet получил возможность динамически получать учетные данные (credentials) для реестров контейнерных образов (container registry), вызывая сторонние плагины — специфичные для облачных провайдеров биинарники. Взаимодействие с плагинами происходит по Kubernetes API через stdio. Вынос специфичного кода провайдеров из ядра Kubernetes следует общему тренду смены in-tree на out-of-tree для растущей кодовой базы проекта. Текущая реализация — альфа-версия, подробности — в документации Kubernetes.

  • CronJob API, который до сих пор находился в бета-версии (с релиза Kubernetes 1.8, а это более 3 лет назад!), решили продвинуть до стабильного уровня, однако одновременно с этим его код переписывают с целью улучшить масштабируемость (использовать информеры вместо polling) и добавить метрики (пропускная способность контроллера, задержки и т.п.) — для активации необходимо включить feature gate под названием CronJobControllerV2;
  • представленный в K8s 1.18 механизм API Priority and Fairness (APF) для более тонкого контролирования ограничения запросов к API-серверу (с продвинутой системой приоритетов) переведён в бета-версию;
  • команда kubectl debug перешла в бета-версию (все вызовы kubectl alpha debug необходимо изменить на kubectl debug);
  • label и taint под названием node-role.kubernetes.io/master, добавляемый kubeadm'ом на узлы, переименован в node-role.kubernetes.io/control-plane;
  • каждому kube-apiserver в HA-кластерах теперь назначаются уникальные идентификаторы, а у котроллеров есть возможность просмотра их списка в кластере (альфа-версия, KEP-1965).

Прочие изменения


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

  • cri-tools 1.19.0;
  • CNI (Container Networking Interface) 0.8.7, Calico 3.15.2;
  • etcd 3.4.13;
  • используемая версия Go — 1.15.5.

Немного статистики


В составе релиза Kubernetes 1.20 — 42 улучшения: 11 перешли в stable, 15 — beta, 16 — alpha.

За время его подготовки — 11 недель с 25 сентября по 9 декабря — в репозиториях внесли свою лепту 967 компаний и 1335 индивидуумов (44 из них сделали это впервые) из 26 стран.

В число этих компаний попал и «Флант» с несколькими contributions (см. «Flant» в этом списке).

Топ-10 компаний по числу contributions (включают в себя коммиты, PR, issues и т.п.) для последнего релиза выглядит следующим образом:

  1. Google (32284);
  2. VMware (17598);
  3. Red Hat (10935);
  4. Microsoft (7062);
  5. IBM (5857);
  6. The Scale Factory (2151);
  7. Samsung SDS (1471);
  8. Glassdoor (1406);
  9. SUSE (1319);
  10. Kubermatic (1300).

P.S.


Разработчики Kubernetes присвоили релизу v1.20 имя «raddest» (английский сленг, который переводится как «отличный, замечательный, классный»). Потому что, несмотря на сложный для всех год, сообществу удалось привнести рекордное число значимых изменений в этот релиз.

А этот кот стал официальным логотипом для Kubernetes 1.20:



P.P.S.


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

  • «Kubernetes 1.19: обзор основных новшеств»;
  • «Kubernetes 1.18: обзор основных новшеств»;
  • «Kubernetes 1.17: обзор основных новшеств».
Источник: https://habr.com/ru/company/flant/blog/530924/


Интересные статьи

Интересные статьи

Привет, меня зовут Иван, и сегодня я расскажу как управлять приложением Tarantool Cartridge в кластере Kubernetes при помощи Tarantool Operator. Мы пройдем полный цикл от разработки до ...
Привет, Хабр! Наша прошлая статья, в которой мы анализировали рынок вакансий и зарплат профессии «аналитик данных», была очень тепло встречена. Поэтому мы решили продолжить. Встречайте об...
Для полного освоения Kubernetes нужно знать различные способы масштабирования кластерных ресурсов: по словам разработчиков системы, это одна из главных задач Kubernetes. Мы подготовили высокоур...
Битрикс24 — популярная в малом бизнесе CRM c большими возможностями даже на бесплатном тарифе. Благодаря API Битрикс24 (даже в облачной редакции) можно легко интегрировать с другими системами.
Мы публикуем видео с прошедшего мероприятия. Приятного просмотра.