In short
- containerd is part of Docker (the part that pulls and runs images)
- Since Kubernetes is concerned only with pulling and running images and not creating them, it makes little sense to support Docker (which does not implement CRI) as a runtime, when containerd (which implements CRI) is the only thing that is needed
- Even though Kubernetes drops support for Docker as a container runtime, images created with docker will still work in Kubernetes since they follow the OCI-spec.
Docker as an underlying runtime is being deprecated in favor of
runtimes that use the Container Runtime Interface (CRI) created for
Kubernetes. Docker-produced images will continue to work in your
cluster with all runtimes, as they always have.
The longer answer
containerd is a container runtime, which is a piece of software that pulls images, manages networking, storage and starts containers (using runc). There are other container runtimes, such as cri-o that can be used for this purpose also. Those container runtime can handle any image following the OCI-spec, which is a specification of the container image format.
Docker on the other hand is much more than that. It is a multi-competent tool that can both create OCI compliant images as well as running them. When Docker pulls or runs an image it uses containerd.
Kubernetes relies heavily on a plugin architecture where various needs like storage, networking etc can be fullfilled by any implementation that adheres to the interface Kubernetes specifies. For container runtimes, Kubernetes defines the Container Runtime Interface CRI, and any container runtime that implements that interface can be used to pull images and launch containers in Kubernetes.
The extra features, like creating images etc that comes with Docker has little to no value for Kubernetes, which is concerned with pulling images and running containers only. The fact that Docker does not implement CRI makes it unneccessary complex for Kubernetes to support Docker as a runtime, when all it needs is the containerd runtime.
[...]
Docker is cool and useful because it has a lot of UX enhancements
that make it really easy for humans
[...]
As a result of this human-friendly abstraction layer, your Kubernetes
cluster has to use another tool called Dockershim to get at what it
really needs, which is containerd. That’s not great, because it gives
us another thing that has to be maintained and can possibly break.
What’s actually happening here is that Dockershim is being removed
from Kubelet as early as v1.23 release, which removes support for
Docker as a container runtime as a result. You might be thinking to
yourself, but if containerd is included in the Docker stack, why does
Kubernetes need the Dockershim?
Docker isn’t compliant with CRI, the Container Runtime Interface. If
it were, we wouldn’t need the shim, and this wouldn’t be a thing
Quotes are taken from the article Don't Panic: Kubernetes and Docker