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

Docker is deprecated — и как теперь быть?

Kubernetes объявил Docker устаревшим и планирует прекратить его использование примерно через год, в версии 1.22 или 1.23. Эта новость вызвала много вопросов и непонимания. В блоге Kubernetes появилось целых две статьи, разъясняющих смысл записи [1]в Changelog (раз [2] и два [3]). Если все обобщить, то для разработчиков (те, которые Dev) ничего не меняется — они все так же могут продолжать использовать docker build для сборки своих контейнеров, а вот для инженеров, ответственных за эксплуатацию кластера (Ops), пришла пора разобраться и освоить несколько новых инструментов.

Docker is deprecated — и как теперь быть? - 1

Но для начала давайте вернемся в 2016 год, когда Kubernetes представил [4]Container Runtime Interface (CRI). До версии Kubernetes 1.3 kubelet умел работать только с Docker, а в 1.3 анонсировали поддержку rkt Container Engine [5] (этот проект уже прекратил свое существование). При этом код, отвечающий за взаимодействие с Docker и rkt, был глубоко и широко интегрирован в исходники kubelet. Процесс добавления поддержки rkt показал, что для добавления новых container runtime необходимо хорошо разбираться в устройстве и алгоритмах работы kubelet, а результат получился очень сложным для поддержки и развития.

Поэтому решили все упростить, и добавили новую абстракцию — Container Runtime Interface [6]. Весь код, реализующий высокоуровневый интерфейс работы с Docker, был убран из kubelet, а вместо него kubelet стал использовать CRI. Но тут возникла небольшая проблемка — Docker не умеет в CRI. Чтобы ее решить, в Kubernetes написали программу-прокладку между kubelet и Docker. С одной стороны она принимает запросы от kubelet через CRI, а с другой — транслирует их в docker-демон.

И назвали эту программу dockershim [7], и вот как раз ее и хотят убрать к версии 1.23.

Возвращаемся назад, в конец 2020 года, и смотрим чего у нас новенького по сравнению с 2016 в плане развития Container Runtime Interface.

  • Проект rkt закрыт.

  • RedHat создали и всячески продвигают свой собственный движок для запуска контейнеров CRI-O.

  • Монолитный Docker разделили на containerd, dockerd и docker-cli.

В итоге у нас сейчас есть два движка для запуска контейнеров, которые умеют в CRI — это containerd и cri-o. Естественно, все эти события произошли не прямо в 2020 году, но массовый интерес к ним возник именно после объявления Kubernetes о прекращении поддержки Docker.

Сборка

Давайте же разберемся, чем нам это грозит. Начнем с наиболее частого вопроса: «Как же собирать образ контейнера с помощью containerd или cri-o?»

И ответ очень простой: «Никак». Потому что containerd и cri-o предназначены только для запуска контейнеров из готовых образов. Плюс они умеют еще несколько вещей, необходимых для эксплуатации:

  • загрузка образов из интернета;

  • просмотр информации о запущенных подах и контейнерах;

  • удаление образов, подов и контейнеров;

  • подключение внутрь контейнера (запуск внутри контейнера процесса с bash).

Но они не умеют ни собирать новый образ, ни пушить его в какой-либо registry. И как теперь быть ?

Начнем с того, что в 2015 году «Docker и остальные лидеры индустрии контейнеризации» основали Open Container Initiative (OCI) [8] и опубликовали в ее рамках спецификацию [9]формата хранения образов контейнеров. Эту спецификацию поддерживают Docker, containerd и cri-o, так что образ, собранный с помощью docker build на машине разработчика, должен без проблем запустится с помощью containerd или cri-o. И так и происходит в подавляющем большинстве случаев, но время от времени попадаются «нюансы реализации». Эти нюансы, конечно, исправляются, но иногда не так быстро, как хотелось бы.

Если вы за стабильность и минимальные изменения — запускайте новые кластера с containerd в качестве движка контейнеризации. А на машинах разработчиков и CI runners сборки смело оставляйте Docker.

Если вы выбрали безопасность из коробки, кровавый enterpise и платную поддержку, то наверняка используете Openshift [10](платформа на базе Kubernetes), в котором для запуска контейнеров применяется cri-o. А для сборки образов RedHat создала отдельную утилиту, которую назвала buildah [11]. В отличие от Docker, этой утилите для сборки образов не нужен запущенный движок контейнеризации.

Из альтернатив можно еще посоветовать kaniko [12]— утилиту для сборки образов от Google. Она поставляется в виде образа контейнера, так что для запуска ей нужен движок контейнеризации, но для сборки — уже нет.

Эксплуатация

С разработкой разобрались, теперь пора перейти к самому интересному: что делать инженеру, который зашел на узел, чтобы разобраться, почему статус узла стал NotReady, набрал привычную команду docker ps, а в ответ получил docker: command not found.

Фундаментальная проблема тут в том, что Docker изначально ориентировался на взаимодействие с человеком, и к последним версиям у него появился очень классный и удобный консольный интерфейс, а вот компоненты, реализующие CRI — они by design ориентированы на взаимодействие с программой-оркестратором, а не с человеком.

Но внезапно оказалось, что человек тоже хочет взаимодействовать с CRI, и для этого была написана отдельная утилита crictl [13], которая представляет собой CLI-консоль к CRI-движку. То есть одна и та же утилита crictl позволяет посмотреть список контейнеров запущенных с помощью containerd или cri-o.

Очень часто встречается информация, что можно просто заменить docker на crictl и вместо docker ps набирать crictl ps. Сказка заканчивается, когда вы попробуете запустить контейнер с помощью crictl run , и внезапно оказывается, что сначала надо создать манифест для PodSandbox, а уже потом написать манифест, описывающий контейнер, который будет запущен в этом поде.

С другой стороны надо помнить, что CRI был придуман командой разработки Kubernetes и для Kubernetes, и поэтому, на мой взгляд, правильнее было бы его назвать Pod Runtime Interface.

И crictl оптимизирован для работы с контейнерами, созданными kubelet. Например, в выводе не показываются служебные PODSandbox контейнеры, а имена контейнеров показываются в более понятном виде, чем в Docker. Да и возможности по работе с CLI постоянно улучшаются.

Еще одна вещь, с которой часто возникают проблемы понимания. Многие путают docker (бинарник из пакета docker-cli) и dockerd (демон, управляющий контейнерами). Пытаются сделать crictl image save/load и внезапно оказывается, что в crictl таких команд нет. А на созданный issue авторы устало отвечают, что crictl — консоль для CRI runtime, который должен только запускать контейнеры, ну еще образ скачать из registry. А про манипуляции с образами в спецификации ничего нет.

Но выход есть! Для манипуляции с образами контейнеров можно воспользоваться дополнительной утилитой skopeo [14], если вы используете cri-o, или утилитой ctr [15] из комплекта containerd.

И в завершение дам ответ на идею, которая наверняка возникнет после прочтения этой статьи:

«Подождите, но ведь есть containerd, с которым умеет работать kubelet и dockerd! Давайте поставим Docker (три пакета docker-cli, docker, containerd), kubelet настроим на работу с containerd напрямую, и у нас при этом останется старая добрая команда docker».

Вот только docker ps не покажет контейнеров, запущенных kubelet через CRI. Произойдет это из-за того, что containerd умеет работать в многопользовательском режиме, и docker с kubelet запускают контейнеры в различных containerd namespaces [16]moby и k8s.io соответственно (не надо путать их с kubernetes namespaces [17]). Посмотреть на контейнеры в разных неймспейсах можно с помощью утилиты ctr -n <ns_name> container ls.

Автор: LuckySB

Источник [18]


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

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

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

[1] записи : https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation

[2] раз: https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

[3] два: https://kubernetes.io/blog/2020/12/02/dockershim-faq/

[4] представил : https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/

[5] rkt Container Engine: https://github.com/rkt/rkt

[6] Container Runtime Interface: https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md

[7] dockershim: https://github.com/kubernetes/kubernetes/tree/release-1.5/pkg/kubelet/dockershim

[8] Open Container Initiative (OCI): https://opencontainers.org/

[9] спецификацию : https://github.com/opencontainers/image-spec

[10] Openshift : https://www.openshift.com/

[11] buildah: https://github.com/containers/buildah

[12] kaniko : https://github.com/GoogleContainerTools/kaniko

[13] crictl: https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md

[14] skopeo: https://github.com/containers/skopeo

[15] ctr: https://github.com/containerd/containerd/blob/9741f03932fbab48cb645dbef73526fe4f25a983/RELEASES.md#ctr-tool

[16] containerd namespaces: https://github.com/containerd/containerd/blob/master/docs/namespaces.md

[17] kubernetes namespaces: https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/

[18] Источник: https://habr.com/ru/post/531820/?utm_source=habrahabr&utm_medium=rss&utm_campaign=531820