kubernetes移除Docker?

标签: | 发表时间:2020-12-16 08:37 | 作者:
出处:https://mp.weixin.qq.com

两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时。

Dockershim deprecation Docker as an underlying runtime is being deprecated. Docker-produced images will continue to work in your cluster with all runtimes, as they always have.

这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用。看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定?这样做的原因又是如何?又会带来那些影响呢?今天,咱们就来掰扯一下。


首先,看一下目前在Kubernetes上如何使用Docker运行时来创建一个容器,如下:


  1. Kubelet 通过 CRI (Container Runtime Interface)接口调用 dockershim,来创建一个容器。从图上不难看出kubelet的这一步调用,是自己在调用自己,也确实如此,这是因为dockershim的代码目前是内嵌在 Kubelet中的,所以请求的发送和接收都是Kubelet;

  2. dockershim收到请求后,会转换成Docker API请求发给Docker Daemon去创建一个容器;

  3. DockerDaemon收到后,在将请求发送给containerd创建一个容器

  4. containerd收该请求后,会创建一个叫做containerd-shim的进程,对容器的操作统统交给containerd-shim去完成;

  5. containerd-shim再调用runC来实现容器的的启动

  6. runC完成容器的启动后便会退出,containerd-shim会成为容器的父进程


所以不难看出,一旦从kubelet中移除dockershim,上述流程中的第一步就会无法完成,创建容器的请求自然就无法发送到Docker daemo上,真可谓釜底抽薪,一招毙命。不过,这个流程确实繁琐,要在CRI,dockershim,docker daemo之间绕一下,聪明的你肯定会对此产生各种疑问,“为什么kubelet不直接去调用containerd呢?这个CRI又是什么呢?为什么kubelet不能直接发给Docker Dameon呢? 如果在Kubernetes上使用rkt又应该怎么做呢?”


有道是有人的地方就有江湖,有利益,有帮派,有明争暗斗。想当年kubelet想要创建容器直接跟Docker Daemon说一声就行,而那时containerd还没出生,Docker Daemon自己调一下libcontainer这个库就可以让容器跑起来。但随着容器市场的逐渐火热,每个厂家都想扎进来,“这大蛋糕可不能让Docker一家吃完啊,倒不是馋那一两口蛋糕,主要是考虑到胆固醇太高对Docker的身体不好,所以大家应该踊跃的为Docker分担一下”。Docker也知道众人拾柴火焰高的道理,这把大火能否将传统技术厂商的城池化为灰烬,成为吾之沃土,靠一个人是远远不够的,于是振臂高呼“我要健康,我要放火”,接着就联合各路的带头大哥,鼓捣出一个OCI标准,用来规范容器市场,营造更为和谐的容器生态环境。而且Docker为了符合OCI标准,更是以身作则,直接挥刀自宫,把xx切了,额。。。错了,是把runtime及其管理功能从Docker daemon中剥离了出来,随后Docker又把libcontainer封装了一下,变成runC,做了投名状,捐给了OCI。


Docker所作的可谓仁至义尽,但还是有人不满足,CoreOS还想搞事,也想成为Kubernetes的默认runtime,与Docker并驾齐驱。Kubernetes也在考虑我不能和某一家的容器技术栈绑死,用户的口味也各异,连区区豆腐脑都有甜咸之分,我这高科技产物也应该满足用户的差异化需求,再加上Google和CoreOS的亲密关系,结果就真给合到kubelet里了,从而实现了对多个容器引擎的兼容,但这事费力不讨好,每次更新kubelet都得考虑Docker和rkt,负责维护kubelet的SIG Node小组越做越难受,直接掀了桌子。

‍‍



这活还得继续干,不过得换个思路,干脆把kubelet对容器的操作抽象成一个接口,kubelet只要和这个接口交互就行了,Docker,rkt等容器项目提供一个该接口的实现并暴露给kubelet不就妥了!于是Kubernetes在1.5推出了CRI,有了CRI接口后kubelet就不再直接和容器运行时Say Hi了,而是与CRI进行通信,从而实现了平台和容器运行时的解耦。响应CRI的组件称为CRI shim,它主要实现CRI规定的每个接口,然后把请求转换成对后端容器,比如Docker或rkt的请求或者操作。


这个CRI接口只是Kubernetes自家标准,而当时Kubernetes也没有现在今的地位,所以Docker觉得“凭啥你一个平台说风就是雨?”,不用你,我还有Swarm,并未立即针对CRI进行相应的开发。


Anyway,无论容器厂家们怎么来实现,容器运行时的三层抽象此时已经很清晰了,如下:

Orchestration API -> Container API -> Kernel API


具体一点就是:

Kubernetes API -> CRI-runtime > OCI-runtime


那么在Kubernetes中所划分的CRI-runtime/OCI-runtime都有那些呢?

  • cri-runtime:  containerd/CRI-O

  • oci-runtime:  runC/Kata/gVisor


下图很清晰的解释了这三者是如何协同工作的:



但如今Kubernetes的市场表现相当亮眼,占有率一度接近8成,而Swarm的表现就相当的一般了。按理说都这样了,得认怂,不能硬刚,毕竟人家拳头大啊。但Docker到现在都没有实现对CRI支持,依旧通过dockershim这样一个桥接服务来实现。你是不是觉得Docker的头太铁了,非要撞到南墙才肯回头?其实也不是,这里就要谈谈CNCF和containerd了。


我们知道Kubernetes的主力推手CNCF,是由Google牵头一众厂商于2015年成立,而在此之前Google曾向Docker表达了足够的“善意”,希望能够“手牵手,一步两步三步四步望着天,看星星,一颗两颗三颗四颗连成线”,一起给Docker项目开发一个中立的运行时,但彼时的Docker一家独大,压根不考虑这个“自残”的建议,没鸟Google。另一家知名的开源软件公司Redhat也曾因Docker强推Swarm的关系与其产生嫌隙。而和Docker有瓜葛的这两位,其实在2014年就达成了战略合作关系,现在Kubernetes所力推的,用于替换Docker运行时的CRI-O就是由Redhat开发,Redhat恰巧也是CNCF的创始会员。这局面,甚是有趣!鲁迅曾说过“和敌人的敌人交朋友,就像烧烤配啤酒”,看来Docker没有好好读鲁迅先生的书。



Kubernetes最初的时候使用Docker作为运行时,一是因为Docker拥有大量的用户,考虑到技术惯性,能够很容易的获得这部分用户;二是当时也没有其他的选择了,所以你才能看到kubelet中有dockershim的代码。但随着容器技术的快速发展,以及CRI的出现,Docker已经不在是唯一的选择了。Docker也考虑是否要实现CRI,但毕竟Docker本身包含了太多功能,如果仅仅作为一个运行时,说好听点是“大材小用”,说直白点是“你不够纯”。


前面我提到过,为了符合OCI标准,Docker daemo拆分出了runC以及containred。显然,containerd作为一个单纯的high-level容器运行时更贴合Kubernetes的需求。在2017年Docker把containerd年捐给了CNCF,随后一年Kubernetes开始支持containerd作为容器运行时管理器,2019年containerd从CNCF毕业,所以单从技术上看,此时的containerd已经可以作为Kubernetes的容器运行时了,替换Docker运行时的条件已经成熟。这么一看,在Docker上去实现对CRI的支持确实没啥必要,这应该就“头铁”的原因吧。BTW,我不是阴谋论者,但这一步一步的掏空Docker怎么看都像一个局啊!



另外,在2017年,迫切渴望盈利的Docker公司做了一个重要的决定,宣布将原来开源的Docker项目更名为Moby,交给社区维护,自己仍然持有Docker的注册商标,这是什么骚操作呢?说白了,世上再无Docker的开源项目,无论是Docker EE还是CE,都属于是Docker公司的商业产品。这样一来,多年来所积累的庞大用户团体和资源顷刻间转移到Docker公司的商业产品上。



其实Docker想盈利,谁都能理解,但依靠开源软件赚钱本身就是一件难事,成功者寥寥无几,Redhat能成是因为手上有个OS,但Docker没有啊,而且云原生时代的OS,目前看恰恰就是Kubernetes。更何况容器所采用的cgroup,namespace,aufs,overlay2等技术,都是Linux Kernel所提供的能力,并不是Docker独创。另外,Docker能如此快速的发展壮大,离不开社区多年以来的贡献,但这手分的一点都不graceful,本以为能“我挥一挥衣袖,不带走一片云彩”,Docker却“我改一改名,把项目全部带走”,如此激进的做法,伤了人心,丢了人心。


 


从此,Docker告别了开源,这自然与强调技术开放的Kubernetes站在了两条道上,“道不同不相为谋”。所以,去除dockershim的举动看似突然,实则早已埋下伏笔,有技术上的可能性,也有商业上的利益驱使,更有价值观上的不同。


后面的故事我们就都知道了,Kubernetes社区表明由于维护dockershim对于开发以及运维人员来说是一项繁重的任务,所以在1.20中正式弃用dockershime,不在支持Docker作为运行时,建议大家使用包含CRI完整实现的容器运行时。听上去有理有据,合情合理,但我相信真实的情况应该是这样:



仅供娱乐,别当真


那么Docker运行时没了,在Kubernetes中还能使用那些运行时呢?我们知道Runtime负责提取和运行容器镜像,而Docker只是众多容器运行时中的一种,还有很多选择,比如Kubernetes所提到的CRI的完整实现containerd以及CRI-O,如下图:




相对于dockershim的方案,这两种方案确实要简洁很多。第一种,就是kubelet直接调containerd,如果之前使用Docker,那么迁移到containerd应该是个不错的选择;第二种,CRI-O是Kubernetes的运行时,它的目的式绕过现有的机制,直接操作Linux容器,但在稳定性上目前可能无法满足商用的需求。


如果你担心以后无法使用Docker镜像,也Duck不必。因为Docker镜像是符合OCI标准的,对于Kubernetes来说,只要镜像符合OCI标准,就OK,其他的runtime也是如此。


如果用户近期不想替换运行时怎么办?在1.20上仍然可以使用Docker作为runtime,只不过在启动kubelet时会出现一条告警。直到2021年末Kubernetes才会在1.23版本中将完全移除dockershim。如果你很固执,在1.23后仍然像继续使用Docker,部署一个dockershim呗,自己去集成起来,而且Mirantis和Docker也会合作出一个开源的dockershim组件。


综上,这个移除会有影响,但有限,并不是毁天灭地。相反,商业化的Docker被移除,对于云原生技术发展可能会起到更为正面的影响,推动其他开源容器项目的发展。


好了,就扯到这里了,下次咱们再聊聊容器运行时。


参考资料:

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#whats-new-major-themes

https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

https://kubernetes.io/blog/2020/12/02/dockershim-faq/

相关 [kubernetes docker] 推荐:

kubernetes移除Docker?

- -
两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时. 这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用. 看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定.

docker/kubernetes国内源/镜像源解决方式

- - Xinkun Blog
最近在使用kubeadm时,被各种连接不上搞到崩溃. 这里统一整理了国内的一些镜像源,apt源,kubeadm源等,以便查阅. Azure China提供了目前用过的质量最好的镜像源. 而且都支持匿名拉取,也就是不需要登录. 这里,我开发了一个小的脚本azk8spull,这个脚本可以自动根据镜像名称进行解析,转换为azure的mirror镜像源域名.

Kubernetes & Microservice

- - 午夜咖啡
这是前一段时间在一个微服务的 meetup 上的分享,整理成文章发布出来. 谈微服务之前,先澄清一下概念. 微服务这个词的准确定义很难,不同的人有不同的人的看法. 比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界.

Docker & Flatpak

- - IT瘾-dev
目前最流行的技术莫过于Docker,Docker和Docker衍生的东西用到了很多很酷的技术,目前deepin应用软件发布转变成flatpak,这些看似风牛马不相及的技术方案,实际都使用了一个共同的底层技术——Namespace,假如没有namespace支持,这些技术实现都将成为空中楼阁. 一句话总结,无论是Docker、sysmted-nspawn还是flatpak,都是在namespace基础上,针对不同的场景,生出的不同的解决方案.

docker初体验之docker-tomcat

- - BlogJava-首页技术区
docker已经是现在最热的容器技术,最近也去体验了一下,在daocloud注册了一个账号,并开始本机实战docker. daocloud免费有两个容器可用,体验送T恤,邀请送书,这里我分享一个daocloud的邀请码 https://account.daocloud.io/signup?invite_code=mxeq2jkmcur37vz6ven8,daocloud是非常棒的容器云平台,使用体验好,问题响应也及时,绑定微信还送一个额外容器.

Kubernetes 完全教程

- - 午夜咖啡
经过一个阶段的准备,视频版本的 《Kubernetes 完全教程》出炉了. 课程一共分为七节,另外有一节 Docker 预备课,每节课大约一个多小时. 目标是让从没接触过 Kubernetes 的同学也能通过这个课程掌握 Kubernetes. 为什么要学习 Kubernetes. 在介绍课程之前,先说说为什么要学习 Kubernetes 以及什么人需要学习 Kubernetes.

Kubernetes 监控详解

- - DockOne.io
【编者的话】监控 Kubernetes 并不是件容易的事. 本文介绍了监控 Kubernetes 的难点、用例以及有关工具,希望可以帮助大家进一步了解监控 Kubernetes. 如果想要监控 Kubernetes,包括基础架构平台和正在运行的工作负载,传统的监控工具和流程可能还不够用. 就目前而言,监控 Kubernetes 并不是件容易的事.

Docker应用场景

- - 灯火阑珊
Flynn:一个使用go语言编写的开源PaaS平台,目标是简化分布式环境中应用的部署和维护,可以通过git push命令,将应用部署到Docker,从而省去复杂的配置和操作. CoreOS:一种新的架构体系重新设计的Linux发型版,可以运行在既有的硬件活着云服务器上. CoreOS不提供类似yum或apt的包管理工具,用户不需要在CoreOS中安装软件,而是让程序都在Docker容器中运行.

docker使用场景

- - 开源软件 - ITeye博客
Docker应用容器相对于 VM 有以下几个优点:. 1、启动速度快,容器通常在一秒内可以启动,而 VM 通常要更久. 2、资源利用率高,一台普通PC 可以跑上千个容器,你跑上千个 VM 试试. 3、性能开销小, VM 通常需要额外的 CPU 和内存来完成 OS 的功能,这一部分占据了额外的资源. 因为VM 的 Hypervisor 需要实现对硬件的虚拟化,并且还要搭载自己的操作系统,自然在启动速度和资源利用率以及性能上有比较大的开销.

Docker 监控实战

- - SegmentFault 最新的文章
如今,越来越多的公司开始使用 Docker 了,现在来给大家看几组数据:. 2 / 3 的公司在尝试了 Docker 后最终使用了它. 也就是说 Docker 的转化率达到了 67%,而转化市场也控制在 60 天内. 越大型的公司越早开始使用 Docker. 研究发现主机数量越多的公司,越早开始使用 Docker.