- PVSM.RU - https://www.pvsm.ru -

Зачем нужен containerd и почему его отделили от Docker

В середине марта стало известно, что компания Docker предложила [1] свой проект containerd независимому фонду Cloud Native Computing Foundation (кстати, произошло это одновременно [2] с rkt от CoreOS). Событие последовало за обещанием компании, данным в декабре прошлого года, когда containerd был официально отделён от Docker Engine. Что же это за компонент и зачем его отделили?

Зачем нужен containerd и почему его отделили от Docker - 1

Как устроен containerd

containerd [3] — это бывшая часть Docker, а ныне самостоятельное решение, реализующее исполняемую среду для запуска контейнеров. При его создании, как утверждают разработчики, они стремились к простоте, надёжности и портируемости.

«Физически» это демон на хост-системе, который управляет всем жизненным циклом контейнера: от получения и хранения образа до запуска контейнера (через runC — подробнее см. ниже) и контролирования его работы. С демоном containerd можно взаимодействовать по низкоуровневому gRPC API через локальный UNIX-сокет, а для экспериментов и отладки также доступна консольная утилита ctr (она тоже использует gRPC API). Исходный код написан на Go и доступен на GitHub [4] под лицензией Apache License 2.0.

Зачем нужен containerd и почему его отделили от Docker - 2

Основные примитивы, с которыми работает containerd, — это bundles («комплекты») и контейнеры. Запуском контейнеров занимается runC [5] — утилита, написанная на Go, использующая libcontainer и отделённая [6] от Docker в 2015 году. Она работает в соответствии со спецификацией OCI Runtime Specification [7] и запускает контейнеры как свои дочерние процессы. Для запуска требует только корневую файловую систему и конфигурацию (всё остальное: получение образа, его распаковка и т.п. — остаётся для неё «за кадром»).

Bundles содержат конфигурацию, метаданные и данные корневой файловой системы. Они являются дисковым представлением запущенного контейнера (в простейшем случае — это обычный каталог в ФС), которое можно переносить на другие системы, упаковывать и распространять. По сути всё устройство containerd заключается в том, чтобы координировать создание и запуск bundles.

Подробнее об архитектуре

Компоненты containerd образуют следующие подсистемы:

  1. Distribution — сервис, обеспечивающий получение образов контейнеров.
  2. Bundle — сервис, позволяющий извлекать (и упаковывать) bundles из дисковых образов.
  3. Runtime — сервис для запуска bundles (вызывает runC для запуска контейнеров с переданными им параметрами).

Каждая подсистема имеет один или несколько компонентов, реализующих её поведение. Именно к сервисам, предоставляемым подсистемами, и обращаются пользователи containerd через gRPC API.

Компоненты containerd, работающие одновременно с разными подсистемами, называются модулями и представлены следующими:

  • Executor, реализующий непосредственный запуск контейнера.
  • Supervisor, контролирующий и отражающий статус контейнера.
  • Metadata, хранящий метаданные в графовой базе данных.
  • Content, предоставляющий доступ к адресуемому хранилищу контента (постоянных данных).
  • Snapshot, управляющий снапшотами файловой системы для образов контейнера. Аналог graphdriver в сегодняшнем Docker. Слои распаковываются в снапшоты.
  • Events, реализующий событийное поведение и возможность аудита.
  • Metrics, обеспечивающий доступность (по API) метрик различных компонентов.

Всё вместе это выглядит так:
Зачем нужен containerd и почему его отделили от Docker - 3

Как это работает

Схема и её описание взяты из документа containerd/design/architecture [8]:
image

  • В контроллер подсистемы Distribution приходит запрос забрать нужный образ. Он помещает содержимое образа в хранилище контента (Content store), а указатели на имя образа и корневой манифест регистрируются в хранилище метаданных (Metadata store).
  • Когда образ получен, пользователь может (через контроллер Bundle) распаковать образ в bundle. Слои этого образа (полученные из хранилища контента) распаковываются в модуль Snapshot.
  • Когда снапшот корневой системы контейнера готов, контроллер Bundle, используя манифест и конфиг образа, формирует конфигурацию для запуска (в частности, готовится список mount'ов, полученных из модуля Snapshot).
  • Подготовленный bundle передаётся в подсистему Runtime для запуска. Она считывает готовую конфигурацию для создания работающего контейнера.

Роль в Docker, связь с другими компонентами

Вынесение containerd в отдельный проект началось [9] около года назад, когда разработчики Docker предприняли попытку «сделать Docker Engine компактнее, лучше, быстрее и сильнее» и так объясняли свои действия: «Имея автономную среду исполнения вроде runc, мы нуждались ещё в аккуратной точке для интеграции, чтобы добавить runc к общему стеку и управлять сотнями контейнеров».

На момент выделения containerd из Docker (1.12) в плане развития проекта значился «рефакторинг кодовой базы Docker Engine для выноса большей части логики размещения, сетевой работы и хранения на единственном хосте в компонент, предназначенный для многократного использования, который будет применяться в Docker и которым смогут пользоваться другие проекты оркестровки контейнеров и сервисы размещения контейнеров».

Набор функций, выполнение которых поручили containerd, получился следующим:

  • размещение образов в Docker Registry;
  • поддержка сети для создания системных интерфейсов и API для управления сетевым пространством имён контейнера;
  • хранилище (на уровне хоста) для файловых систем образа и контейнера;
  • gRPC API (именно по нему и сам Docker Engine общается с containerd);
  • новый API для метрик в формате Prometheus, используемых внутри и на уровне контейнера;
  • полная поддержка спецификации образов OCI (Open Container Initiative) и эталонной реализации runC.

Так в Docker видят использование будущего containerd 1.0 (его релиз запланирован на июнь 2017 года) внутри Docker Engine:

Зачем нужен containerd и почему его отделили от Docker - 5

Подводя итог, авторы утверждают [10], что в containerd сосредоточены возможности, в которых «нуждается любая ориентированная на контейнеры платформа», и ничего лишнего. По факту это достаточно низкоуровневое решение, взаимодействовать с которым предлагается не конечным разработчикам и пользователям, а более крупным системам, таким как Kubernetes (в рамках Kubelet) и Mesos, а также сервисам вроде Amazon ECS и Google Container Engine. Встраивание в продукты предлагается всё через тот же gRPC API (утилита ctr предназначена только для отладки и экспериментов).

P.S. На прошлой неделе Cloud Native Computing Foundation формально подтвердила [11] принятие containerd в число своих проектов. И в тот же день такая участь постигла [12] проект rkt [13], который решает аналогичные containerd задачи в CoreOS: является реализацией открытой спецификации App Container (appc) и использует формат ACI (Application Container Image) для образов. CNCF будет поддерживать развитие обоих проектов.

Автор: Флант

Источник [14]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/sistemnoe-administrirovanie/251753

Ссылки в тексте:

[1] предложила: https://blog.docker.com/2017/03/docker-donates-containerd-to-cncf/

[2] одновременно: https://www.nixp.ru/news/13965.html

[3] containerd: https://containerd.io/

[4] GitHub: https://github.com/docker/containerd

[5] runC: http://runc.io/

[6] отделённая: https://blog.docker.com/2015/06/runc/

[7] OCI Runtime Specification: https://github.com/opencontainers/runtime-spec

[8] containerd/design/architecture: https://github.com/docker/containerd/blob/master/design/architecture.md

[9] началось: https://blog.docker.com/2016/04/docker-containerd-integration/

[10] утверждают: https://blog.docker.com/2017/01/containerd-livestream-recap/

[11] подтвердила: https://www.cncf.io/announcement/2017/03/29/containerd-joins-cloud-native-computing-foundation/

[12] постигла: https://www.cncf.io/blog/2017/03/29/rkt-pod-native-container-engine-launches-cncf/

[13] rkt: https://coreos.com/rkt/

[14] Источник: https://habrahabr.ru/post/325358/