EDIT – December 2021 – Unfortunately the steps documented here no longer work for the newer versions of containerd and runc. I will update once I get the steps working again.
There’s been a lot of conversations happening on twitter over the last couple of days due to the fact that Docker is deprecated in Kubernetes v1.20.
If you want to know more about the reason why I highly recommend checking out this twitter thread.
DISCLAIMER – You’d never do this for a production cluster. For those clusters, you’d simply get rid of the existing nodes and bring new ones in on a rolling basis. This blog is just me mucking about with my Raspberry Pi cluster to see if the update can be done in-place without having to rebuild the nodes (as I really didn’t want to have to do that).
So the first thing to do is drain the node (my node is called k8s-node-1) that is to be updated and cordon it:-
kubectl drain k8s-node-1 --ignore-daemonsets
Then ssh onto the node and stop the kubelet: –
systemctl stop kubelet
Then remove Docker: –
apt-get remove docker.io
Remove old dependencies: –
Now unmask the existing containerd service (containerd is used by Docker so that’s why it’s already there): –
systemctl unmask containerd
Install the dependencies required:-
apt-get install unzip make golang-go libseccomp2 libseccomp-dev btrfs-progs libbtrfs-dev
OK, now we’re following the instructions to install containerd from source detailed here.
I installed from source as I tried to use apt-get to install (as detailed here on the Kubernetes docs) but it wouldn’t work for me. No idea why, didn’t spend to much time looking and tbh, I haven’t installed anything from source before so this was kinda fun (once it worked).
Anyway, doing everything as root, grab the containerd source: –
go get -d github.com/containerd/containerd
Now grab protoc and install: –
wget -c https://github.com/google/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_64.zip sudo unzip protoc-3.11.4-linux-x86_64.zip -d /usr/local
Get the runc code: –
go get -d github.com/opencontainers/runc
Navigate to the downloaded package (check your $GOPATH variable) mine was set to ~/go so cd into it and use make to build and install: –
cd ~/go/src/github.com/opencontainers/runc make make install
Now we’re going to do the same thing with containerd itself: –
cd ~/go/src/github.com/containerd/containerd make make install
Cool. Now copy the containerd.service file to systemd to create the containerd service: –
cp containerd.service /etc/systemd/system/ chmod 644 /etc/systemd/system/containerd.service
And start containerd: –
systemctl daemon-reload systemctl start containerd systemctl enable containerd
Let’s confirm containerd is up and running: –
systemctl status containerd
Awesome! Nearly done, now we need to update the kubelet to use containerd as it defaults to docker. We can do this by running: –
sed -i 's/3.2/3.2 --container-runtime=remote --container-runtime-endpoint=unix:\/\/\/run\/containerd\/containerd.sock/g' /var/lib/kubelet/kubeadm-flags.env
The flags for the kubelet are detailed here
I’m using sed to append the flags to the cluster but if that doesn’t work, edit manually with vim:-
And the following flags need to be added: –
OK, now that’s done we can start the kubelet: –
systemctl start kubelet
And confirm that it’s working:-
systemctl status kubelet
Finally, uncordon the node. So back on the local machine:-
kubectl uncordon k8s-node-1
Run through that for all the worker nodes in the cluster. I did the control node as well following these instructions (didn’t drain/cordon it) and it worked a charm!
kubectl get nodes -o wide
Thanks for reading!