company_banner

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

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



    Как устроен containerd


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

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



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

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

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


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

    P.S. На прошлой неделе Cloud Native Computing Foundation формально подтвердила принятие containerd в число своих проектов. И в тот же день такая участь постигла проект rkt, который решает аналогичные containerd задачи в CoreOS: является реализацией открытой спецификации App Container (appc) и использует формат ACI (Application Container Image) для образов. CNCF будет поддерживать развитие обоих проектов.
    Флант
    357.38
    Специалисты по DevOps и Kubernetes
    Support the author
    Share post

    Comments 0

    Only users with full accounts can post comments. Log in, please.