Switching Kubernetes Container Runtime from Docker to containerd and Managing It with crictl
This guide explains how to safely switch a Kubernetes cluster's container runtime from Docker to containerd by putting nodes into maintenance mode, updating configuration files, restarting services, verifying the change, and then using crictl for efficient container and pod management, including command comparisons and log handling.
After learning the history and basic usage of containerd, this section demonstrates how to replace Docker with containerd as the container runtime in a Kubernetes cluster.
Node Maintenance : Mark the target node (e.g., node1 ) as unschedulable using kubectl cordon node1 , then drain it with kubectl drain node1 --ignore-daemonsets to evict running Pods.
# 将 node1 标记为 unschedulable
➜ ~ kubectl cordon node1
node/node1 cordoned
➜ ~ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 85d v1.19.11
node1 Ready,SchedulingDisabled
85d v1.19.11
node2 Ready
85d v1.19.11Switching to containerd : Stop kubelet , docker , and containerd , then generate the default containerd config with containerd config default > /etc/containerd/config.toml . Modify the pause image and registry mirrors in the [plugins."io.containerd.grpc.v1.cri"] section.
# Generate default config
➜ ~ containerd config default > /etc/containerd/config.toml
# Set custom pause image
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/k8sxio/pause:3.2"
# Registry mirrors
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://bqr1dr1n.mirror.aliyuncs.com"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
endpoint = ["https://registry.aliyuncs.com/k8sxio"]Update /etc/sysconfig/kubelet to use containerd as the remote runtime:
KUBELET_EXTRA_ARGS="--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"Reload systemd and restart both containerd and kubelet , then verify the node runtime with kubectl get nodes -o wide , confirming containerd://1.4.4 is active on node1 .
# Restart services
➜ ~ systemctl daemon-reload
➜ ~ systemctl restart containerd
➜ ~ systemctl restart kubelet
# Verify
➜ ~ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready master 85d v1.19.11 192.168.31.30
CentOS Linux 7 (Core) 3.10.0-1160.25.1.el7.x86_64 docker://19.3.9
node1 Ready,SchedulingDisabled
85d v1.19.11 192.168.31.95
CentOS Linux 7 (Core) 3.10.0-1160.25.1.el7.x86_64 containerd://1.4.4After confirming, uncordon the node with kubectl uncordon node1 and repeat the process for other nodes.
➜ ~ kubectl uncordon node1
node/node1 uncordonedUsing crictl : Install crictl from the cri-tools releases, configure /etc/crictl.yaml to point to the containerd socket, and use it for pod, container, and image management.
# Install crictl
VERSION="v1.22.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz
crictl version
# Config file
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
debug: false
pull-image-on-create: false
disable-pull-on-run: falseCommon crictl commands include crictl pods , crictl ps , crictl images , crictl exec , crictl logs , and crictl stats . The guide also provides a comparison table of Docker, containerd (via crictl), and ctr commands.
Log Configuration Differences : With Docker, logs are stored under /var/lib/docker/containers and linked via /var/log/pods and /var/log/containers . With containerd, kubelet writes logs directly to /var/log/pods and creates symlinks in /var/log/containers . Log rotation is configured via Docker's log-driver options or kubelet's --container-log-max-files and --container-log-max-size flags.
# Docker log config (json-file)
{"log-driver":"json-file","log-opts":{"max-size":"100m","max-file":10}}
# containerd/kubelet log config
--container-log-max-files=10 --container-log-max-size="100Mi"Finally, the article notes that after switching to containerd, the Docker socket is unavailable, so alternative image build methods that do not rely on docker.sock must be used.
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.