Слово «containerd» чаще всего всплывает в двух ситуациях: в выводе docker info и в ошибках Kubernetes, когда pod висит в ContainerCreating. Между тем это самостоятельный рантайм: он тянет образы, готовит снапшоты файловой системы, запускает процессы через runc и следит за ними. Docker использует его внутри, Kubernetes общается с ним по CRI. Понимание containerd полезно и для отладки кластера, и для сервера, где Docker не нужен вовсе.

Место в стеке

Цепочка выглядит так: docker или kubelet → containerd → containerd-shim-runc-v2 → runc → процесс. containerd не создаёт контейнеры сам: он разбирает OCI-образ, распаковывает слои в snapshotter, формирует OCI-спецификацию и вызывает runc, который делает clone, pivot_root и execve. Дальше контейнер живёт под присмотром shim-процесса, а containerd может перезапуститься, не убив нагрузки.

Из этого следуют практические выводы. containerd не умеет собирать образы — для сборки нужен BuildKit или nerdctl. У него нет привычных -p и -v в низкоуровневом клиенте ctr. Зато есть CRI, снапшоты, пространства имён и понятная конфигурация в одном файле.

Установка и первые проверки

В Debian и Ubuntu пакет containerd есть в репозитории, но версия там отстаёт. Для сервера берите пакет из репозитория Docker или официальный архив с релизами. После установки проверьте, что служба поднялась и сокет на месте.

sudo apt install containerd
sudo systemctl enable --now containerd
containerd --version
sudo ctr version

ctr version показывает две строки: клиент и сервер. Если сервер не отвечает, смотрите journalctl -u containerd -n 50 — чаще всего это синтаксическая ошибка в /etc/containerd/config.toml или занятый сокет.

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

Файл настроек генерируется командой containerd config default. В containerd 2.x используется третья версия схемы, в 1.x — вторая; перед обновлением мажорной ветки сверьте свой файл с выводом containerd config default и перенесите изменения вручную. После правок проверяйте результат через containerd config dump: он показывает уже собранную конфигурацию, а не только то, что вы написали.

sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo containerd config dump | grep -E 'version|root|state'
sudo systemctl restart containerd

Ключевые параметры: root — каталог с образами и снапшотами, state — сокеты и временные файлы, snapshotter — обычно overlayfs. Для Kubernetes обязательно включите SystemdCgroup = true в опциях рантайма runc: без этого kubelet и systemd по-разному считают cgroup, и поды ведут себя нестабильно под нагрузкой.

Пространства имён и ctr

containerd разделяет объекты по namespace. Docker работает в moby, Kubernetes — в k8s.io, а ctr по умолчанию смотрит в default. Поэтому «пустой» список контейнеров на ноде Kubernetes — нормальная ситуация, если забыть про -n.

sudo ctr -n k8s.io containers ls
sudo ctr -n k8s.io tasks ls
sudo ctr images pull docker.io/library/alpine:latest
sudo ctr run --rm docker.io/library/alpine:latest demo /bin/sh

ctr run запускает процесс без сети и проброса портов, зато без лишних слоёв. Для повседневной работы удобнее nerdctl — он даёт синтаксис, похожий на Docker, и умеет run -p, compose и сборку через BuildKit. ctr оставьте для диагностики: он ближе к API и показывает то, что скрывают обёртки.

CRI и crictl

Kubelet не использует ctr: он ходит в CRI-плагин по тому же сокету. Для отладки есть crictl, который понимает поды, sandbox-контейнеры и логи. Настройте /etc/crictl.yaml, чтобы не передавать endpoint каждый раз.

runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
sudo crictl ps -a
sudo crictl logs --tail=50 CONTAINER_ID
sudo crictl inspect CONTAINER_ID | jq '.info.runtimeSpec.process.args'
sudo crictl stats

Если pod застрял в ContainerCreating, смотрите события через kubectl describe pod, а затем проверяйте containerd: crictl images покажет, скачался ли образ, crictl pods — создан ли sandbox. Частая причина — недоступный реестр или несовпадение архитектуры образа.

Отдельная история — sandbox-образ. Каждому поду нужен контейнер-«песочница» на базе pause: он держит network namespace, а контейнеры пода присоединяются к нему. Если этот образ не скачивается, pod навсегда остаётся в ContainerCreating, хотя приложение ни при чём. Проверьте crictl images | grep pause и доступность реестра, указанного для sandbox в конфигурации CRI: во внутренней сети его часто забывают отзеркалить.

Реестры и зеркала

Настройки реестров в CRI задаются через каталог certs.d. Для каждого хоста создаётся подкаталог с файлом hosts.toml, где перечислены зеркала и параметры TLS. Это удобнее, чем править глобальные переменные окружения, и работает одинаково для Docker Hub и внутренних реестров.

mkdir -p /etc/containerd/certs.d/docker.io
cat >/etc/containerd/certs.d/docker.io/hosts.toml <<'EOF'
server = "https://docker.io"
[host."https://mirror.example.com"]
  capabilities = ["pull", "resolve"]
EOF
sudo systemctl restart containerd

Отладка и обслуживание

  • ctr plugin ls — какие плагины загружены; выключенный CRI объясняет, почему kubelet не видит рантайм.
  • ctr -n k8s.io snapshots ls — снапшоты; их количество растёт, если образы давно не чистили.
  • crictl rmi --prune — удаляет неиспользуемые образы, не трогая те, на которые ссылаются контейнеры.
  • journalctl -u containerd -f — живой лог; ошибки вида failed to pull обычно содержат точный код ответа реестра.
sudo ctr plugin ls | grep -v ok
sudo ctr -n k8s.io snapshots ls | wc -l
sudo crictl rmi --prune
sudo ss -lntp | grep containerd

Перезапуск systemctl restart containerd не убивает работающие контейнеры: shim-процессы остаются, а новый демон подхватывает их при старте. Но если вы удалили снапшот или слой, на котором держится файловая система контейнера, восстановить её не получится — сначала останавливайте нагрузку, потом чистите.

Итог

containerd — это средний слой, который стоит знать отдельно от Docker и Kubernetes. Он отвечает за образы, снапшоты и запуск процессов, а его конфигурация умещается в один файл. Для диагностики держите под рукой ctr -n k8s.io, crictl и journalctl -u containerd: этого набора хватает, чтобы отличить проблему рантайма от проблемы сети или реестра.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте