Русский
Русский
English
Статистика
Реклама

Cri

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

08.12.2020 14:22:23 | Автор: admin

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

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

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

И назвали эту программу dockershim, и вот как раз ее и хотят убрать к версии 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) и опубликовали в ее рамках спецификацию формата хранения образов контейнеров. Эту спецификацию поддерживают Docker, containerd и cri-o, так что образ, собранный с помощью docker build на машине разработчика, должен без проблем запустится с помощью containerd или cri-o. И так и происходит в подавляющем большинстве случаев, но время от времени попадаются нюансы реализации. Эти нюансы, конечно, исправляются, но иногда не так быстро, как хотелось бы.

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

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

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

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

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

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

Но внезапно оказалось, что человек тоже хочет взаимодействовать с CRI, и для этого была написана отдельная утилита crictl, которая представляет собой 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, если вы используете cri-o, или утилитой ctr из комплекта containerd.

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

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

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

Подробнее..

Перевод Как заменить container runtime в Kubernetes

14.03.2021 18:20:23 | Автор: admin

Братцы! Скорее всего вы уже знаете, что Kubernetes отказался от поддержки Docker в качестве среды выполнения контейнеров (container runtime) в будующих версиях. В релизе 1.20, вышедшем в конце 2020 года Dockershim помечен как не рекомендованный (depricated). В релизе 1.22, выход которого запланирован на конец 2021 года, от его поддержки планируют полностью отказаться.

Если вы используете управляемые кластеры Kubernetes (такие как GKE, EKS, AKS) это не станет для вас серьезной проблемой и скорее всего переключение будет простым. Но если вы управляете кластером самостоятельно (например с помощью kubeadm) и используете Docker в container runtime, рано или поздно, вам придется заменить ее, чтобы иметь возможность обновлениять Kubernetes до последних версий.

Задача этой статьи не дать исчерпывающую информацию о причинах такого решения со стороны разработчиков Kubernetes или подробно изучить поведения конкретных container runtime в кластере Kubernetes. Вместо этого мы шаг за шагом разберемся как переключить Docker container runtime на другое решение, поддерживающее стандарт Container Runtime Interface(CRI). Если вас интересуют причины из-за которых Docker больше не рекомендован к использованию, ознакомьтесь со статьей из официального блога Kubernetes Don't Panic: Kubernetes and Docker.

Чтобы не пропустить новые статьи подписывайтесь на телеграм-канал Mops DevOps

Что проверять в первую очередь

Влияние на рабочие нагрузки, выполняемые в вашем кластере, должно быть минимальным. Единственное, о чем вам нужно позаботиться, - это используете ли вы Docker-in-Docker в любой из ваших контейнерных рабочих нагрузок, смонтировав сокет Docker /var/run/docker.sock. В этом случае вам нужно будет найти альтернативу (например, Kaniko), прежде чем переключаться с Docker на новую container runtime.

Также настоятельно рекомендуется сделать резервную копию ваших данных, прежде чем переходить к переключению среды выполнения контейнера!

Приступим к работе!

Отлично, теперь, когда вы готовы к переключению container runtime, можно начинать. В этой статье бедем использовать containerd в качестве container runtime, но приведенные ниже шаги можно адаптировать к другой среде выполнения контейнера, например, CRI-O.

Мы начнем с рабочих узлов (worker nodes) и только потом выполним аналогичные действия на мастерах (control plane).

Worker nodes

Указанные ниже шаги нужно выполнить на всех рабочих узлах кластера.

1) Вначале выполним drain и cordon узла кластера, чтобы эвакуировать нагрузки с него и предотвратить планирование новых нагрузок во время выполнения последующих операций:

kubectl cordon <node_name>kubectl drain <node_name>

Замечание: если на узлах кластера запущены DaemonSets, необходимо использовать флаг --ignore-daemonsets, чтобы продолжить эвакуацию остальных pods. Не волнуйтесь kubelet эти pods автоматически пересоздаст с помощью новой container runtime, когда процедура переключения будет завершена. Если у вас есть критические сервисы, запущенные в DaemonSet, и вы не хотите, чтобы они работали во время процесса переключения, вы можете либо указать nodeSelector в своем DaemonSet, либо полностью удалить и переустановить их в конце процесса.

2) Останавливаем сервис kubelet:

sudo systemctl stop kubeletsudo systemctl status kubelet

3) Удаляем Docker

Я не буду подробно описывать команды, поскольку это зависит от вашего дистрибутива Linux и способа установки Docker. Просто будьте осторожны, если вы хотите полностью очистить артефакты Docker, возможно, вам придется вручную удалить некоторые файлы (например, /var/ lib/docker).

Подробную инструкцию вы найдете в документации Docker.

4) Устанавливаем countainerd используя официальному руководству для вашей версии операционной системы.

5) Выполняем Enableи Startсервиса containerd:

sudo systemctl enable containerdsudo systemctl start containerdsudo systemctl status containerd

6) Kubernetes взаимодействует с container runtime через плагин CRI . Убедитесь, что этот плагин не был отключен при установке containerd.

Проверим файл конфигурации:

vim /etc/containerd/config.toml проверяем параметрdisabled_plugins = [""]

Если на предыдущем шаге внесены изменения в конфигурационный файл, необходимо перезагрузить сервис containerd:

sudo systemctl restart containerd

7) Отредактируем конфигурационный файл kubelet:

vim /var/lib/kubelet/kubeadm-flags.envДобавим в конфигурационный файл флаги для переменной KUBELET_KUBEADM_ARGS(при необходимости измените путь к container runtime)--container-runtime=remote --container-runtime-endpoint=/run/containerd/containerd.sock

8) Запускаем сервис kubelet:

sudo systemctl start kubelet

9) Проверяем, что на узле запущена требуемая версия container runtime:

kubectl describe node <node_name>
System Info:  Machine ID:                 21a5dd31f86c4  System UUID:                4227EF55-BA3BCCB57BCE  Boot ID:                    77229747-9ea581ec6773  Kernel Version:             3.10.0-1127.10.1.el7.x86_64  OS Image:                   Red Hat Enterprise Linux Server 7.8 (Maipo)  Operating System:           linux  Architecture:               amd64>>Container Runtime Version:  containerd://1.4.3  Kubelet Version:            v1.20.2  Kube-Proxy Version:         v1.20.2

10) Выполняем Uncordon на узле, чтобы разрешить планировать на него нагрузки, и проверим статус работы pods:

kubectl uncordon <node_name>

Вот и все, как только все ваши поды будут перезапущены, вы можете перейти к настройке следующего узла кластера!

Control Plane

Процедура обновление container runtime на мастерах полностью повторяет установку на рабочих узлах кластера. Однако будьте осторожны, если ваш кластер запущен с единственным мастером.

Пока новая container runtime будет загружать образы kube-apiserver, etcd и coredns и создавать соответствующие pods, кластер будет недоступен. У вас также не должна быть возможности запускать команду kubectl.

Вот несколько советов, которые помогут вам следить за запуском container runtime и устранять потенциальные проблемы:

1) Используем journalctl, чтобы отслеживать изменения в журналах kubelet:

journalctl -u kubelet

2) Проверяем журналы containerd:

journalctl -u containerd

3) Используем утилиту crictl, чтобы убедится, что контейнеры запущены:

crictl --runtime-endpoint /run/containerd/containerd.sock ps

4) После замены container runtime убедимся, что используем требуемую версию, выполнив команду на всех узлах кластера:

kubectl describe node <master_node_name>также можем выполнить команду, она выведет информацию сразу по всем узлам кластераkubectl get node -o wide

Поздравляю! Кластер Kubernetes настроен без Docker, теперь проблем с обновлением на новые версии возникнуть не должно.


Телеграм-канал Mops DevOps - анонсы вебинаров и конференций, полезные статьи и видео, а так же регулярные скидки на обучение!

Подробнее..

Перевод Миграция с Docker на containerd в среде Kubernetes

05.04.2021 10:08:01 | Автор: admin


Kubernetes отказывается от Docker для выполнения контейнеров после версии 1.20. (Прим. переводчика: в декабре мы уже писали о том, как это изменение повлияет на задачи разработчиков и инженеров эксплуатации: Docker is deprecated и как теперь быть?)


Без паники. Контейнеры Docker все еще поддерживаются, но без dockershim/Docker слоя между Kubernetes и containerd, который будет удален, начиная с версии 1.22+.


Если вы используете Docker, нужно перейти на поддерживаемый интерфейс container runtime interface (CRI). Хорошим вариантом будет containerd он уже есть у вас на ноде Kubernetes, если вы работаете с Docker.


Дополнительное преимущество меньше издержек благодаря отсутствию dockershim и уровней преобразования Docker, как видно на иллюстрации.



Переход с dockershim на containerd CRI


Как мигрировать?


Сначала проверяем, какая среда запуска контейнеров (container runtime) у нас используется. Это можно сделать командой kubectl get nodes -o wide


Как видите, здесь у нас Docker.


NAME       STATUS   ROLES                  AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION                             CONTAINER-RUNTIMEk8s-cn01   Ready    control-plane,master   78m     v1.20.4   10.65.79.164   <none>        Ubuntu 20.04.2 LTS   5.4.0-67-generic                           docker://20.10.5k8s-wn01   Ready    <none>                 64m     v1.20.4   10.65.79.131   <none>        Ubuntu 20.04.2 LTS   5.4.0-67-generic                           docker://20.10.5k8s-wn02   Ready    <none>                 4m16s   v1.20.4   10.65.79.244   <none>        CentOS Linux 8       4.18.0-240.15.1.el8_3.centos.plus.x86_64   docker://20.10.5

kubectl get nodes -o wide


Проверим, есть ли у нас containerd CLI /usr/bin/ctr и неймспейс moby из Docker.


NAME LABELSmoby

просмотр неймспейсов


Можно посмотреть запущенные контейнеры в этом неймспейсе.


CONTAINER                                                           IMAGE    RUNTIME04f9500885c473c9cb2b4f8d09dc4feea5c24838519b9a01251011830bab16a2    -        io.containerd.runc.v257d4c75ab9947829228a087b857b203c48a9d1c83de0a1b49af3624fb08c9d33    -        io.containerd.runc.v2934c007a259018a5cbda56dd8e066a66f2c9cfcb8003e7f8d25833fe462582fd    -        io.containerd.runc.v294315822d8f8a05e1be5adb7e5c18add33cbf2604057100c87572b5fc55169cd    -        io.containerd.runc.v2dfa01906e845239c74a0b35d457e845382468dd9ad6e99dd0c16be30f8a23a2d    -        io.containerd.runc.v2

Просмотр списка контейнеров в неймспейсе moby


Если все выглядит нормально, можно изменить CRI. Меняем по одной ноде за раз, начиная с рабочих и заканчивая мастером. Если мастер только один, вы временно потеряете доступ к кластеру, но он восстановится сам.


Cordon и drain


Выполняем cordon и drain для нод, чтобы перенести поды на другие ноды.


root@k8s-cn01:~# kubectl cordon k8s-wn01node/k8s-wn01 cordonedroot@k8s-cn01:~# kubectl drain k8s-wn01 --ignore-daemonsetsnode/k8s-wn01 already cordonedWARNING: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-9wnh4, kube-system/weave-net-pgptmevicting pod default/nginx-6799fc88d8-r44x9pod/nginx-6799fc88d8-r44x9 evictednode/k8s-wn01 evictedroot@k8s-cn01:~# kubectl get nodesNAME       STATUS                     ROLES                  AGE    VERSIONk8s-cn01   Ready                      control-plane,master   138m   v1.20.4k8s-wn01   Ready,SchedulingDisabled   <none>                 124m   v1.20.4k8s-wn02   Ready                      <none>                 64m    v1.20.4

Останавливаем сервисы


 systemctl stop kubelet  systemctl stop docker

остановка kubelet и docker


Удаляем Docker (по желанию)


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


apt purge docker-ce docker-ce-cliORyum remove docker-ce docker-ce-cli

удаление docker


Конфигурация containerd


Отключим строку disabled_plugins в /etc/containerd/config.toml, чтобы CRI загрузился.


#disabled_plugins = ["cri"]

/etc/containerd/config.tom


Если для cotainerd нет файла конфигурации, создайте новый дефолтный файл.


containerd config default > /etc/containerd/config.toml

создание файла конфигурации


Перезапустим containerd.


systemctl restart containerd

Меняем среду запуска


Правим файл /var/lib/kubelet/kubeadm-flags.env и добавляем среду containerd во флаги --container-runtimeremote и --container-runtimeendpoint=unix:///run/containerd/containerd.sock"


Файл kubeadm-flags будет выглядеть как-то так:


KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2--resolv-conf=/run/systemd/resolve/resolv.conf --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"

/var/lib/kubelet/kubeadm-flags.env


Запускаем kubelet


Изменив среду запуска, запускаем сервис kubelet.


systemctl start kubelet

запуск kubelet


Проверяем


Запускаем kubectl get nodes -o wide и видим, что у измененной ноды новая среда запуска.


NAME       STATUS                   ROLES                  AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION                             CONTAINER-RUNTIMEk8s-cn01   Ready                    control-plane,master   131m   v1.20.4   10.65.79.164   <none>        Ubuntu 20.04.2 LTS   5.4.0-67-generic                           docker://20.10.5k8s-wn01   Ready,,SchedulingDisabled        <none>                 117m   v1.20.4   10.65.79.131         <none>        Ubuntu 20.04.2 LTS   5.4.0-67-generic                           containerd://1.4.4k8s-wn02   Ready             <none>                 57m    v1.20.4   10.65.79.244   <none>        CentOS Linux 8       4.18.0-240.15.1.el8_3.centos.plus.x86_64   docker://20.10.5

Измененная нода все еще имеет статус cordoned. Отменим его.


root@k8s-cn01:~# kubectl uncordon k8s-wn01node/k8s-wn01 uncordonedroot@k8s-cn01:~# kubectl get nodesNAME       STATUS   ROLES                  AGE    VERSIONk8s-cn01   Ready    control-plane,master   143m   v1.20.4k8s-wn01   Ready    <none>                 129m   v1.20.4k8s-wn02   Ready    <none>                 69m    v1.20.4

Если проверить неймспейсы на ноде сейчас, увидим k8s.io. Неймспейс moby теперь пуст, никакие контейнеры в нем не выполняются все мигрировало в k8s.io.


root@k8s-wn01:~# ctr namespaces listNAME   LABELSk8s.iomobyroot@k8s-wn01:~# ctr --namespace moby container listCONTAINER    IMAGE    RUNTIMEroot@k8s-wn01:~# ctr --namespace k8s.io container listCONTAINER                                                           IMAGE                                    RUNTIME08d4b5ca1f0ddd08fff7f64ea4eb12be66b8ec860d119565e553c84d16942d26    docker.io/weaveworks/weave-kube:2.8.1    io.containerd.runc.v21c9e3f61f542b12abb4b849075b084fb7fe3f69b89ce668d73022c2cd647bcd1    k8s.gcr.io/pause:3.2                     io.containerd.runc.v21f8e0c5a6f8219de1c8f25bbb28d5d5c71b74e9ccfb9620007701847d29f23a2    k8s.gcr.io/kube-proxy:v1.20.4            io.containerd.runc.v239296ebd6017a7c83cd58004c94708c927f10a996a4e6ba0bbf003c6713fe713    docker.io/weaveworks/weave-kube:2.8.1    io.containerd.runc.v267f812954f46fa5c1f6ab39e681e2481f868309f28bd1b8ba44cce53f5c0071c    docker.io/weaveworks/weave-npc:2.8.1     io.containerd.runc.v29caed1d57d40cedef736e45adf550eda6a0befd32712e5b6af5d711681ba71f0    k8s.gcr.io/pause:3.2                     io.containerd.runc.v2

просмотр нового неймспейса k8s.io


Мы успешно изменили CRI, теперь можно повторить все то же самое для следующей ноды.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru