Появление Docker привело к взрывному росту популярности контейнеров, но с тех пор появились и другие инструменты. К сожалению, разобраться в них может быть совсем непросто. Но мы попробуем! И если вы считаете себя единственным, кто всего этого пока не понимает, не волнуйтесь... Это не так!

Что такое Docker?

Существует разница между компанией Docker, контейнерами Docker, образами Docker и инструментами Docker, к которым мы все привыкли. Важно понимать, что Docker — лишь один из инструментов для работы с контейнерами; существуют и другие инструменты, причем некоторые из них поддерживает сама компания Docker.

Как видите, вы не единственный, кто сбит с толку. Давайте разберёмся, чем отличаются Docker, containerd и CRI-O. Это особенно важно, если вы работаете с Kubernetes.

Обзор экосистемы контейнеров

Экосистема контейнеров состоит из множества технологий, специальной терминологии и компаний, конкурирующих друг с другом. К счастью, компании иногда заключают хрупкое перемирие, чтобы согласовать некоторые стандарты. Эти стандарты помогают добиться совместимости между различными инструментами и избежать зависимости от одной компании или проекта. Основные стандарты, о которых необходимо знать:

  • Container Runtime Interface (CRI) определяет API между Kubernetes и Container Runtime (средой выполнения контейнеров).

  • Open Container Initiative (OCI) определяет стандарт образов и контейнеров.

На этой иллюстрации показано, как Docker, Kubernetes, OCI, CRI, containerd и runc вписываются в эту экосистему:

Docker

Мы начнем с Docker, потому что это самый популярный инструмент для работы с контейнерами в настоящий момент. Для многих само название "Docker" является синонимом слова «контейнер».

Компания Docker создала очень удобный инструмент для работы с контейнерами. Docker можно установить на ноутбук (Docker Desktop) ??или сервер (Docker Engine). Он содержит набор инструментов, упрощающих труд разработчиков и DevOps—инженеров. С помощью Docker CLI можно создавать образы контейнеров, работать с репозиториями, создавать, запускать и управлять контейнерами.

Docker состоит из трех проектов:

  • docker-cli: утилита командной строки, с которой вы взаимодействуете с помощью команды docker.

  • containerd: Linux Daemon, который управляет контейнерами и запускает их. Он загружает образы из репозитория, управляет хранилищем и сетью, а также контролирует работу контейнеров.

  • runc: низкоуровневая среда выполнения контейнеров, которая создает и запускает контейнеры.

На самом деле, когда вы запускаете контейнер с помощью docker, вы фактически запускаете его через Docker Daemon, containerd, а затем runc.

Dockershim: Docker в Kubernetes

Важно помнить, что Kubernetes поддерживает только Container Runtime, которые работают с Container Runtime Interface (CRI), но Docker не поддерживает этот стандарт напрямую, поэтому Kubernetes включает компонент под названием dockershim, который необходим для работы с Docker.

Что такое shim?

Компонент, который функционирует как мост между различными API, обеспечивая совместимость.

В дальнейшем Kubernetes откажется от поддержки dockershim и, соответственно, Docker и будет работать только с Container Runtime, поддерживающими Container Runtime Interface (CRI) — containerd или CRI-O.

Но это не означает, что Kubernetes не сможет запускать контейнеры из Docker—образов. И containerd, и CRI-O могут запускать образы в формате Docker (фактически в формате OCI), они просто делают это без использования команды docker и Docker Daemon.

Docker—образы

То, что многие люди называют Docker—образами, на самом деле является образами в формате Open Container Initiative (OCI). Поэтому, если вы загружаете образ из Docker Hub или другого репозитория, вы сможете использовать его с помощью команды docker, или в кластере Kubernetes, или с помощью утилиты podman, или любого другого инструмента, поддерживающего спецификацию формата образа OCI.

Container Runtime Interface (CRI)

CRI — это API, который Kubernetes использует для управления различными Container Runtime, создающими и управляющими контейнерами. CRI упрощает для Kubernetes использование различных Container Runtime. Вместо того, чтобы включать в Kubernetes поддержку каждой из них, используется стандарт CRI. При этом задача управления контейнерами полностью ложится на Container Runtime.

Поэтому, если вы можете использовать containerd для запуска контейнеров, вы также можете использовать CRI-O, потому что они поддерживают стандарт CRI. При этом, если вы конечный пользователь, то вам не важно, какая Container Runtime используется.

Помните, что Red Hat (проект OpenShift) использует CRI-O и отвечает за его поддержку (безопасность, исправления ошибок и т. д.). В то время как Docker поддерживает containerd.

Какая Container Runtime используется в Kubernetes

В архитектуре Kubernetes Kubelet (агент, работающий на каждом узле) отвечает за взаимодействие с Container Runtime. Вы можете проверить, какую Container Runtime вы используете, просмотрев параметры Kubelet на каждом узле. В манифесте есть опции --container-runtime и --container-runtime-endpoint, которые используются для настройки Container Runtime.

containerd

сontainerd — это Container Runtime, которая раньше была частью Docker. Реализует спецификацию CRI. Умеет скачивать образы из репозитория и управляет ими, а затем передает их Container Runtime нижнего уровня (о ней речь пойдет дальше), которая фактически создает и запускает процессы контейнера.

сontainerd был выделен из проекта Docker, чтобы сделать Docker модульным. Таким образом, Docker сам использует containerd. Когда вы устанавливаете Docker, он также устанавливает containerd. Кроме того, сontainerd использует собственный плагин для поддержки CRI в Kubernetes.

CRI-O

CRI-O — это еще одна Container Runtime, реализующая Container Runtime Interface (CRI). Она была специально создана с нуля при поддержке Red Hat, IBM, Intel и SUSE как Container Runtime для Kubernetes. Это альтернатива containerd, которая также позволяет загружать образы контейнеров из репозиториев, управлять ими и запускать Container Runtime нижнего уровня для запуска процессов контейнера.

Open Container Initiative (OCI)

OCI — это группа компаний, которые поддерживают спецификацию формата образа контейнера и метода запуска контейнеров. Идея OCI заключается в том, что вы можете выбирать между различными Container Runtime, которые соответствуют этой спецификации. При этом каждая из них может иметь разные реализации нижнего уровня. Например, у вас, может быть, одна OCI-совместимая Container Runtime для ваших хостов Linux и одна для ваших хостов Windows. В этом заключается преимущество стандартизации.

runc

runc — это еще одна среда выполнения контейнера, совместимая с OCI, которая запускает процессы контейнеров. runc называют эталонной реализацией OCI.

Что такое эталонная реализация?

Эталонная реализация — это программное обеспечение, в котором реализованы все требования спецификации или стандарта. В случае с OCI runc предоставляет все функции, ожидаемые от OCI-совместимой среды выполнения.

Вот несколько альтернатив runc:

  • crun: среда выполнения контейнеров, написанная на C (в отличие от runc, которая написана на Go).

  • kata-runtime: из проекта Katacontainers, который реализует спецификацию OCI как отдельные небольшие виртуальные машины (аппаратная виртуализация).

  • gVisor: разработана в Google, создает контейнеры с собственным ядром. Рреализует OCI в своей среде выполнения, называемой runsc.

Есть ли аналоги runc для Windows?

runc — это инструмент для запуска контейнеров в Linux. В Windows всё немного иначе. Эквивалент runc — это служба Microsoft Host Compute Service (HCS). Она содержит инструмент под названием runhcs, который является форком runc и также реализует спецификацию Open Container Initiative.

Подведем итоги

Docker — это лишь часть всей экосистемы контейнеров. Существуют открытые стандарты: CRI и OCI, и несколько Container Runtime с поддержкой CRI: containerd, runc, CRI-O и, конечно, сам Docker. Возможно, скоро мы увидим множество новых реализаций Container Runtime с поддержкой стандартов CRI и OCI.