Lesson ย inย  BETA: Kubernetes the (Very) Hard Way

containerd

Release date: TBA

What is containerd?

containerd is an industry-standard container runtime that provides the fundamental tools for running containers.

Originally developed by Docker, containerd is now maintained by the CNCF, and has become one of the most widely adopted container runtimes in the cloud-native ecosystem.

containerd provides several essential services to Kubernetes:

  1. Container Lifecycle Management: Creating, starting, stopping, and deleting containers
  2. Image Management: Pulling, storing, and managing container images from registries
  3. Storage Management: Handling container filesystems and volume mounts
  4. Network Management: Coordinating with CNI plugins for container networking
  5. Runtime Management: Interfacing with low-level runtimes
containerd in a Kubernetes cluster

containerd in a Kubernetes cluster

Important

๐Ÿ› Reporting issues

If you encounter any issues throughout the course, please report them here.

Installing containerd

Follow these steps to install containerd:

Set the version to install:

CONTAINERD_VERSION=2.1.4
Latest version
CONTAINERD_VERSION=$(curl -s https://api.github.com/repos/containerd/containerd/releases/latest | jq -r '.tag_name | sub("^v"; "")')

Download and install containerd from GitHub:

curl -fsSLO https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION?}/containerd-${CONTAINERD_VERSION?}-linux-amd64.tar.gz
sudo tar xzvofC containerd-${CONTAINERD_VERSION?}-linux-amd64.tar.gz /usr/local

Download the systemd unit file to run containerd as a systemd service:

sudo wget -P /etc/systemd/system https://raw.githubusercontent.com/containerd/containerd/main/containerd.service

Start the containerd service:

sudo systemctl daemon-reload
sudo systemctl enable --now containerd
Note

If you run into any issues, check out the Tips & Tricks at the beginning of the course.

Congratulations! You have successfully installed containerd. ๐ŸŽ‰

Interacting with containerd

containerd includes a CLI tool called ctr for basic container operations.

Note

๐Ÿ’ก Think of ctr as similar to the Docker CLI, but designed for lower-level container operations.

Unlike higher-level tools like Docker CLI, ctr requires you to manually pull an image before running it:

sudo ctr images pull ghcr.io/sagikazarmark/docker-hello-world:latest

With the image pulled, you can run the container:

sudo ctr run --rm ghcr.io/sagikazarmark/docker-hello-world:latest hello

This command will fail because no OCI runtime is installed yet:

ctr: failed to create shim task: OCI runtime create failed:
unable to retrieve OCI runtime error
(open /run/containerd/io.containerd.runtime.v2.task/default/hello/log.json: no such file or directory):
exec: "runc": executable file not found in $PATH

The next section covers installing an OCI runtime to resolve this issue.

Installing an OCI Runtime

containerd is a high-level container runtime that provides a wide range of container management services, but delegates certain tasks to specialized components. One critical task is actually running the container process, which containerd delegates to a low-level OCI runtime.

๐Ÿ›๏ธ History

Historically, container management used a highly integrated, monolithic architecture (think Docker Engine).

As the ecosystem matured and standardization efforts advanced, the need for a more modular and flexible approach became clear.

This evolution led to the development of various high-level container runtimes and the establishment of the Open Container Initiative (OCI).

containerd and OCI

containerd and OCI

What is containerd-shim?

containerd-shim is a lightweight process that acts as a bridge between containerd and OCI runtimes.

It provides a stable interface for containerd to interact with the runtime, keeps containers running even if containerd crashes, handles container I/O, and reaps processes when they exit.

The reference OCI runtime implementation is runc, which serves as the default runtime for containerd.

Note

๐Ÿ’ก Other OCI runtimes exist, such as crun (written in C for better performance) and gVisor (which provides additional security isolation).

However, runc remains the most widely used and well-tested option.

Follow these steps to install runc:

Set the version to install:

RUNC_VERSION=v1.3.0
Latest version
RUNC_VERSION=$(curl -s https://api.github.com/repos/opencontainers/runc/releases/latest | jq -r .tag_name)

Download and install runc from GitHub:

curl -fsSLO https://github.com/opencontainers/runc/releases/download/${RUNC_VERSION?}/runc.amd64

sudo install -m 755 runc.amd64 /usr/local/sbin/runc

Create a configuration file that tells containerd to use the systemd cgroup driver:

/etc/containerd/config.toml
version = 3

[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc.options]
SystemdCgroup = true
Hint
sudo mkdir -p /etc/containerd
sudoedit /etc/containerd/config.toml
Note

๐Ÿ’ก When using systemd as the init system, it's recommended to use the systemd cgroup driver for consistent cgroup management.

Restart the containerd service to apply the configuration changes:

sudo systemctl restart containerd

With runc installed and configured, the container now runs successfully:

sudo ctr run --rm ghcr.io/sagikazarmark/docker-hello-world:latest hello

Installing nerdctl

Although ctr is an excellent tool for low-level interaction with containerd, it isn't the most user-friendly tool, especially for users familiar with the Docker CLI.

Fortunately, there's an alternative tool called nerdctl (contaiNERD CTL) that provides a Docker CLI-like interface for interacting with containerd.

Follow these steps to install nerdctl:

Set the version to install:

NERDCTL_VERSION=2.1.3
Latest version
NERDCTL_VERSION=$(curl -s https://api.github.com/repos/containerd/nerdctl/releases/latest | jq -r '.tag_name | sub("^v"; "")')

Download and install nerdctl from GitHub:

curl -fsSLO https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION?}/nerdctl-${NERDCTL_VERSION?}-linux-amd64.tar.gz

tar xzvof nerdctl-${NERDCTL_VERSION?}-linux-amd64.tar.gz

sudo install -m 755 nerdctl /usr/local/bin

nerdctl completion bash | sudo tee /etc/bash_completion.d/nerdctl

Unlike ctr, nerdctl automatically handles image pulling and network setup.

Verify that by running a container:

sudo nerdctl run --rm ghcr.io/stefanprodan/podinfo:latest /home/app/podinfo --version

This command will fail because CNI plugins are not installed yet:

FATA[0000] failed to create shim task: OCI runtime create failed:
runc create failed: unable to start container process:
error during container init: error running createRuntime hook #0:
exit status 1, stdout: , stderr: time="2025-07-17T12:39:15Z" level=warning msg="Container failed starting. Removing allocated network configuration."

time="2025-07-17T12:39:15Z" level=fatal msg="failed to call cni.Setup: plugin type=\"bridge\" failed (add): failed to find plugin \"bridge\" in path [/opt/cni/bin]"

While ctr doesn't automatically create a network for containers, nerdctl attempts to create a bridge network by default. Without CNI plugins installed, this network creation fails.

Work around this by telling nerdctl to use the host network instead:

sudo nerdctl run --net host --rm ghcr.io/stefanprodan/podinfo:latest /home/app/podinfo --version
Important

This is only a workaround for educational purposes.

In a production environment, you should install CNI plugins to manage network configurations.

The next section covers installing CNI plugins to resolve this issue.

Installing CNI Plugins

Just as containerd delegates container process execution to OCI runtimes, it delegates network configuration to specialized components through the Container Network Interface (CNI).

CNI is a specification and set of libraries for configuring network interfaces in Linux containers. It provides a standardized way for container runtimes to set up container networking, including creating network namespaces, configuring IP addresses, and establishing connectivity between containers and the host system.

containerd, OCI and CNI

containerd, OCI and CNI

Various CNI plugins are available, many of which can be found in the official CNI plugins repository.

CNI usage in Kubernetes will be covered later in this course.

For now, understand that nerdctl uses the bridge plugin by default to configure the network namespace for each container.

Follow these steps to install CNI plugins:

Set the version to install:

CNI_PLUGINS_VERSION=v1.7.1
Latest version
CNI_PLUGINS_VERSION=$(curl -s https://api.github.com/repos/containernetworking/plugins/releases/latest | jq -r .tag_name)

Download and install the CNI plugins from GitHub:

curl -fsSLO https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION?}/cni-plugins-linux-amd64-${CNI_PLUGINS_VERSION?}.tgz

sudo mkdir -p /opt/cni/bin

sudo tar xzvofC cni-plugins-linux-amd64-${CNI_PLUGINS_VERSION?}.tgz /opt/cni/bin
Note

๐Ÿ’ก CNI plugins are installed in /opt/cni/bin by convention.

Container runtimes, Kubernetes network addons look for them in this directory by default.

With CNI plugins installed, containerd is now fully functional.

Run the container again using nerdctl:

sudo nerdctl run -d --name podinfo ghcr.io/stefanprodan/podinfo:latest

Verify that the container is running:

sudo nerdctl ps

Verify that the podinfo application is working correctly:

podinfoIp=$(sudo nerdctl inspect --format '{{ .NetworkSettings.IPAddress }}' podinfo)
curl -f http://${podinfoIp}:9898

Summary

In this lesson, you learned about containerd, the high-level container runtime that serves as the foundation for container management on Kubernetes worker nodes.

Key takeaways:

  • Modular architecture: containerd orchestrates container operations while delegating specific tasks to specialized components: OCI runtimes (like runc) handle process execution and CNI plugins manage networking
  • Essential services: Provides container lifecycle management, image management, storage coordination, and network interface setup for Kubernetes pods
  • Management tools: Use ctr for low-level debugging and nerdctl for Docker-like commands when working directly with containerd

With containerd now running and fully configured with runc and CNI plugins, you're ready to set up kubeletโ€”the Kubernetes node agent that will use containerd to manage pod lifecycles.

Related Content

Iximiuz Labs offers a wide range of resources related to containers.

Here are some highlights to explore further.

๐Ÿงช Playgrounds

๐Ÿ“– Tutorials

๐Ÿ“š Courses

๐Ÿ› ๏ธ Skills Paths

Note

๐Ÿ’ก Be sure to check out Ivan's blog for extensive examples and explanations of containerization concepts.

References

Note

๐Ÿ’ก To dive deeper into the concepts covered in this lesson, check out the resources below.

Previous lesson
Tips & Tricks
Next lesson
kubelet