The kubelet requires a CRI-compatible container runtime (containerd, CRI-O, Docker). This error occurs when the runtime is not installed, not running, or disabled. Fix by installing/starting the runtime or enabling the CRI plugin.
Kubernetes 1.20+ requires a Container Runtime Interface (CRI) compliant runtime on each node. The kubelet cannot create or manage containers without one. The error occurs when: 1. No container runtime is installed on the node 2. The runtime service isn't running 3. The CRI plugin is disabled (especially common with containerd) 4. The kubelet can't connect to the runtime socket This is a blocking issueβthe node cannot schedule any pods until resolved.
Check if containerd, Docker, or CRI-O is installed:
# Check for containerd:
which containerd
containerd --version
# Check for Docker:
which docker
docker --version
# Check for CRI-O:
which crio
crio --versionIf none exist, install one (containerd is recommended).
Ensure the runtime is running and will start on boot:
# For containerd:
sudo systemctl start containerd
sudo systemctl enable containerd
# For Docker:
sudo systemctl start docker
sudo systemctl enable docker
# For CRI-O:
sudo systemctl start crio
sudo systemctl enable crio
# Verify it's running:
sudo systemctl status containerdcontainerd sometimes ships with CRI plugin disabled by default:
# Check the config:
sudo cat /etc/containerd/config.toml | grep disabled_plugins
# If you see disabled_plugins = ["cri"], edit it:
sudo nano /etc/containerd/config.toml
# Comment out or remove the line:
# disabled_plugins = ["cri"]
# Or delete and regenerate the config:
sudo rm /etc/containerd/config.toml
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
# Restart containerd:
sudo systemctl restart containerdEnsure kubelet knows where to find the runtime:
# Check kubelet configuration:
sudo cat /etc/kubernetes/kubelet.conf | grep container-runtime
# Typical runtime socket paths:
# - containerd: unix:///run/containerd/containerd.sock
# - Docker: unix:///var/run/docker.sock
# - CRI-O: unix:///var/run/crio/crio.sock
# If needed, edit kubelet service:
sudo systemctl edit kubelet
# Add or update the flag (if not already set):
# Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
# Restart kubelet:
sudo systemctl daemon-reload
sudo systemctl restart kubeletCheck if the runtime socket exists and is readable:
# For containerd:
ls -la /run/containerd/containerd.sock
# For Docker:
ls -la /var/run/docker.sock
# For CRI-O:
ls -la /var/run/crio/crio.sock
# Test connection:
sudo ctr version # for containerd
docker ps # for DockerThe socket should exist and be readable by the kubelet user (usually root).
Review detailed kubelet logs:
# View kubelet journal:
sudo journalctl -u kubelet -n 50 -f
# Or check kubelet logs:
sudo cat /var/log/kubelet.log | tail -100
# Look for:
# - Connection refused
# - File not found
# - Permission denied
# - Version mismatchThe actual error message will guide the next steps.
If the runtime is corrupted or broken, reinstall it:
# For containerd:
sudo apt-get remove containerd -y
sudo apt-get install containerd -y
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
# For Docker:
sudo apt-get remove docker.io docker-ce -y
sudo apt-get install docker.io -y
sudo systemctl start docker
# Verify:
sudo systemctl status containerdAfter fixing the runtime, rejoin the cluster:
# For worker nodes:
kubeadm reset # Only if the node was corrupted
kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
# For control plane nodes (if node isn't working):
sudo systemctl restart kubelet
# Check node status:
kubectl get nodes -o wide
kubectl describe node <node-name>The node should transition to Ready within 1-2 minutes.
### Container Runtime Versions
Kubernetes 1.36 and later no longer support containerd 1.x (deprecated v1 CRI API). Ensure:
containerd --version # Should be 1.7.0+### CRI-O Setup
If using CRI-O, ensure proper installation:
# Install from official repo (Ubuntu):
curl -fsSL https://pkgs.k8s.io/addons:/cri-o/stable/v1.30/deb/Release.key | sudo apt-key add -
echo "deb https://pkgs.k8s.io/addons:/cri-o/stable/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/cri-o.list
sudo apt-get install cri-o -y### containerd on WSL2
On Windows with WSL2:
# Install from official source:
curl -fsSL https://github.com/containerd/containerd/releases/download/v1.7.0/containerd-1.7.0-linux-amd64.tar.gz | tar xzvC /usr/local
# Ensure systemd is running in WSL2### Docker Daemon Configuration
For Docker, verify daemon is accessible to kubelet:
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"storage-driver": "overlay2"
}### Testing Runtime Directly
Verify runtime works independent of Kubernetes:
# containerd:
ctr --namespace k8s.io image list
ctr run --rm alpine alpine echo "Hello"
# Docker:
docker ps
docker run --rm alpine echo "Hello"
# CRI-O:
crictl ps
crictl runIf this fails, the runtime itself is broken, not Kubernetes.
Failed to connect to server: connection refused (HTTP/2)
How to fix "HTTP/2 connection refused" error in Kubernetes
No subnets found for EKS cluster
How to fix "eks subnet not found" in Kubernetes
missing request for cpu in container
How to fix "missing request for cpu in container" in Kubernetes HPA
unable to compute replica count
How to fix "unable to compute replica count" in Kubernetes HPA
error: context not found
How to fix "error: context not found" in Kubernetes