容器运行时目前有

  • containerd  脱胎于docker当中开源libcontainerd
  • CRI-O      红帽依照CRI开发,用于openshift,
  • Docker    docker全栈,除了底层的containerd,上层还有好多高级抽象层提供dockerd然后供docker命令调用。k8s之所以1.20以后版本弃用docker的原因在于调用docker这个容器运行时的时候为了对接docker多出来的高级抽象层,还单独写了一个Dockershim来对接docker对人类友好对机器没必要的高级抽象层。所以docker全栈用来跑K8S用不到的部分很多,而且接口反而还多一层,导致K8s要抛弃他(狗日大厂就是牛逼啊,硬生生的做容器编排做大了以后把docker的市场慢慢全部蚕食掉,docker当时生态没利用好啊)
  • podman (RHEL8/Centos8默认已替换了docker)

其中这里面k8s其实是通过API接口来调用这些运行时的,CRI-O,containedrd提供CRI接口,可以直接调用,而且只实现CRI要求的功能(镜像操作,容器运行操作,存储),别的网络以及其他上层包装好的功能对K8S来说其实也不需要。

下面的这些白嫖的图应该比较清晰看出k8s调用docker的中间多出来的多余部分。有洁癖的人可以换CRI-O或者containerd了。docker还是单独用吧。不过小规模真没必要上k8s,swarm,docker_compose完全够用了。k8s维护够一般IT人员喝一壶了。

名次解释:

OCI     开放容器标准 open container initiative,OCI 中定义了两个标准:容器运行时标准 和 容器镜像标准,实现了这一标准的主流是:runc(也即我们日常说的 Docker)、Kata-Container。

主要作用,制作容器:

  • 1、容器镜像制作内容,即 ImageSpec

  • 2、容器需要接收哪些指令,即 runtimeSpec

CRI    容器运行环境接口  https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.mdicon-default.png?t=LA92https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md

 白嫖2张知乎的图,画的非常清晰。

 

k8s 1.20版本为什么不推荐docker? - 知乎icon-default.png?t=LA92https://www.zhihu.com/question/433124795/answer/1616290710

CSDN上白嫖的参考地址

Kubernetes 1.20 版本开始将弃用 Docker,是时候拥抱 Containerd 和 Podman 了!_easylife206的专栏-CSDN博客icon-default.png?t=LA92https://blog.csdn.net/easylife206/article/details/110602496

Kubelete 创建容器步骤 [1]

  • 1、Kubelet 通过 CRI 接口(gRPC)调用 dockershim,请求创建一个容器。CRI 即容器运行时接口,这一步中,Kubelet 可以视作一个简单的 CRI Client,而 dockershim 就是接收请求的 Server。目前 dockershim 的代码其实是内嵌在 Kubelet 中的,所以接收调用就是 Kubelet 进程。

  • 2、dockershim 收到请求后,转化成 Docker Daemon 能听懂的请求,发到 Docker Daemon 上请求创建一个容器。

  • 3、Docker Daemon 早在 1.12 版本中就已经将针对容器的操作移到另一个守护进程 containerd 中,因此 Docker Daemon 仍然不能帮我们创建容器,而是要请求 containerd 创建一个容器。

  • 4、containerd 收到请求后,并不会自己直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让 containerd-shim 去操作容器。是因为容器进程需要一个父进程来做诸如收集状态,维持 stdin 等 fd 打开等工作。而假如这个父进程就是 containerd,那每次 containerd 挂掉或升级,整个宿主机上所有的容器都得退出了。而引入了 containerd-shim 就规避了这个问题(containerd 和 shim 并不是父子进程关系)。

  • 5、我们知道创建容器需要做一些设置 namespaces 和 cgroups,挂载 root filesystem 等等操作,而这些事该怎么做已经有了公开的规范,那就是 OCI。它的一个参考实现叫做 runC。于是,containerd-shim 在这一步需要调用 runC 这个命令行工具,来启动容器。

  • 6、runC 启动完容器后本身会直接退出,containerd-shim 则会成为容器进程的父进程,负责收集容器进程的状态,上报给 containerd,并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程。

通过上面来看,Docker Daemon 和 dockershim 看上去就是两个不干活的东西,Kubelet 为啥不直接调用 containerd 呢?  所以新版本采用丢弃dockershim代码不支持docker了。docker自己并没有提供CRI接口,血淋淋的大厂厮杀。

 

K8S官方说明

别慌: Kubernetes 和 Docker | Kubernetesicon-default.png?t=LA92https://kubernetes.io/zh/blog/2020/12/02/dont-panic-kubernetes-and-docker/#

这里面说的也很清晰。

K8s 终将废弃 docker,TKE 早已支持 containerd - 腾讯云原生 - 博客园近日 K8s 官方称最早将在 1.23版本弃用 docker 作为容器运行时,并在博客中强调可以使用如 containerd 等 CRI 运行时来代替 docker。本文会做详细解读,并介绍 dockhttps://www.cnblogs.com/tencent-cloud-native/p/14134164.html

这一篇也说的非常清晰。

Docker、Containerd、RunC分别是什么?_wanger5354的博客-CSDN博客icon-default.png?t=LA92https://blog.csdn.net/wanger5354/article/details/121358241

k8s调用容器运行时也处于比较高的层级,这篇文章说了runc 这类比较低的运行时和比较高的containerd的调用关系。

RunC 是从 Docker 的 libcontainer 中迁移而来的,实现了容器启停、资源隔离等功能。Docker将RunC捐赠给 OCI 作为OCI容器运行时标准的参考实现。Docker 默认提供了 docker-runc 实现。事实上,通过 containerd 的封装,可以在 Docker Daemon 启动的时候指定 RunC的实现。
 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐