“寄生”在 kubelet 中的 dockershim

rkt 和 docker 争霸时,kubelet 需维护两坨代码分别适配运行时组件,严重拖慢新版本发布速度

SIG-Node 提出 CRI(Container Runtime Interface)让kubelet可以适配所有的运行时

Docker 当时并没有(也不打算)实现这组接口, kubelet 只能在内部维护 “dockershim”组件充当 docker 的 CRI 转接器,kubelet 创建容器时通过 CRI 接口调用 dockershim ,而 dockershim 再通过 http 请求把请求交给 docker 。 kubelet 架构变成下图

kubelet 创建容器调用链

  • 实现了 CRI 接口的组件作为容器运行时,红色箭头,ContainerManager 直接通过 CRI 调用到容器运行时,一次 grpc 请求
  • 使用 docker 时,ContainerManager 走蓝色调用链, CRI 请求通过 unix:///var/run/dockershim.sock 流向 dockershim,dockershim 做转换后把请求转发给 docker

kubelet 中实现 docker 转接器本来就是一种不优雅的实现,让调用链变长且不稳定性,还给 kubelet 的维护添加了额外工作

在 Pod 中使用 DinD(Docker in Docker)

docker 的 socket (/run/docker.sock) 挂载到 Pod 中,并在 Pod 中调用 docker 的 api 构建镜像或创建编译容器等

Kaniko、Img 或 Buildah。把 docker daemon 作为 DaemonSet 或者给想要使用 docker 的 Pod 添加一个 docker daemon 的 sidecar 的方式在任意运行时中使用 DinD 方案

containerd

2016 年docker 把负责容器生命周期的模块拆分出containerd捐给社区

docker 拆分后结构(docker 公司添加了部分编排代码)

调用 docker 命令创建容器后

  • docker daemon 通过 Image 模块下载镜像并保存到 Graph Driver 模块中

  • 之后通过 client 调用 containerd 创建并运行容器

  • 可能 --volume给容器添加持久化存储(Storage 模块)

  • 可能--network连接用 docker 命令创建的几个容器(Networking 模块)

K8s 提供了更强的卷挂载和集群级别的网络能力,在集群中 kubelet 只会用到 docker 提供的镜像下载和容器管理功能,而编排、网络、存储等功能都不会用到

kubelet 创建 Pod 时赖的几个运行时模块

containerd 捐赠给 CNCF 社区后,社区添加了镜像管理模块和 CRI 模块后,除管理容器的生命周期,还可直接作为 K8s 的运行时使用,2019 年 2 月从 CNCF 社区毕业,正式进入生产环境

containerd 作为容器运行时,给 kubelet 带来创建 Pod 所需的全部功能,同时得到更纯粹的功能模块以及更短的调用链

containerd 以成为简单、稳定且可靠的容器运行时为目标

docker 希望能成为一个完整的产品(交互,使用体验及更多的功能),同时为了给 swarm 做基础,提供了网络和卷的功能,K8s 用不上

一定程度上讲,即使在 kubelet 1.23 版本之后 docker 提供了 CRI 接口,containerd 仍然是更好的选择

https://www.cnblogs.com/tencent-cloud-native/p/14134164.html

https://www.infoq.cn/article/ouj6indxsbxdloo8j8fu

https://cnodejs.org/topic/57fdab2ffdf3bd3d65118530