Install Mirantis cri-dockerd as Docker Engine shim for Kubernetes

Posted on 249 views

Mirantis cri-dockerd is an adapter created to provide a shim for Docker Engine to let you control Docker Engine via the Kubernetes Container Runtime Interface. I know most of you by now are aware that Kubernetes has deprecated Docker as a container runtime after v1.20. This was as a result of Kubernetes Development decision to deprecate Docker as an underlying runtime in favor of runtimes that use the Container Runtime Interface (CRI) created for Kubernetes. However, Docker-produced images will continue to work in your Kubernetes cluster with all runtimes, as they always have. For any container engine that is CRI compliant, it can run in Kubernetes with no extra effort.

But it’s not the end of the world, and you don’t need to panic. What you just need is to change your container runtime from Docker to another supported container runtime. Mirantis and Docker came into rescue by agreeing to partner in the maintenance of the shim code standalone. This code is maintained outside Kubernetes, as a conformant CRI interface for the Docker Engine API. The cri-dockerd makes Docker Engine to be CRI compliant and you can continue to use it in your Kubernetes by just switching from the built in dockershim to the external one.

Setup cri-dockerd as Docker Engine shim for Kubernetes

We will start with the installation of cri-dockerd and demonstrate how one can use it in Kubernetes. A “shim” is used to translate between the Docker Engine component and the relevant Kubernetes interface, in this case Container Runtime Interface (CRI). If you need a CRI compliant Engine, you can easily switch to Containerd and eliminate the need for cri-dockerd interface.

It is worth mention that all the images you create using docker build are compliant with the underlying standard CRI use. The container images are still going to work well with Kubernetes. Our focus is on replacing deprecated dockershim so that we can make Docker Engine CRI compliant.

Install cri-dockerd on Linux

You can install cri-dockerd on Linux from source using Go, or by downloading ready binaries. We shall consider the two options.

A pre-requisite for this installation is Docker-Engine. You can reference our guide below to install the latest Docker Engine runtime on your Linux machine:

Ensure Docker service is running before you proceed:

$ systemctl status docker
 docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-04-15 10:34:54 UTC; 14s ago
 Main PID: 26072 (dockerd)
    Tasks: 9
   Memory: 29.1M
   CGroup: /system.slice/docker.service
           └─26072 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Install cri-dockerd using ready binary

Install wget and curl command line tools.

### Debian based systems ###
sudo apt update
sudo apt install git wget curl

### RHEL based systems ###
sudo yum -y install git wget curl

### SUSE based Linux ###
sudo zypper install git wget curl

### Arch based Linux ###
sudo pacman -Syy
sudo pacman -S git wget curl

Once the tools are installed, use them to download the latest binary package of cri-dockerd. But first, let’s get the latest release version:

VER=$(curl -s|grep tag_name | cut -d '"' -f 4|sed 's/v//g')
echo $VER

We can then download the archive file from Github cri-dockerd releases page.

### For Intel 64-bit CPU ###
tar xvf cri-dockerd-$VER.amd64.tgz

### For ARM 64-bit CPU ###

Move cri-dockerd binary package to /usr/local/bin directory

sudo mv cri-dockerd/cri-dockerd /usr/local/bin/

Validate successful installation by running the commands below:

$ cri-dockerd --version
cri-dockerd 0.2.5 (10797dc)

Configure systemd units for cri-dockerd:

sudo mv cri-docker.socket cri-docker.service /etc/systemd/system/
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

Start and enable the services

sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

Confirm the service is now running:

$ systemctl status cri-docker.socket
 cri-docker.socket - CRI Docker Socket for the API
     Loaded: loaded (/etc/systemd/system/cri-docker.socket; enabled; vendor preset: enabled)
     Active: active (listening) since Fri 2022-04-15 08:48:59 UTC; 25s ago
   Triggers:  cri-docker.service
     Listen: /run/cri-dockerd.sock (Stream)
      Tasks: 0 (limit: 4677)
     Memory: 60.0K
     CGroup: /system.slice/cri-docker.socket

Apr 15 08:48:59 ubuntu-20-04-02 systemd[1]: Starting CRI Docker Socket for the API.
Apr 15 08:48:59 ubuntu-20-04-02 systemd[1]: Listening on CRI Docker Socket for the API.

Install cri-dockerd from source

Install Golang on your system

chmod +x ./installer_linux
source ~/.bash_profile

Confirm installation by checking version of Go.

$ go version
go version go1.18.1 linux/amd64

Clone the project code from Github repository

git clone

Run the commands below to build this code (in a POSIX environment):

cd cri-dockerd
mkdir bin
cd src && go get && go build -o ../bin/cri-dockerd
cd ..

Finally install cri-dockerd on a Linux system. This assumes your system uses systemd, and Docker Engine is installed.

sudo mkdir -p /usr/local/bin
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
sudo cp -a packaging/systemd/* /etc/systemd/system

Start and enable the cri-docker service

sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

Check service status:

$ systemctl status cri-docker.socket
 cri-docker.socket - CRI Docker Socket for the API
   Loaded: loaded (/etc/systemd/system/cri-docker.socket; enabled; vendor preset: disabled)
   Active: active (listening) since Fri 2022-04-15 10:38:54 UTC; 15s ago
   Listen: /run/cri-dockerd.sock (Stream)
    Tasks: 0 (limit: 49496)
   Memory: 4.0K
   CGroup: /system.slice/cri-docker.socket

From the output we can find out the path to the CRI socket.

Listen: /run/cri-dockerd.sock

For cri-dockerd, the CRI socket is /run/cri-dockerd.sock by default.

Configure the kubelet to use cri-dockerd

You should have kubelet installed before you can configure it to use cri-dockerd. The steps shared apply to clusters set up using the kubeadm.

Using cri-dockerd on new Kubernetes cluster

Ensure Docker Engine is installed and running:

systemctl status docker

You should have installed kubeadm and kubelet components as well. With the components installed we can test pulling container images for Kubernetes.

$ sudo kubeadm config images pull --cri-socket /run/cri-dockerd.sock 
[config/images] Pulled
[config/images] Pulled
[config/images] Pulled
[config/images] Pulled
[config/images] Pulled
[config/images] Pulled
[config/images] Pulled

Bootstrap Control plane (This is for single node controller)

sudo kubeadm init \
  --pod-network-cidr= \
  --cri-socket /run/cri-dockerd.sock

The initialization should be successful.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Container runtime endpoint is configured in /var/lib/kubelet/kubeadm-flags.env.

$ sudo cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--container-runtime=remote --container-runtime-endpoint=/run/cri-dockerd.sock"

Migrating existing Nodes from from dockershim to cri-dockerd

Cordon the node. Don’t forget to replace  with the name of the node.

kubectl cordon 

Drain the node to safely evict running Pods:

kubectl drain  --ignore-daemonsets

Open /var/lib/kubelet/kubeadm-flags.env on each affected node.

sudo vim /var/lib/kubelet/kubeadm-flags.env

Modify the --container-runtime-endpoint flag to unix:///var/run/cri-dockerd.sock.

The kubeadm tool stores the node’s socket as an annotation on the Node object in the control plane. To modify this socket for each affected node:

Edit the YAML representation of the Node object:

KUBECONFIG=/path/to/admin.conf kubectl edit no 

Replace the following:

  • /path/to/admin.conf: the path to the kubectl configuration file, admin.conf.
  • : the name of the node you want to modify.

Change from /var/run/dockershim.sock to unix:///var/run/cri-dockerd.sock.

Save the changes. The Node object is updated on save and restart kubelet

sudo systemctl restart kubelet

Uncordon the node to let Pods schedule on it:

kubectl uncordon 



Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.