Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке containerd і яка його роль в Docker-екосистемі?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**containerd** це CNCF graduated container-runtime, спочатку витягнутий з Docker. Це шар, що реально pull'ить image, керує container-life-cycle і говорить з нижчим OCI-runtime (`runc`). І Docker, і Kubernetes беруть containerd під капотом. ``` Docker: docker → dockerd → containerd → runc → container K8s: kubelet → containerd → runc → container ``` **Головне:** containerd незалежний від Docker. Kubernetes з 1.24 говорить з containerd напряму через CRI, відкинувши dockershim. Tools: `ctr` (low-level) і `nerdctl` (Docker-CLI-сумісний) взаємодіють з containerd без dockerd.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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'ить усе.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.