Don't panic, Docker containers and images are still alive. It's not that it will change everything.
Also worth reading:
Read this carefully and start considering Docker alternatives
Yes, it is true. Docker is now deprecated in Kubernetes.
Docker support in the kubelet is now deprecated and will be removed in a future release. The kubelet uses a module called "dockershim" which implements CRI support for Docker and it has seen maintenance issues in the Kubernetes community. We encourage you to evaluate moving to a container runtime that is a full-fledged implementation of CRI (v1alpha1 or v1 compliant) as they become available.
In short, what it means here is that Docker does not support Kubernetes Runtime API called CRI(Container Runtime Interface) and Kubernetes people have been using a bridge service called "dockershim". It converts Docker API and CRI, but it will no longer be provided from Kubernetes side within a few minor releases.
Docker in local is a very powerful tool to create dev environment for sure, but in order to understand what's causing this, you need to understand what Docker does in the current Kubernetes architecture.
Kubernetes is an infra orchestration tool that groups up many different compute resources such as virtual/physical machines and make it look like a huge compute resource for your application to run and share with others. In this architecture, Docker, or a container runtime, is used only to run those applications in an actual host by being scheduled by Kubernetes control plane.
Look at the architecture diagram. You can see that each Kubernetes node talks to the control plane.
kubelet on each node fetch metadata and it execs CRI to run create/delete containers on the node.
Again, Kubernetes only talks in CRI and talking to Docker requires a bridge service. So that's reason 1.
To explain the next reason, we have to see the Docker architecture a bit. Here's the diagram.
So yeah, Kubernetes actually needs inside of the red area. Docker Network and Volume are not used in Kubernetes.
Having more features while you never use, itself can be a security risk. The less features you have, the smaller the attack surface becomes.
So this is where you start considering alternatives. It's called CRI runtimes.
There are two major CRI runtime implementations.
If you just want to migrate from Docker, this is the best option as containerd is actually used inside of Docker to do all the "runtime" jobs as you can see in the diagram above. They provides CRI and it's 100% what Docker provides, too.
containerd is 100% open source so you can see docs on GitHub and even contribute to it too.
CRI-O is a CRI runtime mainly developed by Red Hat folks. In fact, this runtime is used in Red Hat OpenShift now. Yes, they do not depend on Docker anymore.
Interestingly, RHEL 7 does not officially support Docker either. Instead, they provide Podman, Buildah and CRI-O for container environment.
CRI-O's strength in my opinion is its minimalism because it was created to be a "CRI" runtime. While containerd started as a part of Docker trying to be more open source, they are pure CRI runtime so CRI-O does not have anything that CRI does not require.
It can be more challenging to migrate from Docker to CRI-O because of that, it still provides what you needs to run applications on Kubernetes.
When we talk about Container Runtimes, we need to be careful which type of runtime you're talking about. We do have two types of runtimes; CRI runtimes and OCI runtimes.
As I described, CRI is an API that Kubernetes provides to talk to a container runtime in order to create/delete containerised applications.
They talk in gRPC via IPC as kubelet and the runtime runs on the same host, and a CRI runtime has responsibility for getting request from kubelet and execute OCI container runtime to run a container. Wait, what? Maybe I should explain with a diagram for this one.
So what a CRI runtime does is the following
- Get the gRPC request from kubelet
- Create OCI json config following the spec
OCI runtimes are responsible for spawning a container using Linux kernel system calls such as cgroups and namespace. You might have heard about
gVisor. This is what they are.
runC spawns containers after CRI executes the binary by calling Linux system calls. That indicates runC relies on the kernel that is running on your Linux machine.
It also implies that if you ever discover runC's vulnerability that makes you take the root privilege of your host, a containerized application can also do so. A bad hacker could take your host machine's root and boom! Things surely will get bad. This is one of the reasons why you should keep updating your Docker(or any other container runtimes) too, not just your containerized application.
gVisor is an OCI runtime that were originally created by Google folks. It actually runs on their infrastructure to run their Cloud services such as Google Cloud Run, Google App Engine(2nd gen), and Google Cloud Functions(and even more!)
What's interesting here is that gVisor has a "guest kernel" layer which means a containerised applications cannot directly touch to the host kernel layer. Even if they think they do, they only touch the gVisor's guest kernel.
gVisor's security model is actually very interesting and worth reading the official doc.
Notable differences from runC is as follows.
- Performance is worse
- Linux kernel layer is not 100% compatible
- Not supported by default
1. Docker is surely deprecated but only in Kubernetes, so if you're a K8s admin, you should start thinking to adopt a CRI runtime such as containerd and CRI-O.
a. containerd is Docker compatible where the core components are the same.
b. CRI-O can be a strong option where you want more minimal functionality for Kubernetes
Depending on your workload, runC might not be always the best option to use!