Skip to main content

Що таке containerd і яка його роль в Docker-екосистемі?

containerd це production-grade container-runtime, що живе між high-level оркестраторами (Docker, Kubernetes) і low-level OCI-runtime (runc). Це один з найуспішніших infrastructure-компонентів, про який ніхто не говорить, тихо крутить більшість container у світі.

Теорія

TL;DR

  • containerd = container-daemon. Керує container-life-cycle: pull image, unpack, run, monitor, network-setup.
  • Спочатку витягнутий з Docker у 2017 як окремий компонент, тоді donated CNCF у 2019. CNCF graduated проект.
  • Використовується Docker (daemon-стек: dockerd → containerd → runc).
  • Використовується Kubernetes напряму (з 1.24, dockershim видалено).
  • Tooling: ctr (low-level admin), nerdctl (Docker-CLI-сумісний).
  • runc нижче containerd, runc створює один container на invocation; containerd керує long-running orchestration.

Де containerd сидить

+----------------------------------------+ | User-facing tools | | docker / kubectl / podman / | | ctr / nerdctl | +----------------------------------------+ | | +---------v-----+ +------v-----------+ | dockerd | | kubelet | | (Docker only) | | (Kubernetes only)| +---------------+ +------------------+ | | +----+ +----+ v v +---------------+ | containerd | | (CRI server) | +---------------+ | +---------------+ | OCI-runtime | | runc / kata | | gVisor / etc | +---------------+ | +---------------+ | Container | | (процес) | +---------------+

Docker-користувачі б'ють dockerd, що делегує containerd. Kubernetes-користувачі б'ють kubelet, що використовує containerd напряму через CRI (Container Runtime Interface). Обидва врешті у тому самому containerd, потім runc.

Чому containerd було витягнуто

У 2014-2016 Docker був монолітом, що робив усе. Два тиски виникли:

  1. Kubernetes хотів runtime без решти Docker (без docker build, без Docker CLI, без Swarm). Просто «керувати container».
  2. Стандартизація — OCI-ініціатива хотіла чіткий контракт для runtime. Внутрішній код Docker не мав чистої абстракції.

Docker (компанія) витягнув containerd у 2017, donate'нув CNCF і reshape'нув Docker daemon, щоб використовувати containerd внутрішньо. Результат: той самий Docker, але runtime-шар тепер reusable будь-ким.

Що containerd реально робить

  • Image-management: pull з registry, зберігання шарів, підготовка rootfs.
  • Container-life-cycle: create, start, stop, pause, resume, kill, delete.
  • Snapshot-management: використовує storage-drivers (overlayfs, btrfs тощо) для управління filesystem-snapshot.
  • Process-supervision: через containerd-shim (один shim на container, переживає рестарти daemon).
  • Networking-handoff: САМ networking не робить; делегує CNI-плагінам (Kubernetes) або callback-API (Docker).
  • Метрики і події: експозить container-метрики; емітить події, на які оркестратори підписуються.

Що не робить:

  • Білд image (це buildkit / docker build / kaniko).
  • Дає CLI для end-users (бери ctr або nerdctl).
  • Network-policy / orchestration (це Kubernetes / Swarm / Cilium / Calico).
  • High-level UX (Docker дає це Docker-користувачам).

ctr — low-level admin-tool

Шиппиться з containerd. Говорить з gRPC API containerd напряму:

bash
# List image ctr images list # Pull image ctr images pull docker.io/library/alpine:3.21 # Запуск container ctr run --rm docker.io/library/alpine:3.21 mytest /bin/sh # Список running-task ctr tasks list

Не user-friendly; задумано для debug або low-level admin. Зверни увагу: containerd використовує namespaces для розділення клієнтів, Docker використовує moby, Kubernetes k8s.io. Щоб побачити Docker-container через ctr: ctr -n moby containers list.

nerdctl — Docker-сумісний CLI

bash
nerdctl run --rm hello-world # як docker run nerdctl ps nerdctl images nerdctl compose up -d # Compose-підтримка теж

nerdctl говорить Docker-style командами, але говорить з containerd напряму (без dockerd). Корисно у K8s-node, де Docker не встановлено, але container running.

containerd у Kubernetes (post-dockershim)

Kubernetes 1.24 (квітень 2022) видалив dockershim, compatibility-шар, що давав kubelet говорити з dockerd. Тепер kubelet говорить з containerd напряму через CRI:

# /etc/crictl.yaml runtime-endpoint: unix:///run/containerd/containerd.sock

Пряміше, простіше, менше moving-parts. crictl це Kubernetes-flavored CLI для debug на цьому шарі.

Типові помилки

Плутати containerd з runc

Люди часто думають, що вони взаємозамінні. Не так.

  • runc це one-shot CLI, що створює один container на invocation, тоді виходить. Реалізує OCI Runtime Spec.
  • containerd це long-running daemon, що керує life-cycle багатьох container. Викликає runc як tool.

Сприймати containerd як Docker-специфічний

Не так. Kubernetes використовує containerd без Docker. Те саме podman (через crun, схоже, але інше). containerd це незалежна інфраструктура, що Docker випадково теж використовує.

Спроба використати Docker-image на Kubernetes через маніпуляцію /var/lib/docker

Kubernetes containerd використовує /var/lib/containerd/, НЕ Docker /var/lib/docker/. Вони ізольовані. Щоб переміщати image, push у registry і pull на іншій стороні, або бери nerdctl save/load.

Плутати ctr -n moby і ctr -n k8s.io

Namespace containerd (moby, k8s.io, default) це ізоляція між клієнтами. Docker-container живуть у moby, K8s у k8s.io. Дефолтні ctr-команди query'їть default і нічого не знаходить.

Реальне застосування

  • Усі великі cloud-Kubernetes (EKS, GKE, AKS) беруть containerd як runtime.
  • Docker Engine використовує containerd внутрішньо (з Docker 18.09).
  • Edge / IoT: lightweight-footprint containerd робить його популярним на resource-constrained пристроях.
  • CRI-O (альтернатива containerd, використовується деякими OpenShift-деплоями) — та сама роль, інша реалізація. Обидва реалізують CRI Kubernetes.

Питання для поглиблення

Q: Яка різниця між containerd і Docker?


A: Docker це повна платформа: CLI, daemon (dockerd), build-tools, registry-client, networking, image-management. containerd це лише container-runtime частина — pull image, run container, manage life-cycle. Docker використовує containerd внутрішньо.

Q: Яка різниця між containerd і CRI-O?


A: Обидва реалізують Container Runtime Interface (CRI) Kubernetes. containerd ширший, використовується і Docker. CRI-O K8s-специфічний, легший. Функціонально еквівалентні для K8s; різні спільноти і design-філософії.

Q: Як containerd взаємодіє з OCI-runtime?


A: Через runtime-spec інтерфейс. containerd пише config.json (OCI Runtime Spec) і просить runtime (runc, kata, gVisor) створити container. Runtime викликається раз на container-старт; containerd-shim тоді supervise'їть.

Q: Що таке containerd-shim?


A: Малий процес на container, що тримає container stdin/stdout/stderr і переживає рестарт containerd. Якщо containerd помирає, shim тримає container живим; коли containerd повертається, він reconnect'ується через shim.

Q: (Senior) Як мігрувати workload з Docker на containerd-direct (без Docker-daemon)?


A: Kubernetes-managed: зміни kubelet-config показувати на containerd; видали dockershim-бінари (сучасний K8s уже це робить). Image-формат OCI, без конверсії. Image-pull працюють ідентично (той самий registry-протокол). Volume через CSI-плагіни. Networking через CNI-плагіни. Міграція переважно audit: що залежало від Docker-специфічної поведінки (Docker-socket-mounts у pod, посилання на /var/lib/docker)? Refactor цього. Для non-K8s сценаріїв заміни docker run на nerdctl run або podman run, ті самі флаги, інша daemon-модель.

Приклади

Inspecting Docker containerd

bash
# List Docker container через ctr sudo ctr -n moby containers list CONTAINER IMAGE RUNTIME a3f9d2b8c1e4f3a2... - io.containerd.runc.v2 # Те саме для K8s sudo ctr -n k8s.io containers list

Namespace-вибір (-n) направляє query у правильний slice стану containerd.

Використання nerdctl замість docker

bash
# nerdctl працює рівно як docker nerdctl run -d --name web -p 8080:80 nginx nerdctl ps nerdctl logs web nerdctl compose up -d # Але під капотом, без dockerd — лише containerd. ps -ef | grep dockerd # (нічого) ps -ef | grep containerd containerd ...

Корисно у середовищах, де Docker свідомо не встановлено (деякі K8s-node, hardened-host).

Розгляд handoff containerd → runc

bash
# Коли container стартує, можна побачити ланцюг $ ps -ef | grep -E 'containerd|runc' | grep -v grep root 1235 1 /usr/bin/containerd root 4567 1235 containerd-shim-runc-v2 -id abc123 ... # Сам runc не у списку, він пробіг і вийшов # Процес container parent'нутий shim'ом (4567)

runc-invocation короткий; shim це що залишається. containerd це long-running daemon, що orchestrate'ить усе.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів