Q: What is the Container Runtime Interface (CRI) in Kubernetes? How does kubelet communicate with runtimes like containerd and CRI-O via gRPC, and why was dockershim deprecated in v1.24?
Deep dive into the Container Runtime Interface (CRI) in Kubernetes: gRPC client-server model, kubelet integration, containerd vs CRI-O, OCI runtime spec (runc), and why dockershim was deprecated.
Want to master this scenario in a live sandbox? KodeKloud's CKA & CKAD Hands-On Certification Track covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
How CRI Works: The gRPC Client-Server Model
The communication architecture on every Kubernetes worker node:
- Kubelet (CRI Client): The node agent acts as a gRPC client calling a local UNIX domain socket (e.g.,
/run/containerd/containerd.sock). - CRI Runtime (gRPC Server): A daemon like containerd or CRI-O that implements two specific gRPC services:
- 1. RuntimeService: Manages container lifecycles, sandbox pods, exec, attach, and stop operations (
RunPodSandbox,CreateContainer,StartContainer,StopContainer). - 2. ImageService: Manages pulling, listing, inspecting, and deleting container images (
PullImage,ListImages,RemoveImage).
The Layered Runtime Hierarchy (CRI vs OCI)
Understanding the division of labor:
- High-Level Runtime (CRI): containerd or CRI-O. Responsible for image pulling, network namespace setup (CNI), unpackaging layers, and managing storage.
- Low-Level Runtime (OCI): runc (or crun, gVisor, Kata Containers). Implements the Open Container Initiative (OCI) runtime specification. Interacts directly with Linux kernel primitives:
namespaces,cgroups,seccomp, andchrootto physically launch processes. - Shim (containerd-shim-v2): A lightweight daemon that stays running per pod to hold open standard I/O streams and exit codes even if the main containerd daemon restarts during node upgrades.
Why Was Dockershim Deprecated in v1.24?
The architectural rationale behind the transition:
- Docker was never designed for Kubernetes; it was designed for human workstations with unnecessary extras (Docker swarm, volume plugins, build tools).
- Kubelet had to communicate with an internal adapter called dockershim, which called the Docker daemon, which called containerd, which called runc! (3 redundant hops).
- By deprecating dockershim, Kubernetes eliminated the Docker daemon middleman. Kubelet communicates directly with containerd via CRI, reducing node memory overhead, CPU latency, and maintenance baggage.
Debugging CRI in Production with crictl
Essential CLI tools replacing docker commands on nodes:
crictlis designed specifically for debugging CRI runtimes on Kubernetes nodes and ignores non-Kubernetes Docker containers.
- The Container Runtime Interface (CRI) is a gRPC protocol that allows kubelet to manage pods and images across different container runtimes without recompiling Kubernetes.
- It splits responsibilities into high-level runtimes like containerd and CRI-O that handle image pulling and CNI, which then invoke low-level OCI runtimes like runc to start isolated Linux processes.
- Dockershim was removed in v1.24 because Docker Engine introduced unnecessary overhead; kubelet now speaks directly to containerd via CRI, improving performance and stability.