containerd — runtime pre produkčné Kubernetes
containerd je priemyselný štandard pre kontajnerový runtime. Je to CNCF Graduated projekt, ktorý dnes poháňa väčšinu produkčných Kubernetes klastrov na svete — od spravovaných služieb ako EKS, GKE a AKS až po vlastnú on-premise infraštruktúru. Na rozdiel od Dockera ako celku je containerd minimalistický daemon zameraný čisto na správu životného cyklu kontajnerov, pull a správu obrazov a ich ukladanie.
Vznik a história
Docker Engine, ktorý prišiel na scénu v roku 2013, bol spočiatku monolitická aplikácia. S rastúcim ekosystémom sa ukázalo, že je potrebné vyčleniť nízkoúrovňový runtime do samostatnej, znovu použiteľnej knižnice. V roku 2016 Docker Inc. vyextrahoval jadro runtime logiky do projektu containerd a v marci 2017 ho daroval CNCF (Cloud Native Computing Foundation). Projekt dosiahol CNCF Graduated status v roku 2019 — čím sa zaradil po bok Kubernetes, Prometheus a Envoy ako zrelá produkčná technológia.
Dôvod vzniku bol prostý: Kubernetes potreboval štandardizované rozhranie pre komunikáciu s runtime (CRI — Container Runtime Interface, definované v roku 2016). Docker nebol CRI-kompatibilný, pretože vznikol skôr. Riešením bol dočasný adaptér dockershim priamo v kóde kubeletu. Tento workaround bol problematický — udržiavanie dockershimu bolo záťažou pre core Kubernetes tím a každá nová funkcia CRI sa musela duplicitne implementovať aj pre dockershim. Výsledkom bolo rozhodnutie dockershim odstrániť.
Architektúra containerd
containerd nie je len jednoduchý wrapper nad runc. Je to plnohodnotný daemon s pluginovým modelom, ktorý zabezpečuje celý životný cyklus kontajnera.
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes kubelet / ctr / nerdctl │
└────────────────────────┬────────────────────────────────────┘
│ gRPC (CRI alebo containerd API)
┌────────────────────────▼────────────────────────────────────┐
│ containerd daemon (/run/containerd/containerd.sock) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ CRI Plugin │ │ Content Store│ │ Snapshotter │ │
│ │ (io.cri.v1) │ │ (blobs, OCI) │ │ (overlayfs, ...) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Sandbox API │ │ Task Service│ │ Transfer Service│ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│ exec + shim API
┌────────────────────────▼────────────────────────────────────┐
│ containerd-shim-runc-v2 (per-kontajner proces) │
│ └──► runc / crun (OCI runtime — spúšťa kontajner) │
└─────────────────────────────────────────────────────────────┘
containerd daemon — centrálny long-running proces. Počúva na Unix sockete, spravuje metadáta (uložené v bolt DB), orchestruje snapshoty, pull obrazov a lifecycle kontajnerov.
containerd-shim — ľahký proces sprostredkovateľa, ktorý existuje pre každý bežiaci kontajner. Jeho úlohou je odizolovat containerd daemon od životného cyklu konkrétneho kontajnera — ak containerd reštartuje, kontajnery naďalej bežia. Shim tiež spravuje stdio streamy a exit status.
runc / crun — OCI runtime, ktorý skutočne vytvára kontajner — namespaces, cgroups, seccomp, capabilities. runc je referenčná implementácia v Go. crun je rýchlejšia alternatíva v C, odporúčaná pri vysokej hustote podov (nižšia spotreba pamäte, rýchlejší start).
Content Store — imutabilná blob store pre vrstvy obrazov a manifesty. Organizovaná podľa OCI distribution spec — každý blob adresovaný SHA256 digestom.
Snapshotters — pluginy pre správu filesystémov kontajnerov:
| Snapshotter | Popis |
|---|---|
overlayfs |
Predvolený na Linuxe, vyžaduje kernel 4.0+, väčšina produkcie |
btrfs |
Native COW snapshoty na btrfs filesystéme |
zfs |
Native ZFS snapshoty, vhodné pre storage-heavy workloady |
stargz |
Lazy-pull — kontajner štartuje skôr, ako sa stiahne celý obraz |
native |
Fallback bez COW, iba pre testovanie |
CRI Plugin — vstavaný plugin io.containerd.cri.v1.runtime implementuje Kubernetes Container Runtime Interface. Cez neho kubelet komunikuje s containerd pomocou gRPC.
Vzťah k iným runtimem
Docker a containerd
Docker Desktop a Docker Engine dnes interne používajú containerd ako runtime. Keď spustíte docker run, Docker CLI komunikuje s Docker Engineom, ktorý deleguje prácu na containerd. Inými slovami, ak používate Docker, containerd už beží pod kapotou.
CRI-O
CRI-O je alternatívny runtime implementujúci CRI, vytvorený priamo pre Kubernetes spoločnosťami Red Hat, IBM a Intel. Je úzko špecializovaný — neobsahuje nič, čo nie je potrebné pre Kubernetes. Je predvoleným runtimem na OpenShift. Na rozdiel od containerd neposkytuje standalone CLI na správu kontajnerov mimo K8s.
Mirantis cri-dockerd
Po odstránení dockershimu vydali Mirantis a Docker komunitný nástroj cri-dockerd — adaptér, ktorý implementuje CRI a deleguje volania na Docker Engine. Je to spôsob, ako zachovať Docker ako runtime v Kubernetes bez dockershimu. Pre nové nasadenia sa neodporúča.
Podman
Podman je daemonless nástroj pre správu kontajnerov kompatibilný s Docker CLI. Používa libcontainer (rovnaká knižnica ako runc), ale nepotrebuje bežiaci daemon. Neimplementuje CRI — pre Kubernetes sa bežne nepoužíva ako runtime (existuje experimentálny podman-remote pre niektoré prípady).
Kata Containers, gVisor, youki
Tieto projekty sú alternatívne OCI runtime implementácie:
- Kata Containers — každý kontajner beží v ľahkej VM (qemu/firecracker), silná izolácia.
- gVisor — Google sandbox runtime, interceptuje syscally v user space.
- youki — runc-kompatibilná implementácia v Ruste.
Všetky môžu byť nakonfigurované ako RuntimeClass v Kubernetes a containerd ich orchestruje rovnako ako runc — cez shim vrstvu.
Prečo Kubernetes opustil dockershim
Kubernetes 1.20 (december 2020) označil dockershim ako deprecated. Kubernetes 1.24 (máj 2022) ho definitívne odstránil.
Hlavné dôvody:
- Udržiavacia záťaž — dockershim bol špecifický kód v kubelete, ktorý musel sledovať každú verziu Docker Engine.
- Redundantná vrstva — Docker → dockershim → containerd. Kubernetes takto komunikoval s containerd cez dve medzivrstvy. Priame CRI volanie na containerd odstraňuje jednu vrstvu.
- Funkcionálna parita — CRI definuje štandardné rozhranie; Docker prinášal funkcie (volumes, networking) ktoré Kubernetes nepotreboval a spravoval si vlastné.
- Bezpečnosť — dockerd beží ako root a má širší attack surface.
Po migrácii na containerd nahlásili operátori typicky zrýchlenie pod start time, nižšiu spotrebu pamäte a jednoduchší debug (jeden daemon menej).
Inštalácia a CLI nástroje
Inštalácia na Ubuntu/Debian
# Pridanie Docker APT repozitára (obsahuje aj containerd.io)
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y containerd.io
# Generovanie predvolenej konfigurácie
containerd config default > /etc/containerd/config.toml
systemctl enable --now containerd
ctr — low-level CLI
ctr je vstavaný CLI nástroj containerd. Je nízkoúrovňový a nie je určený na bežné každodenné použitie — hlavne pre debugging a administráciu.
# Zoznam namespace
ctr namespaces list
# Pull obrazu (do namespace "default")
ctr image pull docker.io/library/nginx:alpine
# Zoznam stiahnutých obrazov
ctr images list
# Spustenie kontajnera (jednoduchý, nie v poda)
ctr run --rm docker.io/library/nginx:alpine mynginx
# Zoznam bežiacich taskov
ctr tasks list
# Exec do bežiaceho kontajnera
ctr tasks exec --exec-id myshell mynginx sh
# Vymazanie obrazu
ctr images rm docker.io/library/nginx:alpine
Dôležitý koncept: containerd používa namespaces na izoláciu kontajnerov a obrazov. Kubernetes používa namespace k8s.io, Docker používa moby. Pri debugovaní K8s podov je preto potrebné:
ctr -n k8s.io tasks list
ctr -n k8s.io images list
nerdctl — Docker-compatible CLI
nerdctl (contaiNERD CTL) je Docker-kompatibilný CLI pre containerd vytvorený komunitou. Pokrýva väčšinu docker príkazov vrátane Compose, rootless a lazy pull.
# Inštalácia nerdctl (full bundle obsahuje aj BuildKit, CNI pluginy)
wget https://github.com/containerd/nerdctl/releases/latest/download/nerdctl-full-2.1.3-linux-amd64.tar.gz
tar -C /usr/local -xzf nerdctl-full-2.1.3-linux-amd64.tar.gz
# Teraz nerdctl funguje ako docker
nerdctl pull nginx:alpine
nerdctl run -d -p 8080:80 --name web nginx:alpine
nerdctl ps
nerdctl logs web
nerdctl exec -it web sh
nerdctl stop web && nerdctl rm web
# nerdctl compose — Docker Compose kompatibilita
nerdctl compose up -d
nerdctl compose down
nerdctl v2.x (2025) je kompatibilný s containerd 1.7 až 2.2 (verzia 1.6 prešla na EOL).
Konfigurácia: /etc/containerd/config.toml
containerd 2.0 zaviedol config version 3 s reorganizovanými plugin cestami. Kritická zmena: CRI plugin premenoval z io.containerd.grpc.v1.cri na io.containerd.cri.v1.runtime.
# /etc/containerd/config.toml
# Platí pre containerd 2.x (config version 3)
version = 3
[plugins.'io.containerd.cri.v1.runtime']
# Sandbox (pause) kontajner
sandbox_image = "registry.k8s.io/pause:3.10"
[plugins.'io.containerd.cri.v1.runtime'.containerd]
default_runtime_name = "runc"
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
# DÔLEŽITÉ: systemd driver musí byť zarovnaný s kubelet --cgroup-driver
SystemdCgroup = true
[plugins.'io.containerd.cri.v1.images']
# Registry mirrors — pull-through cache (napr. lokálne zrkadlo)
[plugins.'io.containerd.cri.v1.images'.registry]
[plugins.'io.containerd.cri.v1.images'.registry.mirrors]
[plugins.'io.containerd.cri.v1.images'.registry.mirrors."docker.io"]
endpoint = ["https://registry-mirror.example.internal"]
[plugins.'io.containerd.cri.v1.images'.registry.mirrors."registry.k8s.io"]
endpoint = ["https://k8s-mirror.example.internal"]
# Metrics endpoint pre Prometheus scraping
[metrics]
address = "127.0.0.1:1338"
grpc_histogram = true
Pre containerd 1.x (config version 2) je syntax odlišná — pluginy sú pod io.containerd.grpc.v1.cri a dvojité úvodzovky sú štandard.
# Verifikácia konfigurácie
containerd config dump | head -50
# Reštart po zmene
systemctl restart containerd
Správa obrazov a content store
containerd implementuje OCI Distribution Spec pri pull/push a OCI Image Spec pri ukladaní. Každý blob (vrstva, manifest, config) je uložený SHA256-adresovateľne v content store:
/var/lib/containerd/io.containerd.content.v1.content/blobs/sha256/
Registry mirrors a pull-through cache
Pull-through cache je kľúčová produkčná optimalizácia: miesto priameho sťahovania z internetu cez Docker Hub (rate-limit 100 pull/6h pre anonymných) alebo registry.k8s.io noody pullujú z interného zrkadla. Sardonic server to má nakonfigurované — interný registry mirror cachuje frekventne používané obrazy a eliminuje závislosť od externých registrov pri štarte nových nodov.
Image garbage collection
containerd automaticky zbiera nepoužívané obrazy (GC). V Kubernetes orchestruje GC kubelet cez CRI ImageFsInfo a RemoveImage. Parametre GC sú konfigurovateľné cez kubelet:
--image-gc-high-threshold=85 # % diskového využitia triggering GC
--image-gc-low-threshold=80 # % cieľové po GC
Image store vs snapshot store
V containerd 2.0 bola zavedená separácia image store (metadáta, manifesty) od snapshot store (rozbalené vrstvy filesystému). Predtým boli úzko previazané — teraz umožňujú nezávislú správu a budúce funkcie ako zdieľanie vrstiev medzi rôznymi sandbox typmi.
Snapshotters — deep dive
Snapshotter je kľúčová abstrakcia: zodpovedá za prípravu rootfs pre každý kontajner. Funguje na princípe COW (Copy-on-Write) — každá vrstva je snapshot predchádzajúcej.
overlayfs (predvolený)
Na väčšine moderných Linux distribúcií (kernel 4.0+) je overlayfs najlepšia voľba. Vrstvová štruktúra obrazu sa mapuje priamo na overlay mount — dolné vrstvy sú read-only, horná vrstva (upperdir) je read-write kontajnerová vrstva. Žiadne kopírovanie dat pri čítaní (COW sa aktivuje iba pri zápise).
# Overenie aktívneho snapshottera
containerd config dump | grep -A5 snapshotter
stargz Snapshotter — lazy pull
eStargz (estargz — enhanced STARGZ) je formát obrazu, ktorý umožňuje lazy pull: kontajner môže štartovať ešte predtým, ako sa stiahol celý obraz. Namiesto toho sa stiahnu iba potrebné súbory (na základe TOC — Table of Contents).
Výhoda pri veľkých ML/AI obrazoch (pytorch, tensorflow) kde sú gigabajty dat, ale kontajner pri štarte potrebuje len zlomok súborov.
# Konvertovanie obrazu do eStargz formátu
nerdctl image convert --estargz --oci \
nginx:alpine \
registry.example.com/nginx:alpine-estargz
# Push do registra
nerdctl push registry.example.com/nginx:alpine-estargz
# Pri pull s nerdctl + stargz snapshotter sa lazy pull aktivuje automaticky
nerdctl pull registry.example.com/nginx:alpine-estargz
Stargz Snapshotter je samostatný CNCF projekt dostupný ako plugin pre containerd.
Produkčné tipy
Monitoring
containerd od verzie 1.5+ exponuje Prometheus metriky na konfigurovanom endpointe (predvolene 127.0.0.1:1338). Pre scraping v Prometheus:
# prometheus.yml
scrape_configs:
- job_name: containerd
static_configs:
- targets: ["localhost:1338"]
Kľúčové metriky:
container_runtime_containerd_container_*— počty, stavy kontajnerovcontainer_runtime_containerd_task_*— operácie na taskochcontainer_runtime_containerd_snapshotter_*— výkon snapshotteracontainer_runtime_containerd_image_*— pull latencie
Graceful drain noodu
Pri maintenance noodu v Kubernetes je dôležité nezabiť containerd počas drain-ovania:
# Správny postup
kubectl drain node01 --ignore-daemonsets --delete-emptydir-data
# Počkajte kým sa všetky pody presunú
kubectl cordon node01
# Až potom môžete reštartovať alebo updatovať containerd
systemctl restart containerd
Log rotation
containerd samotný používa journald alebo file logging. Pre kontajnerové logy (stdout/stderr) je log rotation nastaviteľná v Kubernetes cez kubelet konfiguráciu. containerd odovzdáva logy cez shim a kubelet ich spravuje.
Plugin model
containerd 2.0 má plnohodnotný plugin model cez gRPC. NRI (Node Resource Interface) umožňuje externým pluginom reagovať na lifecycle udalosti kontajnerov — napr. NUMA topology hints, CPU pinning, hugepages allocation — bez modifikácie containerd samotného.
Gotchas a časté problémy
Cgroup v1 vs v2 driver mismatch
Toto je najčastejší produkčný problém pri migrácii alebo nových nasadeniach. Pravidlo je jednoduché: ak systém používa cgroup v2 (overíte cez stat -fc %T /sys/fs/cgroup/) a init systém je systemd, vždy nastavte SystemdCgroup = true v containerd aj --cgroup-driver=systemd v kubelete. Nesúlad sa prejavuje náhodným zabíjaním kontajnerov alebo OOM errory bez skutočného OOM.
# Overenie verzie cgroup na node
stat -fc %T /sys/fs/cgroup/
# tmpfs = cgroup v1
# cgroup2fs = cgroup v2
# Overenie aktuálneho drivera
containerd config dump | grep SystemdCgroup
Kernel version requirements
- overlayfs vyžaduje minimálne kernel 4.0 (väčšina distribúcií ho má)
- Pre niektoré seccomp/apparmor profily sú potrebné novšie kernely
- btrfs a zfs snapshottery vyžadujú príslušné kernel moduly
- rootless containerd vyžaduje kernel 5.11+ (user namespaces s overlayfs)
Image rootfs pinning
V produkčnom Kubernetes je dobrá prax pinnúť digest obrazov namiesto tagov:
image: nginx@sha256:a5127daff3d6f4558be7c9b6e70e3c097b55b7fb2be0f4c3bf66f7f65ebe4b5c
containerd content store zaručuje imutabilitu blobs — rovnaký digest vždy znamená rovnaký obsah.
Config version mismatch po upgrade
Pri upgrade z containerd 1.x na 2.x je potrebné regenerovať config — config version 2 a 3 nie sú spätne kompatibilné v plugin cestách:
# Záloha starého configu
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
# Generovanie nového
containerd config default > /etc/containerd/config.toml
# Následne manuálne pridajte zmeny (registry mirrors, SystemdCgroup, etc.)
Namespace izolácia pri debugovaní K8s podov
Začiatočníci often zabúdajú, že ctr images list bez -n k8s.io zobrazí prázdny zoznam — K8s pody sú v namespace k8s.io:
# Toto nezobrazí K8s obrazy:
ctr images list
# Toto áno:
ctr -n k8s.io images list
ctr -n k8s.io tasks list
Porovnanie: containerd vs CRI-O vs cri-dockerd
| Kritérium | containerd | CRI-O | cri-dockerd |
|---|---|---|---|
| Primárny use case | Všeobecný runtime (K8s aj standalone) | Výlučne Kubernetes | K8s s Docker Engine backend |
| CRI kompatibilita | Plná | Plná | Plná (adaptér) |
| Standalone CLI | ctr, nerdctl |
Nie | cez Docker CLI |
| Default na | EKS, GKE, AKS, kubeadm, K3s | OpenShift (RHEL) | — |
| Daemon overhead | Stredný (~30 MB RAM) | Nízky (~15 MB RAM) | Vysoký (Docker + dockerd) |
| Ekosystém | Rozsiahly (Docker, CNCF) | Red Hat orientovaný | Docker oriented |
| Pod density (150+ podov) | Dobré | Mierne lepšie | Horšie |
| Maintenance | Aktívny (CNCF) | Aktívny (Red Hat) | Obmedzený |
| Odporúčanie | Väčšina produkcie | OpenShift, Red Hat stack | Iba migrácia zo starého Docker setup |
Záver porovnania: containerd je správna predvolená voľba pre väčšinu tímov. CRI-O je legitímna alternatíva pri extrémnej pod hustote alebo Red Hat/OpenShift prostredí. cri-dockerd je technologický dlh — ak ho používate, naplánujte migráciu.
containerd 2.x — nová éra
containerd 2.0 (november 2024)
Prvý major release od 1.0 v roku 2017. Kľúčové zmeny:
- Config version 3 — reorganizácia plugin namespace (breaking change pre config.toml)
- Transfer Service GA — štabilné API pre presun artefaktov medzi zdrojmi a cieľmi (registry, OCI layout, running container)
- Sandbox API GA — štabilné rozhranie pre multi-container prostredia (pody, VM sandboxes). Umožňuje runtimem ako Kata definovať sandbox lifetime nezávisle od jednotlivých kontajnerov.
- NRI GA — Node Resource Interface pre externe pluginy
- Odstránenie deprecated features z 1.x série (napr. starý image service, legacy plugin API)
- Minimálny kernel: 4.9+, minimálny Go: 1.21+
containerd 2.1 (máj 2025)
- OCI Image Volumes — Kubernetes 1.31+ feature; volumes priamo z OCI obrazov bez extra PVC. Veľké datasety (ML modely, statické assets) distribuovateľné ako obrazy a mountovateľné ako volumes bez kopírovania do overlay.
- Sandbox Update API — modifikovanie atribútov existujúceho sandboxu za behu (spec, runtime, labels).
- Vylepšený snapshotter plugin system — lepšia izolácia a hot-swap snapshotterov.
Kubernetes kompatibilita
- containerd 1.6.x — Kubernetes 1.20 – 1.29 (EOL)
- containerd 1.7.x — Kubernetes 1.24 – 1.31 (LTS do 2026-03)
- containerd 2.0.x — Kubernetes 1.24+ (LTS do 2027-03)
- containerd 2.1.x — Kubernetes 1.24+ (aktuálna stablená vetva)
Zhrnutie
containerd prešiel od anonymného Docker internals komponentu k CNCF Graduated projektu, ktorý dnes poháňa majoritnú časť cloudovej infraštruktúry. Jeho architektúra — daemon + shim + OCI runtime — dosahuje správnu rovnováhu medzi flexibilitou a jednoduchosťou. Plugin model cez NRI, snapshottery pre rôzne storage backendy a stabilné Sandbox API v 2.x robia z containerd runtime pripravený na ďalšie roky vývoja kontajnerovej infraštruktúry.
Pre nové Kubernetes nasadenia je containerd jasná prvá voľba. Pre existujúce Docker-based prostredia je migrácia na containerd priamočiara a prináša merateľné zlepšenia výkonu a prevádzkovej jednoduchosti.