- https://github.com/containerd/containerd/blob/main/docs/getting-started.md
- https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd
containerd can be installed from the official binaries. For a manual install, the containerd.io package from Docker's repositories is easier because it also brings in runc and a systemd unit.
Install¶
Alma Linux / RHEL family¶
Remove any old Docker packages first:
sudo dnf remove -y docker docker-client docker-client-latest docker-common \
docker-latest docker-latest-logrotate docker-logrotate docker-engine
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf -y install containerd.io
Ubuntu / Debian¶
sudo apt-get remove -y docker docker.io containerd runc
sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update && sudo apt-get install -y containerd.io
Configure for Kubernetes¶
The containerd.io package ships a config that disables the CRI plugin. Replace it with the full default config:
containerd config default | sudo tee /etc/containerd/config.toml
Enable the systemd cgroup driver to match the kubelet:
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
grep -n SystemdCgroup /etc/containerd/config.toml
If the grep returns nothing (the default config layout differs between containerd 1.x and 2.x), add SystemdCgroup = true under the runc options table:
- containerd 1.x:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] - containerd 2.x:
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
sudo systemctl enable --now containerd
sudo systemctl restart containerd
No kubelet flags are needed. kubeadm detects the containerd socket automatically. The old --container-runtime=remote / --container-runtime-endpoint kubelet flags were removed in Kubernetes 1.27.
Debugging tools¶
When the API server is down, kubectl can't tell you anything. These tools talk to containerd directly on the node.
crictl¶
- https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md
Match the crictl minor version to the cluster's Kubernetes version:
VERSION="v1.30.0"
curl -fsSLO https://github.com/kubernetes-sigs/cri-tools/releases/download/${VERSION}/crictl-${VERSION}-linux-amd64.tar.gz
sudo tar zxvf crictl-${VERSION}-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-${VERSION}-linux-amd64.tar.gz
The cri-tools package from the Kubernetes repo installs crictl as well.
Point it at containerd so it stops probing every known socket:
cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
EOF
sudo crictl ps -a # all containers, including exited control-plane pods
sudo crictl pods # pod sandboxes
sudo crictl logs <container-id>
sudo crictl inspect <container-id>
sudo crictl images
sudo crictl rmi --prune # remove unused images
nerdctl¶
- https://github.com/containerd/nerdctl
A Docker-compatible CLI for containerd. Kubernetes containers live in the k8s.io namespace.
VERSION="2.0.3"
curl -fsSLO https://github.com/containerd/nerdctl/releases/download/v${VERSION}/nerdctl-${VERSION}-linux-amd64.tar.gz
sudo tar zxvf nerdctl-${VERSION}-linux-amd64.tar.gz -C /usr/local/bin
rm -f nerdctl-${VERSION}-linux-amd64.tar.gz
sudo nerdctl -n k8s.io ps -a
sudo nerdctl -n k8s.io images
ctr¶
Bundled with containerd. It's low-level and not CRI-aware, but it's always present:
sudo ctr -n k8s.io containers list
sudo ctr -n k8s.io images list