k8s学习之路 | Day14 有关 k8s 弃用 Docker
CRI 是一个插件接口,它使 kubelet 能够使用各种容器运行时,你需要在集群中的每个节点上都有一个可以正常工作的容器运行时, 这样 kubelet 能启动 Pod 及其容器。容器运行时接口(CRI)是kubelet 和容器运行时之间通信的主要协议。
一直想搞清楚关于“k8s 弃用 docker 这件事情”,所以才有了这篇学习记录
官方有关这类话题的文章链接:
https://kubernetes.io/zh-cn/blog/2020/12/02/dont-panic-kubernetes-and-docker/
https://kubernetes.io/zh-cn/blog/2020/12/02/dockershim-faq/
Docker Engine 架构
我们需要先看以下当前 docker 引擎的各个组件,我们从最新的二进制安装包提取到相关组件
- Docker 相关的组件
docker
:docker 客户端的一个完整实现,就是docker 命令
dockerd
:docker 服务端的后台常驻进程,接收客户端发来的请求,执行和转发具体的处理任务,处理完成后将结果返回给客户端docker-init
:docker 会使用 docker-init 作为1号进程,帮助管理容器内子进程docker-proxy
:用来做端口映射,底层依赖iptables
实现
- containerd 相关的组件
containerd
:从 docker 1.11 版本正式从 dockerd 剥离出来,独立存在,完全遵循 OCI 标准,是容器标准化的产物- 负责容器生命周期管理
- 镜像管理
- 接收
dockerd
的请求,通过适当的参数调用runc
启动容器 - 管理存储相关资源
- 管理网络相关资源
- 可以不通过
dockerd
管理容器,可以直接使用containerd
来管理
containerd-shim
:垫片的意思,将containerd
与真正的容器进程进行解耦,使用containerd-shim
作为容器进程的父进程,从而实现重启containerd
不影响已经启动的容器进程ctr
:是containerd
的客户端,主要用来开发和调试,没有dockerd
的环境,这个东西可以用来充当客户端的部分角色
- 容器运行时相关的组件
runc
:是一个标准的 OCI 容器运行时的实现,是一个命令行工具,可以直接用来创建和运行容器
容器运行时 containerd
在上面docker
的架构中,可以看出:
- Docker 引擎包含了
containerd
containerd
专注于运行时的容器管理- Docker 除了容器管理之外,还可以完成镜像构建之类的功能
containerd
并不适合直接面向用户使用,适用于集成到更上层的系统里,比如:k8s、docker等容器编排系统
k8s 中的 kubelet 架构
通过之前的学习过程,知道在 k8s 中
- kubelet 负责维护容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理;
从上面这个图可以看出来
- 在 k8s 架构中,是通过
kubelet
这个组件,使用CRI
接口与容器运行时进行一个交互,
什么是 CRI
CRI 是一个插件接口,它使 kubelet 能够使用各种容器运行时,你需要在集群中的每个节点上都有一个可以正常工作的容器运行时, 这样 kubelet 能启动 Pod 及其容器。容器运行时接口(CRI)是kubelet 和容器运行时之间通信的主要协议
为何放弃使用 Docker Engine
这里的放弃使用Docker Engine
,指的是使用Docker Engine
作为容器运行时
容器运行时
不管什么工具,Docker、k8s 在运行一个容器的时候都会调用容器运行时(CRI),通过容器运行时来完成容器的生命周期管理
-
Docker Engine使用的就是
containerd
-
k8s 在1.24版本之前支持
Docker Engine
-
k8s 支持
containerd
、CRI-O
等多种容器运行时,这些容器运行时都遵循了 OCI 规范,并通过runc
来实现于操作系统内核交互完成容器的生命周期管理 -
但是
Docker Engine
不遵循 OCI 规范,因为他最终也还是通过containerd
去操作的
k8s 调用链
-
在 k8s 早期,那个时候的容器运行时没有太大选择,
Docker Engine
就是使用容器的主要工具,k8s 早期也仅支持这一种形式 -
经过发展,k8s 需要添加更多的容器运行时,来让用户自己选择自己的运行时,比如:
rkt
、hypernetes
等,CRI 的引入对 k8s 项目和用户来说都很棒,但是Docker Engine
作为容器运行时的使用早于 CRI,并且Docker Engine
不兼容 CRI,为了解决这个问题,k8s 的核心组件kubelet
就引入了一个小型软件dockershim
,专门用于填补Docker Engine
和CRI
之间的空白,允许集群操作员继续使用Docker Engine
作为他们的容器运行时基本上不间断,这个时候kubelet
的调用链将会是:kubelet
-->dockershim
(在 kubelet 进程中) -->dockerd
-->containerd
-
然而这个东西给
kubelet
本身带来了许多不必要的复杂性,由于这个shim
,Docker
的一些集成实现不一致,导致维护人员的负担增加,并且维护特定于供应商的代码不符合 k8s 的开源理念 -
这个事情一度的发酵和提起,迎来了最终的一个结果:
k8s 在1.24版本之后不在支持
Docker Engine
运行时,而是采用containerd
-
containerd
作为 k8s 容器运行时,调用链将会变成:kubelet
-->cri plugin
(在 containerd 进程中) -->containerd
-
如果使用
containerd
作为 k8s 容器运行时的话,kubelet
可以直接调用containerd
- 性能提高了(调用链变短了)
- 资源占用也变小了
更多推荐
所有评论(0)