CRI and containerd

The Container Runtime Interface and containerd

The kubelet does not start containers itself. It calls a runtime through the Container Runtime Interface (CRI), a gRPC API for sandboxes, containers and images. The two common runtimes are containerd 234,762 , the daemon under Docker Engine 514 (How Linux Isolates), and CRI-O 669,542 , built for Kubernetes 5,150 alone. The kubelet's adapter for Docker Engine, dockershim, was removed in 1.24 (May 2022); Docker-built images run unchanged because they are OCI images. crictl 2,016 (github.com/kubernetes-sigs/cri-tools (https://github.com/kubernetes-sigs/cri-tools 2,016 )) is a CRI client for debugging a node:

The worker node through the CRI: runtime, Pod sandboxes and containersYAML
W=l3-booknest-worker
docker exec $W crictl version | grep Runtime
docker exec $W crictl pods --state ready -o json \
  | jq -r '.items[] | "\(.id[0:13])  \(.metadata.namespace)/\(.metadata.name)"'
docker exec $W crictl ps -o json \
  | jq -r '.containers[] | "\(.podSandboxId[0:13])  container \(.metadata.name)"'
Output
RuntimeName:  containerd
RuntimeVersion:  v2.3.4
RuntimeApiVersion:  v1
acc5b3690c727  default/web-64546c896b-fh6fn
abdac73884d88  default/web-64546c896b-7r29z
054b7e9ba989d  kube-system/kube-proxy-grdh5
432273f0c3908  kube-system/kindnet-9t4ld
acc5b3690c727  container booknest-web
abdac73884d88  container booknest-web
432273f0c3908  container kindnet-cni
054b7e9ba989d  container kube-proxy

Every Pod first gets a sandbox: containerd starts a tiny pause container (registry.k8s.io/pause:3.10, 320 kB) whose only job is to hold the Pod's network namespace and IP address. The app containers then join that namespace, which is why containers in one Pod reach each other on localhost and why a restarting container keeps its Pod IP. ps inside the node shows one containerd-shim per Pod with its pause and app processes beneath it, so containerd itself can restart without killing containers.

From Pod object to process: kubelet, CRI, containerd, shim, pause and app containers
From Pod object to process: kubelet, CRI, containerd, shim, pause and app containers

crictl bypasses the API server: a container you stop with crictl stop is simply restarted by the kubelet, because the Pod object still asks for it.