Installing and Configuring containerd as a Kubernetes Container Runtime

This post shows you how to install containerd as the container runtime in a Kubernetes cluster. I will also cover setting the cgroup driver for containerd to systemd, which is the preferred cgroup driver for Kubernetes.

In Kubernetes version 1.20 Docker was deprecated as a container runtime in a Kubernetes cluster and support was removed in 1.22. Kubernetes 1.26 requires that you use a runtime that conforms with the Container Runtime Interface (CRI). containerd is a CRI-compatible container runtime and is one of the supported options you have as a container runtime in this post-Docker/Kubernetes world. To be clear, you use container images created with Docker in containerd. containerd will start and run the container in your Kubernetes cluster. This post was previously published in February 2021. This is an updated version with the latest installation and configuration steps.

Configure required modules

First, load two modules in the current running environment and configure them to load on boot.

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

Configure required sysctl to persist across system reboots

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

Apply sysctl parameters without rebooting to the current running environment

sudo sysctl --system

Install containerd packages

As of this writing, the containerd package included with Ubuntu 22.04LTS is 1.7+, which is appropriate for use in a modern version of Kubernetes. To install containerd on Ubuntu, you can use apt-get.

sudo apt-get install -y containerd.io

If you bootstrapped a Kubernetes cluster with kubeadm init and get the following error… it’s because you’re using a version of containerd that’s less than 1.6. I suggest upgrading your Ubuntu installation to 22+ to get a newer version of containerd.

sudo kubeadm init --kubernetes-version v1.29.1
[init] Using Kubernetes version: v1.29.1
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR CRI]: container runtime is not running: output: time="2023-02-20T02:04:25Z" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

Create a containerd configuration file

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

Set the cgroup driver for runc to systemd

Set the cgroup driver for runc to systemd, which is required for the kubelet.
For more information on this config file, see the containerd configuration docs here and also here.

At the end of this section in /etc/containerd/config.toml

      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
      ...

Change the value for SystemCgroup from false to true.

            SystemdCgroup = true

If you like, you can use sed to swap it out in the file without editing it manually.

sudo sed -i 's/            SystemdCgroup = false/            SystemdCgroup = true/' /etc/containerd/config.toml

Restart containerd with the new configuration

sudo systemctl restart containerd

And that’s it. You can install and configure Kubernetes on top of this container runtime.