1.前言

  近日,Kubernetes 官方发布公告,宣布自 v1.20 起放弃对 Docker 的支持,届时用户将收到 Docker 弃用警告,并需要改用其他容器运行时。并在1.23后不再支持docker。

  但Docker目前作为容器镜像构建工具的作用将不受影响,用其构建的容器镜像将一如既往地在集群中与所有容器运行时正常运转。

Kubernetes将弃用docker?_父进程

  • 维护dockershim已成为Kubernetes维护人员的一种负担。创建CRI标准就是为了减轻这种负担,并提升不同容器运行时的可移植性性。Docker本身目前没有实现CRI,但Containerd实现了CRI接口。Dockershim一直是一种临时解决方案,此外,与dockershim不兼容的特性,如cgroups v2和用户命名空间,实现CRI接口的运行时也在慢慢探索并实现上述特性。
  • Kubelet中对Docker支持被弃用,并将在以后的版本中删除。Kubelet使用一个名为​​dockershim​​​的模块,该模块实现了对Docker的​​CRI​​​支持,在此PR后续版本将删除​​dockershim​​。删除了dockershim,那么就不支持了。
  • Kubectl弃用​​--delete-local-data​​ 参数。

 

2.名词解释

  上面中提到两个名词,分别为CRI和dockershim。下面分别解释一下:

2.1 CRI

  大家在看到CRI时就会想起OCI,这两个名词概念容易混淆。

  CRI:容器运行时接口container runtime interface,CRI 中定义了容器和镜像两个接口,实现了这两个接口目前主流的是:CRI-O、Containerd。(目前 PCI 产品使用的即为 Containerd)。

  其主要的作用:

  1.针对容器操作的接口,包括容器的创建、启动和停止等

  2.针对镜像的操作,拉去、删除镜像等

  3.针对 podsandbox(容器沙箱环境)

  4.以上全是接口

 

2.2 OCI

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

  主要作用,制作容器:

  1.容器镜像制作内容,即ImageSpec

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

 

2.3 Dockershim

  dockershim作用:把外部收到的请求转化成Docker Daemon能听懂的请求,让 Docker Daemon 执行创建、删除等容器操作。

 

3.Kubelete 创建容器步骤

 

Kubernetes将弃用docker?_docker_02

  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呢?其实和容器历程有关,这里不在阐述。

  尽管现在已经有CRI-O,containerd-plugin这样更精简轻量的Runtime架构,但dockershim这一套作为经受了最多生产环境考验的方案,迄今为止仍是Kubernetes默认的 Runtime实现。不过Containerd逐渐被人们所知晓。

 

4.展望

  虽然未来Kubelet删除dockershim支持,但并不说明Docker马上就不能在 Kubernetes 中使用,目前容器市场 Docker 还是占用很大的比例。这中间会有一个过渡期,大家可以关注Containerd或者Podman。Centos8开始,仓库源默认容器已经从Docker切换为Podman。

 


作者:​​小家电维修​

转世燕还故榻,为你衔来二月的花。