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)