Как перейти от Dockershim в Kubernetes

Быстрые ссылки
- Что такое Dockershim?
- Как проверить, используется ли Dockershim
- Переход на другой runtime на узле
- Playbook миграции
- Решение проблем и откат
- Выводы
Краткое введение
Kubernetes v1.24 и последующие выпуски больше не поставляются с встроенным Dockershim — компонентом, который ранее обеспечивал совместимость Kubernetes с Docker Engine. Если у вас старые самоуправляемые кластеры, созданные несколько лет назад, они могут полагаться на Dockershim. Если вы используете управляемые кластерные сервисы (EKS, AKS, GKE, DOKS и т.п.), скорее всего, ничего делать не нужно.
Цель статьи — дать практическую инструкцию: проверить, какие узлы затронуты, и безопасно перевести их на поддерживаемый runtime (containerd) или развернуть standalone-адаптер cri-dockerd, если вам необходима совместимость с Docker Engine.
Что такое Dockershim?
Dockershim — это адаптер, который позволял Kubernetes взаимодействовать с Docker Engine до того, как был введён стандарт CRI (Container Runtime Interface). CRI сделал возможной поддержку других runtime (containerd, CRI-O и т.д.). Dockershim представлял собой временное, тесно связанное с реализацией Docker решение; оно усложняло сопровождение Kubernetes и было удалено.
Ключевые моменты:
- CRI — интерфейс, определяющий, как kubelet общается с контейнерным runtime.
- Docker Engine исторически не поддерживал CRI напрямую; Dockershim устранял этот разрыв.
- Containerd — самостоятельный runtime, вышедший из экосистемы Docker и полностью поддерживаемый Kubernetes.
- Cri-dockerd — отдельный проект (Mirantis + Docker) с тем же принципом работы, что Dockershim, но как отдельный компонент.
Важно: удаление Dockershim не влияет на форматы контейнерных образов — Kubernetes по‑прежнему запускает OCI‑совместимые образы, созданные с помощью docker build или других инструментов.
Как проверить, используется ли Dockershim
- Сравните runtime узлов:
$ kubectl get nodes -o wideВ колонке CONTAINER-RUNTIME вы увидите строки вроде docker://19.3.1 или containerd://1.4.13.
Пример:
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.22.8 docker://19.3.1
node-2 Ready v1.22.8 containerd://1.4.13
- На подозрительном узле (с
docker://) выполните проверку конфигурации kubelet. На хосте узла выполните:
$ tr \\0 ' ' < /proc/"$(pgrep kubelet)"/cmdline | grep "\-\-container\-runtime"Примечание: если команда не выводит ничего, это индикатор того, что kubelet запускается без явного флага --container-runtime и, возможно, использует встроенный (удалённый) Dockershim в старых конфигурациях kubelet. Если вывод есть — посмотрите значение --container-runtime-endpoint:
unix:///run/containerd/containerd.sock→ используется containerd; миграция не требуется.unix:///var/run/cri-dockerd.sock→ используется standalone cri-dockerd.- отсутствует явный endpoint и виден
docker://вkubectl get nodes→ узел вероятно использует встроенный Dockershim и требует действия.
Когда нужно действовать немедленно
- Вы планируете обновление кластера до Kubernetes v1.24 или выше.
- У вас есть узлы с контейнерным runtime, обозначенным как
docker://и без явногоcri-socketна объекте Node.
Если вы не обновляете Kubernetes и вам удобно поддерживать текущую версию, немедленных изменений можно избегать, но это потенциально увеличивает техдолг.
Переход runtime на узле — общий план действий
Общий план безопасной миграции одного узла:
- Подготовка: убедиться, что на других узлах есть ресурсы для перезапуска Pod’ов.
- Пометить узел как unschedulable:
kubectl cordon. - Дренировать рабочие нагрузки:
kubectl drain.--ignore-daemonsets - Остановить kubelet и docker сервисы на хосте.
- Установить выбранный runtime (containerd или cri-dockerd).
- Обновить конфигурацию
/var/lib/kubelet/kubeadm-flags.envи аннотацию Nodekubeadm.alpha.kubernetes.io/cri-socket. - Перезапустить kubelet и проверить состояние:
kubectl get nodes -o wide. - Если всё корректно — снять cordon:
kubectl uncordon.
Дальше — подробные инструкции для containerd и cri-dockerd.
Переход на containerd (рекомендуемый путь)
Когда выбирать containerd:
- Вы не используете специфичные Docker‑фичи (docker CLI‑тулза, dockerd API, docker.sock внутри контейнеров).
- Вы хотите минимизировать поверхностные зависимости и упростить сопровождение.
Шаги:
- Cordon и drain узла:
$ kubectl cordon node-1
$ kubectl drain node-1 --ignore-daemonsets- На самом узле остановите kubelet и docker:
$ systemctl stop kubelet$ systemctl disable docker.service --now- Установите containerd. На Debian/Ubuntu пример установки через репозиторий Docker:
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg lsb-release
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null$ sudo apt update
$ sudo apt install containerd- Настройте kubelet для работы с контейнерным runtime remote. Откройте
/var/lib/kubelet/kubeadm-flags.envи добавьте или измените флаги:
--container-runtime=remote--container-runtime-endpoint=unix:///run/containerd/containerd.sock
Файл обычно выглядит как одна строка с KUBELET_KUBEADM_ARGS="..." — внесите изменения аккуратно.
- Обновите аннотацию на объекте Node:
$ kubectl edit node node-1Найдите kubeadm.alpha.kubernetes.io/cri-socket и установите значение unix:///run/containerd/containerd.sock.
- Перезапустите kubelet и проверьте состояние:
$ systemctl start kubelet
$ kubectl get nodes -o wideПример ожидаемого вывода:
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.22.8 containerd://1.4.13
- Снимите cordon:
$ kubectl uncordon node-1Советы:
- Перед массовой миграцией протестируйте процесс на одной ноде (non‑production) и убедитесь, что DaemonSet’ы корректно запускаются.
- Проверьте работу сетевых плагинов (CNI), так как некоторые из них могут требовать дополнительных шагов при смене runtime.
Установка и использование cri-dockerd (если вам нужна совместимость с Docker Engine)
Когда выбирать cri-dockerd:
- Вы используете инструменты, которые ожидают наличия Docker API (например, некоторые CI/CD решения, сторонние аддоны, приложения, монтирующие
/var/run/docker.sock). - Вы не готовы переписывать интеграции и вам нужна быстрая совместимость при обновлениях Kubernetes.
Cri-dockerd — это отдельно поддерживаемый адаптер, который предоставляет CRI-интерфейс поверх Docker Engine.
Шаги установки (пример):
- Убедитесь, что Docker Engine установлен и работает.
- Скачать релиз cri-dockerd (пример v0.2.0):
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.0/cri-dockerd-v0.2.0-linux-amd64.tar.gz
$ tar xvf cri-dockerd-v0.2.0-linux-amd64.tar.gz
$ mv cri-dockerd /usr/local/bin/- Установите systemd‑юниты для cri-dockerd:
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
$ sudo mv cri-docker.socket cri-docker.service /etc/systemd/system/
$ sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable cri-docker.service
$ sudo systemctl enable --now cri-docker.socket- Обновите
/var/lib/kubelet/kubeadm-flags.env:
--container-runtime=remote--container-runtime-endpoint=unix:///var/run/cri-dockerd.sock
- Обновите аннотацию Node:
$ kubectl edit node node-1Установите kubeadm.alpha.kubernetes.io/cri-socket в unix:///var/run/cri-dockerd.sock.
- Перезапустите kubelet и проверьте состояние:
$ systemctl start kubelet
$ kubectl get nodes -o wideВы увидите, что runtime всё ещё отображается как docker://..., но теперь запросы идут через standalone cri-dockerd, а не через встроенный Dockershim.
- Снимите cordon:
$ kubectl uncordon node-1Замечания:
- Cri-dockerd даёт обратную совместимость, но это дополнительный компонент, за которым нужно следить и обновлять.
- Для долгосрочной стратегии рекомендуется постепенно перейти на containerd, если это возможно.
Playbook миграции (SOP для команды)
Минимальный playbook для отдельного узла:
- Предусловия:
- Доступ к консоли узла (SSH).
- Резервные копии критичных данных и манифестов.
- Мониторинг и алерты настроены для быстрого обнаружения проблем.
- Проверка текущего состояния:
kubectl get nodes -o widekubectl describe node— поиск аннотацииcri-socket.
- Снять планировщик:
kubectl cordon. - Дренировать:
kubectl drain.--ignore-daemonsets - На узле: остановить kubelet и docker.
- Установить containerd или cri-dockerd.
- Обновить
/var/lib/kubelet/kubeadm-flags.envи аннотацию Node. - Запустить kubelet и убедиться, что Node в Ready и показывает корректный runtime.
- Снять cordon и мониторить нагрузку и логи.
Критерии приёмки:
- Node возвращается в состояние Ready.
- CONTAINER-RUNTIME показывает
containerd://илиdocker://сcri-dockerdкак endpoint. - Все Pod’ы, за исключением DaemonSet’ов, успешно перезапустились на других узлах и позже вернулись на мигрированный узел при uncordon.
Резервный план и откат (runbook)
Если после перезапуска kubelet узел ушёл в NotReady или Pods не запускаются:
- Просмотрите логи kubelet:
journalctl -u kubelet -xe. - Убедитесь, что сокет runtime существует и доступен с правами, ожидаемыми kubelet (проверить
ls -l /run/containerd/containerd.sockили/var/run/cri-dockerd.sock). - Если проблема связана с отсутствием Docker API и вы устанавливали cri-dockerd, убедитесь, что dockerd запущен:
systemctl status docker. - В крайнем случае откат:
- Верните предыдущую конфигурацию
/var/lib/kubelet/kubeadm-flags.env. - Восстановите аннотацию Node к предыдущему значению (если помните или сохранили резервную копию объекта Node — используйте
kubectl apply -f node-backup.yaml). - Перезапустите docker и kubelet:
systemctl start docker && systemctl start kubelet.
- Верните предыдущую конфигурацию
Важно: всегда сохраняйте резервную копию оригинальной конфигурации Node перед изменениями:
$ kubectl get node node-1 -o yaml > node-1-backup.yamlРешение типичных проблем
Проблема: Node в статусе NotReady после смены runtime
- Проверить логи kubelet и логи runtime.
- Убедиться, что аннотация
cri-socketкорректна. - Убедиться, что CNI плагины совместимы с новым runtime.
Проблема: Pods не запускаются из‑за привязки к docker.sock
- Подумайте о сохранении cri-dockerd или о рефакторинге приложений, чтобы не монтировать
/var/run/docker.sock.
Проблема: DaemonSet’ы не мигрируются
- При дренировании используйте флаг
--ignore-daemonsets, DaemonSet запущенные на узле останутся, и вам нужно обеспечить их поддержку при смене runtime.
Сравнение: containerd vs cri-dockerd (обзор)
| Критерий | containerd | cri-dockerd |
|---|---|---|
| Поддержка в Kubernetes | нативная, рекомендовано | предоставляет совместимость с Docker API через адаптер |
| Поддержка docker.sock | нет (dockerd отсутствует) | да (нужен docker daemon) |
| Сложность сопровождения | ниже (меньше компонентов) | выше (ещё один внешний компонент) |
| Сценарии применения | облачные среды, современные рабочие нагрузки | существующие интеграции, docker-in-docker, legacy tooling |
Выбор зависит от вашего стека и наличия зависимостей от Docker API.
Ментальные модели и эвристики при принятии решения
- Если ваша инфраструктура минимально зависит от Docker API и вы хотите снизить операционные риски — выбирайте containerd.
- Если у вас много инструментов, которые напрямую используют Docker API и быстро переписать их нельзя — используйте cri-dockerd как промежуточное решение.
- Планируйте долгосрочный переход на CRI‑совместимые решения и минимизируйте использование docker.sock в контейнерах.
Роли и задачи (чек‑листы)
SRE / Инженер по платформе:
- Проверить список узлов и runtime.
- Подготовить план миграции и окно работ.
- Обновить образы и конфигурации DaemonSet/CNI при необходимости.
- Выполнить миграцию по шагам и мониторить метрики.
Разработчик приложения:
- [ ] Проверить, не монтируется ли
/var/run/docker.sock. - Убедиться, что контейнеры не зависят от специфичных для Docker образов или настроек.
- Тестировать приложение в среде с containerd.
Операционный менеджер:
- Убедиться, что есть коммуникация с командами о времени простоя.
- Планировать резервные ресурсы и откат.
Безопасность и конфиденциальность
- Монтирование docker.sock даёт контейнерам привилегированный доступ к хост‑демону Docker — это риск безопасности. По возможности избегайте таких паттернов.
- При использовании cri-dockerd сервер Docker по‑прежнему должен быть защищён и обновлён.
- Обновляйте cri-dockerd и containerd в рамках политики обновлений и ревью уязвимостей.
Критерии приёмки
- Узел возвращается в Ready и отображает ожидаемый runtime.
- Контейнеры запускаются корректно и проходят проверку состояния (Liveness/Readiness).
- Метрики и логирование не показывают аномалий после миграции.
- План отката проверен и готов к выполнению при необходимости.
Диаграмма принятия решения
flowchart TD
A[Нужна ли совместимость с Docker API?] -->|Да| B[Установить cri-dockerd]
A -->|Нет| C[Можно ли обновить интеграции?]
C -->|Да| D[Перейти на containerd]
C -->|Нет| B
B --> E[Обновить kubelet и аннотацию Node]
D --> E
E --> F[Перезапустить kubelet и проверить Node](Схема показывает упрощённый выбор между containerd и cri-dockerd)
Короткий глоссарий
- CRI — интерфейс, который kubelet использует для взаимодействия с контейнерным runtime.
- Dockershim — старый адаптер для Docker Engine, удалённый из Kubernetes.
- containerd — легковесный контейнерный runtime, рекомендованный для Kubernetes.
- cri-dockerd — standalone адаптер, предоставляющий CRI поверх Docker Engine.
Выводы
- Проверьте текущие runtime ваших узлов перед планируемым обновлением Kubernetes до v1.24+.
- Для большинства сред containerd — предпочтительный путь: он проще в поддержке и нативно интегрируется с Kubernetes.
- Если вам нужна совместимость с Docker API, используйте cri-dockerd как промежуточное решение, но планируйте долгосрочный переход.
- Всегда тестируйте миграцию на выделенной ноде и имейте план отката.
Важно: перед массовыми изменениями убедитесь, что у вас есть резервные копии манифестов и сохранённое состояние объектов Node (yaml-файл), чтобы в экстренной ситуации можно было вернуть исходную конфигурацию.
Похожие материалы
Повторяющиеся поля в Word — руководство и шаблон
Как увидеть посещённые рестораны в Google Maps
Find My на Mac — настройка, поиск и восстановление
Отключить уведомления Snapchat — пошагово
Как переключиться на Bash в macOS