Вчерашний анонс официальной поддержки Kubernetes компанией Docker в своих продуктах — идеальный повод продолжить одну из наших последних публикаций, посвящённых CRI-O как альтернативному подходу к запуску контейнеров в Kubernetes. В ней уже затрагивались тема cri-containerd — своеобразного «ответа Docker» на попытки Open Source-сообщества уйти от единственного поставщика технологии для контейнеров. Чем же вызван новый поворот в жизни Docker и как его закономерность подтверждается в недавней истории проектов Moby?

Свобода выбора: и от Kubernetes, и от Docker


Kubernetes как PaaS для работы с контейнерами изначально создавалась с идеей предоставления своим пользователям свободы выбора реализаций тех или иных функций платформы. (Подробнее об этом и о том, почему Kubernetes — это больше, чем PaaS, мы писали в отдельной статье.) Технология, применяемая для запуска контейнеров, — один из примеров таких реализаций. Поскольку Open Source-мир контейнеров не ограничен Docker'ом, уже долгое время в Kubernetes есть возможность использования rkt в качестве исполняемой среды для контейнеров. Да, по большому счёту такая возможность появилась благодаря усилиям (и в интересах) одной конкретной компании — CoreOS, — но с этого года rkt входит в число проектов, поддерживаемых некоммерческой организацией CNCF, равно как и её конкурент от Docker — containerd (да и сам Kubernetes развивается в том же фонде).

Тем не менее, по умолчанию в Kubernetes по-прежнему используется вовсе не rkt, а стандарт де-факто в индустрии — Docker. То самое стремление предоставлять пользователям гибкость, «объединившись» с интересами некоторых компаний, привело проект к дальнейшему расширению доступных для выбора исполняемых сред через создание интерфейса Container Runtime Interface (CRI) — он появился с релизом Kubernetes 1.5.

С помощью CRI «подключение» новых контейнерных технологий стало унифицированным и простым, и впервые это было продемонстрировано в рамках проекта CRI-O, подробнее о котором мы писали на прошлой неделе. Формально CRI-O позволяет использовать любую исполняемую среду для контейнеров, совместимую со спецификацией OCI (runtime-spec), а фактически на сегодняшний день поддерживает всем известную runC (проект, отделенный от Docker в 2015 году и ставший эталонной реализацией стандарта OCI) и Clear Containers (от Intel).

Анонсируя поддержку Kubernetes, в Docker подчеркнули, что «философия архитектуры Docker всегда была о предоставлении выбора и гибкости». Так они официально объяснили появление блока Kubernetes в своей платформе, иллюстрируемой 4 слоями:



Сами слои платформы поясняются так (снизу вверх):

  1. containerd как исполняемая среда для контейнеров, соответствующая индустриальному стандарту;
  2. оркестровка Swarm, превращающая группу узлов в распределённую систему;
  3. Docker Community Edition, предлагающая разработчикам простой workflow для создания и доставки приложений в контейнерах;
  4. Docker Enterprise Edition для управления полным циклом безопасной поставки программного обеспечения и запуска контейнеров в production.

И вот пункт «оркестровка Swarm» отныне формулируется как «оркестровка Swarm или Kubernetes», а в дальнейшем (кто знает?) может распространиться и на другие решения.

В официальном анонсе компании была озвучена и другая причина интеграции поддержки Kubernetes в платформу Docker — пожелания её клиентов. Пользователи Docker «или уже спроектировали сервисы для работы на Kubernetes, или хотят Kubernetes из-за определённых нужных им возможностей». Если посмотреть на ситуацию более объективно, то очевидно, что Kubernetes, как и Docker в своё время, становится «индустриальным стандартом». А поскольку конечные пользователи скорее выбирают инструмент оркестровки, чем конкретную нижележащую технологию контейнеров, единственный вариант сохранить (и расширять) аудиторию для Docker — соответствовать потребностям той самой индустрии. Каковы же рыночные перспективы прямого конкурента Kubernetes, разрабатываемого внутри Docker — Swarm, — вопрос, который остаётся открытым и должен быть уже в скором времени прояснён политикой компании.

Moby и Kubernetes


Все слои платформы Docker собираются с помощью специального Open Source-проекта Moby, подробнее о котором мы тоже писали.



Если вкратце, то с его помощью Docker стремится сохранить своё лидерство в экосистеме контейнеров, продвигая его в сообществе как стандарт для «сборки систем на базе контейнеров». Формально Moby также представляет и все upstream-проекты, используемые для сборки платформы Docker. (В общей сложности на них приходится средний показатель в 8800 pull-запросов в год.)

Рассказывая об участии Moby в анонсированной поддержке Kubernetes для Docker, авторы начинают с того, что эти работы начались не вчера, а ведутся уже около года. И основные события представляются следующим образом:



Подробности о «тесных взаимоотношениях» Moby и Kubernetes приводятся на примере некоторых проектов, образующих платформу Docker и не только.

containerd


containerd в прошлом — это компонент Docker, реализующий исполняемую среду для запуска контейнеров:

image

Как и в случае с runC, его постигла участь отделения от Docker в самостоятельный Open Source-проект (ранее в этом году он был передан и принят в фонд CNCF). Его актуальная на сегодня версия — 1.0.0-beta.2, а финальный релиз 1.0.0 должен случиться уже совсем скоро. Будучи одним из базовых компонентов Docker, проект стремится получить более широкое признание, и одной из главных инициатив, направленных на его распространение, стал cri-containerd (инициирован в апреле этого года).

Являясь одной из первых реализаций уже упомянутого интерфейса Kubernetes CRI, cri-containerd претендует на то, чтобы стать популярным решением для запуска контейнеров в Kubernetes в эпоху, когда «тяжёлый» Docker не будет вариантом по умолчанию для пользователей K8s. Текущий статус — альфа-версия, имеющая полный набор возможностей и проходящая «процесс финальной стабилизации». 14 сентября Liu Lantao из Google рассказывал на Moby Summit в Лос-Анджелесе о состоянии cri-containerd, отметив, что проект «очень хорошо» соответствует требованиям CRI и Kubernetes, а также пообещав выпуск бета-версии к концу года.

Вот как изменится схема участия containerd в Kubernetes вместе с cri-containerd:

Примечание к иллюстрации: dockershim — текущая реализация runtime для Docker-контейнеров в K8s.

Более детальная схема работы cri-containerd:

Попробовать cri-containerd в действии можно с помощью различных инструкций:


LinuxKit


LinuxKit — это анонсированная одновременно с Moby утилита для сборки компактных Linux-систем для контейнеров. Как уточняется в описании проекта, LinuxKit «спроектирован для сборки и запуска кластерных приложений с помощью инструментов оркестровки контейнеров, таких как Docker или Kubernetes, но не ограниченных ими».

В документации проекта содержится статья «Kubernetes and LinuxKit», описывающая создание минимальных образов ОС с Kubernetes. По умолчанию в устанавливаемом в эти образы K8s используется Docker Engine, а для перехода на cri-containerd достаточно добавить одну команду в процессе сборки.

InfraKit


InfraKit — набор утилит для оркестровки инфраструктуры, призванный сделать её «самоуправляемой и самовосстанавливающейся». Технически проект состоит из набора небольших контроллеров, называемых плагинами и реализующих различные интерфейсы (Service Provider Interfaces, SPI — подробнее см. в документации). Один из этих интерфейсов — Flavor SPI — отвечает за специфичные для приложения конфигурации и проверки его состояния. Примерами плагинов типа Flavor являются Swarm и Kubernetes, ответственные за проверку наличия узла в кластере, приостановку приёма задач узлом от планировщика и т.п.

Документация по плагину Kubernetes в InfraKit совсем недавно была сведена в этом README. Также доступно 17-минутное видео от ведущего разработчика проекта (David Chung) с демонстрацией запуска кластера Kubernetes на AWS с помощью InfraKit и AWS CloudFormation. Загрузочный (bootstrap) узел выполняет длинную последовательность из действий от установки последней версии Docker Engine до обновления лейблов для монтирования и форматирования томов. Скрипт загрузки сгенерирован плагинами и шаблонами InfraKit.

libnetwork


libnetwork — реализация сетевого интерфейса Container Network Model (CNM) для контейнеров, используемая в Docker. CNM по своей сути является прямым конкурентом Container Networking Interface (CNI), о чём мы писали в этой статье. Kubernetes стал одним из ранних пользователей CNI, предложив всем, кто намере развивать свои сетевые интерфейсы, делать это плагинами к CNI, которые уже и подключаются к Kubernetes.


Рассказывая в прошлом месяце о стандартах для контейнеров, Scott McCarty из Red Hat назвал CNM «стандартом де-факто», потому что «многие вендоры сетевых решений создают утилиты, подходящие и для CNI, и для CNM».

Раз в Docker намерены оставаться с CNM вместо CNI, какой вариант им остаётся для интеграции с Kubernetes? Правильно, сделать плагины к CNI, реализующие поддержку libnetwork. Процесс уже запущен, но в master-ветку пока не попал.

Отрадно видеть и приводимый в Docker пример «движения в обратную сторону» — с выгодой для всех пользователей upstream-версии Kubernetes: представленная в K8s 1.8 альфа-версия поддержки режима IPVS для балансировки нагрузки была создана на основе кода из libnetwork, изначально написанного для Docker Swarm.

Notary


Notary — проект Docker для подписи и верификации контейнеров, основанный на наработках The Update Framework (TUF) и написанный на Go (вместо Python у TUF). В начале этого месяца было инициировано голосование о включении Notary и TUF в инкубатор проектов CNCF. Многие представители комитета из фонда уже поддержали его, но окончательное решение пока не принято. Никакой формальной привязки к K8s у Notary ещё нет, но в Docker ожидают, что после его принятия в CNCF «будет реализована прямая интеграция с другими проектами CNCF, такими как Kubernetes».

libentitlement


Библиотека libentitlement предназначена для высокоуровневого управлениями правами в контейнерах. Так называемые entitlements разрешают/запрещают различные функции безопасности в профиле конфигурации, а библиотека призвана управлять этими профилями для контейнеров. Со списком предлагаемых к реализации entitlements можно ознакомиться здесь.

Проект ещё молод — первый коммит в его репозитории состоялся в мае. Со слов Docker, разработка libentitlement ведётся при участии сообщества Kubernetes. В документации проекта заложен перечень entitlements по умолчанию для Kubernetes, однако на данный момент там значится только многообещающее «TBD».

Подводя итог


Мир контейнеров стал интересным местом для конкуренции и одновременного сотрудничества Open Source-проектов и стоящих за ними компаний.

Даже не имея Kubernetes среди интегрированных в платформу Docker средств оркестровки, инженеры этой компании уже долгое время так или иначе работали над проектами, специально ориентированными на K8s или тесно переплетёнными с его экосистемой.

Формальный анонс поддержки Kubernetes — это значимое и приятное событие для сообщества, подтверждающее слова компании о свободе выбора. Для самой Docker это во многом вынужденная мера, подобная недавнему схожему случаю с Mesosphere.

С некоторыми подробностями о том, что означает пресловутая поддержка Kubernetes для конечного пользователя продуктов Docker, можно ознакомиться в соответствующих записях блога компании: Docker CE for Mac and Windows, Docker EE.

P.S.


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

Комментарии (2)


  1. amarao
    18.10.2017 12:40

    Я смотрю на все эти танцы вокруг того «кто сверху» и становится грустно. Из всего этого только runc выглядит как разумная программа, решающая одну проблему, но решающая её хорошо. Все остальные пытаются одновременно готовить кофе и травить тараканов. На выходе тараканы не довольны пережаренным кофе, а постетители жалуются на слабоватый дуст.


  1. livelace
    18.10.2017 12:44

    Всё очень и очень просто. Разработчикам Kubernetes/Openshift категорически надоело исправлять то, что с легкой руки ломал Docker в угоду своим целям. Предпосылки по замене runtime были еще до CRI-O. Сам Docker, выпустив джина из бутылки, всячески пытается запргынуть в уходящий поезд оркестрации контейнеров (попытки слабые, если честно).