• Ukieweb

    佳的博客

    曾梦想仗剑天涯,后来工作忙没去。

K8s -- 为什么弃用 docker?什么是 cri ? 什么是 shim

在 K8s 1.24 弃用了 docker ,为什么?

CRI(容器运行时接口)

要理解 K8s 为什么“弃用 Docker”,我们还得回顾一下 K8s 的发展历史。

2014年,Docker如日中天,K8s刚刚诞生。虽然它得到了 Google 和 Borg 的支持,但它仍然相对较新并且没有很大的社区。

因此,K8s 自然而然地选择运行在 Docker 上。毕竟“大树背阴好”,同时也可以借机“养精蓄锐”,逐渐发展壮大自己。

时间快进到2016年,CNCF已经成立一年了,K8s也发布了1.0版本,可以正式用于生产环境。这些都预示着K8s已经成长起来了。

于是宣布加入CNCF,成为第一个CNCF托管项目。它想借助基金会的力量联合其他厂商“打倒”Docker。

在2016年底的1.5版本中,K8s引入了新的接口标准:CRI:Container Runtime Interface。

CRI 使用 ProtoBuffer 和 gPRC 来指定 kubelet  应该如何调用容器运行时管理容器image,但这是一组新的接口,与以前的 Docker 调用完全不兼容

显然它不想再被Docker束缚,底层允许接入其他容器技术(如rkt、kata等),随时可以“踢开”Docker。

但是此时的Docker已经很成熟了,市场的惯性也很强。各大云厂商不可能一下子全部取代Docker

因此,K8s只能同时提供一个“折衷”的解决方案,在kubeletDocker之间增加一个“适配器”,将Docker的接口转换为符合CRI的接口

cri-k8s.png

因为这个“适配器”夹在 kubelet Docker之间,所以被形象地称为“shim”,意思是“垫片”。

有了 CRI 和 shim,虽然 K8s 仍然使用 Docker 作为底层运行时,但也具备了与 Docker 解耦的条件,拉开了“弃用 Docker”大戏的序幕。

Containerd

面对挑战,Docker 采取了“断臂求生”的策略,将原来单一架构的 Docker Engine拆分为多个模块,其中 Docker daemon 部分捐赠给 CNCF组建 containerd

作为CNCF的托管项目,containerd必须遵守CRI标准。但是由于很多原因,Docker 只是在 Docker Engine 中调用了 containerd,对外接口保持不变,也就是说不兼容CRI

由于Docker的“固执”,此时 K8s 中有两条调用链:

k8s-call-chains.png

  • 使用 CRI 接口调用 dockershim,然后 dockershim 调用 Docker,Docker 再去 containerd 操作容器。

  • 使用 CRI 接口直接调用 containerd 操作容器。

显然,因为 containerd 是用来管理容器的,所以这两个调用链的最终效果是完全一样的,但是第二种方法去掉了 dockershim 和 Docker Engine 的两个环节,更简洁明了,性能更好。

2018 年 Kubernetes 1.10 发布时,containerd 也更新到1.1 版本,正式与 Kubernetes 集成,并发布博文(https://kubernetes.io/blog/2018/05/24/kubernetes-containerd-integration- goes-ga/ ),展示一些性能测试数据

k8s-docker-performance.jpg

从这些数据可以看出,相比当时的 Docker 18.03,containerd1.1 降低了 Pod启动延迟20%左右,CPU占用率降低了68%,内存占用率降低了12%,这是一个相当可观的性能提升,对于云供应商来说是非常有诱惑力的。

官方 Docker 弃用

两年后的 2020 年,K8s 1.20 终于正式向 Docker “宣战”:将kubelet弃用 Docker 支持,并在未来的版本中彻底移除。

但由于 Docker 几乎已经成为容器技术代名词,而 K8s 已经使用 Docker 多年,所以随着公告的传播“kubelet will deprecate Docker support”被简化为更吸引眼球的“K8s will deprecate docker”。

这自然引起了IT界的恐慌,“不明真相的群众”纷纷表示震惊:用了这么久的 Docker 突然不能用了。为什么 K8s 会这样对待 Docker?之前对 Docker 的投资会归零吗?现有的大量镜像怎么办?

其实,如果你了解了上面提到的这两个项目 CRI,containerd 就会知道K8s的这一举动并不奇怪,一切都是“自然而然”的:它其实只是“弃用了dockershim ”,即移除 dockershim,kubelet 并不是一个“弃用 Docker”的软件产品。

因此,“弃用Docker”对 K8s 和 Docker 不会有太大影响,因为它们的底层都是开源的 containerd,原有的 Docker 镜像和容器依然会正常运行。唯一的变化是K8s绕过了Docker,直接containerd 而不是借用 Docker 调用。

image.png

但是,也会有一些影响。如果 K8s 直接使用 containerd 来操作容器,那么它是一个独立于 Docker 的工作环境,两者都不能访问对方管理的容器镜像。也就是说,使用命令 docker ps看不到K8s中运行的容器的。

这对于某些人来说可能需要一点时间来适应并使用新工具 crictl,但是用于查看容器和 image 的子命令仍然是相同的,例如:ps,images等,适应起来并不困难(但如果我们如果你一直用kubectl管理k8s,这个没有效果)。

K8s 原本计划用一年的时间来完成“弃用 Docker”的工作,但它确实低估了 Docker 的根基。1.23版本还是没能去掉dockershim,只好推迟了半年。最后,今年 5 月发布的 1.24 版本将代码dockershim从kubelet.

自此,Kubernetes 与 Docker 彻底“分道扬镳”。

Docker的未来

那么,Docker 的未来会怎样?云原生时代就没有立足之地了吗?这个问题的答案显然是否定的。

作为容器技术的奠基者,没有人可以质疑Docker的历史地位。虽然 K8s 默认不再绑定 Docker,但 Docker 仍然可以通过其他形式与 K8s 共存。

首先,由于容器镜像格式已经标准化(OCI规范,Open Container Initiative)Docker 镜像在 K8s 中仍然可以正常使用原有的开发测试和CI/CD流程不需要改变。我们仍然可以拉取 Docker Hub ,或者写一个 Dockerfile 来打包应用程序。

其次,Docker是一个完整的软件产品线,不仅包含 containerd,它还包含了镜像构建、分发、测试等诸多服务,甚至K8s都内置在了Docker Desktop中。

容器开发的便利性而言,Docker暂时还很难被取代。广大云原生开发者可以继续在这个熟悉的环境中工作,使用Docker开发运行在K8s上的应用。

同样虽然K8s不再包含dockershim,但Docker已经接管了这部分代码并构建了一个名为 cri-dockerd(https://github.com/mirantis/cri-dockerd)的项目,该项目也同样有效,将  Docker Engine 适配为 CRI 接口,这样 kubelet 就可以通过它再次操作 Docker,就好像什么都没发生过一样。

整体来看,虽然Docker在容器编排大战中败北,被K8s挤到墙角,但依然拥有强大的生命力。多年积累的众多忠实用户和大量应用镜像是其最大的资本和后盾。足以支持它走另一条不与 K8s 正面交锋的道路。

对于初学者来说,Docker简单易用,拥有完整的工具链和友好的界面,市面上很难找到与之相媲美的软件。应该说是入门学习容器技术和云原生的“最佳选择”。



翻译自:

K8s — Why Deprecating Docker?



0
0
下一篇:为什么 containerd 使用 nerdctl 管理容器

0 条评论

老佳啊

85后,大专学历,中原人士,家里没矿。

由于年轻时长的比较帅气,导致在别人眼里,我一直不谈恋爱的原因是清高,实则是自己的小自卑。最大的人生目标就是找一个相知相爱相容的人,共度余生。

和人相处时如果能感受到真诚,会非常注重彼此的关系,对别人没有什么心机,即使有利益冲突,一般也会以和为贵,因为在这个世界上,物质的东西,从来不会吸引到我。

特别迷恋那些大山大水,如果现在还能隐居,可能早就去了。对那些宏伟的有底蕴的人文景观比较不感冒。

从事于IT行业,却一直对厨房念念不忘,由于身材魁梧,总觉得自己上辈子是个将军,可惜这辈子没当兵,也不会打架。