containerd,docker-shim,runc,cri-docker
OCI
Open Container Initiative,开放容器标准
在 Linux 基金会的支持下成立,致力于围绕容器格式和运行时创建开放的行业标准
CRI
容器运行时接口,Container Runtime Interface
是由K8S发布制定的,统一了容器运行时接口的一种标准协议,
容器运行时接口(CRI)是 kubelet 和容器运行时之间通信的主要协议。
K8S最开始只支持docker作为容器运行时。之后为了和docker进行博弈,k8s搞出了cri标准接口,凡是支持CRI的容器运行时,都可以作为K8S的底层容器运行时。

Docker
关于docker是啥不需要过多解释了。
在docker称为容器化的事实标准之后,docker项目本身逐渐成为了一个庞然大物。为了能够降低项目维护的成本,以及其他一些原因。
docker 开始自行拆分自己项目中的代码并形成一个个新的开源项目。
2015 年 6 月 22 日 ,在 OCI 项目启动后,Docker 公司将 Libcontainer 捐出,并改名为 RunC 项目
然后以 RunC 为依据,大家共同制定一套容器和镜像的标准和规范,这套标准和规范,就是 OCI
然后 2016 年,docker 开源并将 containerd 捐赠给了 CNCF,
containerd 几乎囊括了单机运行一个容器运行时所需要的一切:执行,分发,监控,网络,构建,日志等
docker不支持K8S的CRI标准
runC
上面说到的是docker公司将 libcontainer 的实现移动到 runC 并捐赠给了 OCI。
这样,容器社区就有了第一个 OCI Runtime 的参考实现。所以runC只是一个OCI标准的运行时的参考实现。
runC在最底层,我们用 Docker 或者 containerd 去启动容器,最后都会调用 runC 在 Linux 中把容器启动起来 ,它调用namespace、cgroup等系统接口创建容器。
containerd
containerd: 是符合OCI标准的容器运行时。从docker项目中拆分出来的。
目前主流的k8s底层运行时
containerd向上承接CRI接口,向下去调用runC
libcontainer是containerd的前身,现在不提了
所以从上往下的关系是
docker - containerd - runc - OCI格式的容器
dockershim
shim的意思是垫片。相当于一个转换层。
dockershim存在的原因在于上面提到的cri标准。k8s直接调用的是cri标准的接口。
但是Docker是Kubernetes使用的第一个容器运行时。从docker向cri标准过度的过程中,需要一个权宜之计,以实现与其他各种容器运行时的可移植性。这个权宜之计就是 dockershim。

之后,从 containerd 1.0 开始,为了能够减少一层调用的开销,containerd 开发了一个新的 daemon,叫做 CRI-Containerd,直接与 containerd 通信,从而取代了 dockershim:

但是这仍然多了一个独立的 daemon,从 containerd 1.1 开始,社区选择在 containerd 中直接内建 CRI plugin,通过方法调用来进行交互,从而减少一层 gRPC 的开销,最终的容器启动流程如下:

Kubernetes 1.24 版本删除了内置的 dockershim
cri-dockerd
如上所属,docker不支持K8S的CRI标准。随着docker-shim的下线。从kubernetes 1.24开始,如果想继续使用docker的话,可以在kubelet和docker之间加上一个中间层cri-docker。
虽然 Kubernetes 已经不再包含 dockershim,但 Docker 公司却把这部分代码接管了过来,另建了一个叫 cri-dockerd(https://github.com/mirantis/cri-dockerd)的项目,作用也是一样的
其他的容器运行时
和containerd对标的有:cri-o, kata,mcr等
cri-o也是符合cri标准的,他也是redhat的openshift选中的做生产环境的运行时