Kubernetes always needed a container runtime in each node in the cluster so that Pods can run there. Docker revolutionized the containers market and brought them into common usage. Docker Engine was the first and initially the only container runtime supported by Kubernetes. But in long term, the intention was to support various different container runtimes.
As soon as Docker containers became popular in the market, people started to use containers as the standard unit of software delivery. Several companies started using containers to package and deploy their software more and more. Docker’s container runtime did not meet all technical and business needs that engineering teams could have. That is when the community started developing new runtimes with different implementations and capabilities. As several tools were emerging abiding different standards, it started to pollute the container market. That is when the community started the Open Container Initiative (OCI). OCI defines industry standards around container image formats and runtimes. It is to make sure that all container runtimes could run images produced by any build tool.
Let’s dig a little bit deeper to understand how Kubernetes works with various runtimes. If we closely look into Kubernetes Cluster architecture we will find that kubelet is the actual primary agent running on every node in the cluster. It listens to every instruction from API server and depending on the type of container runtime takes an action.
Kubernetes originally only supported Docker as a container runtime engine. But now Kubernetes supports several different runtimes like:
Container Runtime Interface (CRI)
Kubernetes has to be agnostic of any runtime used underneath it. So to decouple Kubernetes from specific runtimes, Container Runtime Interface (CRI) was introduced. In Kubernetes 1.7, the internal Docker integration in Kubernetes was replaced with a CRI-based integration. This actually opened the door to support various runtime by Kubernetes.
The CRI is a collection of a gRPC API, specifications/requirements, and libraries for container runtimes to integrate with a kubelet on a node.
The kubelet doesn’t interface directly with any runtimes. Instead, it talks to the CRI-compliant container runtime. This way CRI solves supporting various runtime alternatives with no change in Kubelet. To plug a new container runtime into Kubernetes, all that is needed is a small piece of code called a shim that translates requests made by Kubernetes into requests understandable by the runtime.
Then let’s understand what is a Container Runtime
Container runtime responsibilities are to :
- Provide core primitives to manage containers on a host
- Manage container lifecycle starting from execution to supervision
- Network Interfaces and management
- Manage Images
- Local storage handling
Let’s look into various container runtimes and compare it with Docker
To plug a new container runtime into Kubernetes, we need to have a small piece of code called a shim that could translate requests made by Kubernetes into requests understandable by the runtime. So every runtime would need a custom shim, that’s tough!!
So the runtime is actually having two parts:
- High-level runtime implements CRI gRPC service and takes care of all prerequisite to successfully operate OCI runtimes.
- OCI runtime works as low-level runtime. The high-level runtime provides inputs to OCI runtime as per OCI Specs.
Dockershim is the Docker CRI embedded in Kubelet so that Kubelet could communicate with Docker. Dockershim is the one that talks to docker and manages pods. Its was the default CRI implementation and that is the reason was present in almost all Kubernetes deployments.
We do have a generic shim which supports all container runtimes, this shim is CRI-O (open-source project created by the community). CRI-O supports any OCI compatible runtime.
CRI-O is a lightweight alternative to Docker as the runtime for kubernetes. It allows Kubernetes to use any OCI-compliant runtime as the container runtime for running pods.
If we closing looking into the architectural diagram above we will notice that :
- CRI-O reduces the one extra hop from docker
- CRI-O works with all OCI runtimes too
- Uses CNI for networking
Containerd is another compliant container runtime it was initiated by Docker Inc. and was donated to CNCF in March 2017. Containerd is lightweight and provides the minimum set of functionality to execute containers and manages images on a node.
- containerd, with revised scope, eliminates the extra hop required by docker
- Redesigned storage drivers for simplicity and better performance
- Uses CNI for networking
- Works with all OCI runtimes
So now coming to the various rumours of dockershim’s deprication. Please do not panic it’s not going to affect any of our CKA or CKAD certifications.
But yes if we are Kubernetes admins we should start thinking of adopting any new runtime such as containerd and CRI-O. But as Docker is just not a container runtime, we can still continue to use docker to build images and use its container registry to push-pull images. Docker-produced images will continue to work in our clusters just as they always have.