DEV Community

AMIT CHATURVEDI
AMIT CHATURVEDI

Posted on

Migrating from Docker To Containerd

In the dynamic world of container orchestration, choosing the right container runtime is crucial for optimizing performance and resource utilization. If you've been using Docker and are contemplating a switch, this blog post will guide you through the process of migrating to Containerd. Follow this step-by-step guide to ensure a smooth migration and unlock the benefits that Containerd has to offer.

Image description

Image description

Understanding the Basics
Containerd Overview:
Containerd serves as an essential building block for higher-level container platforms, including Docker and Kubernetes. Initially developed by Docker, Inc., it was later contributed to the community and is now a standalone project within the Cloud Native Computing Foundation (CNCF). Containerd's design emphasizes simplicity, portability, and extensibility, making it a versatile solution for various containerization needs.

Key Features

Container Lifecycle Management:
Containerd excels in managing the entire lifecycle of containers, handling tasks such as image transfer, container execution, and storage management. It abstracts away the complexities of these operations, providing a standardized interface for container runtimes.

Image Distribution:
Containerd supports the distribution and management of container images. It interfaces with container registries to efficiently pull, push, and store container images, ensuring seamless deployment across diverse environments.

Pluggable Architecture:
With a modular and pluggable architecture, Containerd allows users to customize and extend its functionality. This flexibility enables integrations with various container orchestration systems and supports a diverse range of use cases.

Runtime Interface:
Containerd adheres to the container runtime interface (CRI), making it compatible with container orchestration platforms like Kubernetes. Its compliance with industry standards enhances interoperability and ease of integration into existing container ecosystems.

Architecture:
Containerd's architecture is designed with a focus on simplicity and modularity. The key components include:

Shim Layer:
The shim layer serves as the intermediary between the container runtime and the container process. It helps in handling container execution, managing process lifecycle, and interfacing with the underlying operating system.

Containerd Daemon:
The core daemon manages essential container operations such as image handling, storage management, and container lifecycle. It exposes a gRPC API that enables communication with client applications and container runtimes.

gRPC API:
Containerd's gRPC API provides a standardized and efficient communication channel for interacting with the daemon. It allows seamless integration with client tools, container orchestrators, and other components in the container ecosystem.

Migrate Kubernetes from Docker to Containerd

Image description

Kubernetes decided to deprecate Docker as container runtime after v1.20

Explanation of why Kubernetes decided to deprecate Docker can be found here: Reason Of Deprecate Docker

In this post, we are going to migrate Kubernetes cluster from Docker to Containerd. These changes will apply to all nodes in the cluster. I recommend starting migrating from worker nodes.

Prepare node
First of all, scheduling must be disabled and all unnecessary workloads, except daemon sets, must be evicted.

- Start by cordoning the node

$ kubectl cordon k8s-worker-3
node/k8s-worker-3 cordoned
Enter fullscreen mode Exit fullscreen mode

- Drain node

$ kubectl drain k8s-worker-3 --ignore-daemonsets --delete-emptydir-data
node/k8s-worker-3 already cordoned
node/k8s-worker-3 evicted
Enter fullscreen mode Exit fullscreen mode

- Stop Kubelet and docker

$ systemctl stop kubelet
$ systemctl stop docker
Enter fullscreen mode Exit fullscreen mode

- Switch to containerd

Node is ready to be migrated to containerd. Start by removing docker as it will not be needed anymore

$ apt purge docker-ce docker-ce-cli
Enter fullscreen mode Exit fullscreen mode

Ensure containerd is installed

$ ctr -n moby container list
Enter fullscreen mode Exit fullscreen mode

Ensure that config file for containerd in /etc/containerd/config.toml is present. You can generate it with

$ mkdir -p /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml
Enter fullscreen mode Exit fullscreen mode

If you are using the systemd as a cgroup driver, you must configure it in containerd config. In /etc/containerd/config.toml Add

<...>
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  <...>
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true # <--- This line
<...>
Enter fullscreen mode Exit fullscreen mode

Restart containerd

$ systemctl restart containerd
$ systemctl status containerd
Enter fullscreen mode Exit fullscreen mode

Image description

Edit /var/lib/kubelet/kubeadm-flags.env file by adding container runtime flags
--container-runtime=remote
--container-runtime-endpoint=unix:///run/containerd/containerd.sock

kubeadm-flags.env file should now look something like this

$ cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
Enter fullscreen mode Exit fullscreen mode

Start Kubelet

$ systemctl start kubelet
$ systemctl status kubelet
Enter fullscreen mode Exit fullscreen mode

Image descriptionImage description

Check cluster status

$ kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

Uncordon the node if everything looks good

$ kubectl uncordon k8s-worker-3
Enter fullscreen mode Exit fullscreen mode

Repeat the procedure for all nodes (one by one) and in last master node.

Post-migration
Let's free up some space by removing docker-related folders. They will not be needed anymore

$ rm -r /etc/docker
$ rm -r /var/lib/docker
$ rm -r /var/lib/dockershim
Enter fullscreen mode Exit fullscreen mode

If you are using kubeadm to manage your cluster initialization, joins, and updates, you might want to re-annotate nodes, so kubeadm will not get confused on your next update whether you are using docker or containterd as a runtime

$ kubectl annotate node k8s-worker-3 --overwrite kubeadm.alpha.kubernetes.io/cri-socket=unix:///run/containerd/containerd.sock
Enter fullscreen mode Exit fullscreen mode

Note that removals and annotate must be executed on all nodes after the whole cluster will be migrated to containerd and ensured that the migration was successful.

Top comments (0)