Docker 架构演进
演进方向
这里先把结论抛出来,Docker这几年的架构演进方向:
1、原有引擎功能下沉入containerd,containerd向着独立于Docker 作为通用容器运行时工具方向演进
2、swarm功能整合入引擎,swarmkit模块不断弱化,最终将被引擎吸收
3、引擎内部功能不断解藕出新模块
一言以蔽之:containerd变胖,引擎集群化
背景
Docker公司在集群管理服务编排工具竞争上落败
Docker公司在2015年Docker 1.9推出了自己的集群管理服务编排工具swarm,刚开始swarm作为一个独立的工具,在Docker 引擎之外。但是从Docker 1.12开始Docker公司将swarm整合入了Docker引擎。至此Docker swarm作为一个完整的服务编排工具和谷歌主导、红帽支持的kubernetes社区直接冲突。于此同时Docker公司在2015开启了自己的商业化之路,开源社区为了避免Docker公司商业化过程中将Docker沦为绑架社区的工具,所以顺势推出了多个Docker替代方案例如rkt。kubernetes社区推出了CRI-O标准,只要是遵从此标准的容器运行时都可以被K8s支持。一时间Docker大有被主流社区抛弃之势!经过2年和K8s的竞争时间来到2017年,Docker swarm已经在事实上彻底落败,Kubernetes社区已经成为开源项目中热度最高的项目。为了应对如此多的不利因素,Docker公司在2017年将自己主导的containerd捐献给CNCF基金会(k8s是旗下的子项目);并且将更多的Docker引擎的功能下沉到Containerd中。借此避免自己在开源社区中被边缘化。
容器世界的标准化不断推进
Docker公司在2013念推出Docker后,极大的颠覆了这个行业,也推进了业务容器化过程。2015 Docker公司主导之下社区推出了容器的第一个行业标准OCI标准(开放容器协议)。彼时Docker公司推出了第一个OCI标准的容器运行时runc。runc作为第一个oci标准运行时(runtime),只是一个参考实现,仅仅承担容器与主机之间的交互。容器运行状态检查、监控,容器生命期管理,io管理、信号传递等一些列容器运行必不可少的功能却“无处安放”。所以Docker公司将Containerd定位为一个生产环境下的OCI 标准运行时。它承担了runc所缺少的大部分容器运行必要功能:生命期管理,io管理,信号管理。在2017年的时候OCI v1标准发布,Docker公司将Docker镜像格式捐献给了OCI协议。所以在2017年发布的Containerd1.0中存储管理这些原来由引擎承担的功能也进入了Containerd(网络管理功能,在https://containerd.io路线图中被列为roadmap,但是在2016年12月份Containerd的主要维护者投票中,网络功能不被列入containerd的功能范畴 而继续交给上层完成,在github containerd的readme中2017 1月12日正式将网络部分功能从containerd 维护范畴中删除)。
Containerd
Containerd在Docker 1.11中才正式出现,刚开始时0.x版本;2017年才推出了1.x标准。如上文所说,Container d作为一个生产环境可用的Oci 实现,它利用了OCI 运行时和镜像格式.下图展现了Containerd对自己在社区中地位作出了诠释

可以看到Containerd作为PaaS工具的通用容器运行时适配层,它利用已有的oci运行时(Containerd使用runc作为运行时,在windows上则是hcsshim),屏蔽底层操作系统的差异;为Paas提供通用的容器支撑。从这个图可以看到Containerd计划支持所有现有应用广泛的Paas平台工具。
下图为Containerd 1.x的架构图

从此架构图可以清楚的看到Containerd对上提供grpc接口方式的api,而Metric api是度量功能使用的。Distribution和Bundle子系统用于容器存储管理,Runtime子系统用于容器执行和监控。Content、Metadata和Snapshots是存储管理组建,Excutor和Supervisor是执行体组建。整个系统通过Event事件驱动。
根据github上containerd的介绍containerd项目工作内容集中在如下几个Scope上:
1、执行:容器创建、运行、停止、暂停、恢复,exec,信号传递、和删除。
2、cow 文件系统支持:在overlay,aufs和其他cow文件系统上内置了存储功能
3、度量系统
4、发布:容器镜像的pull和push,镜像的管理和获取
下面内容不作为containerd项目的工作范畴:
1、网络:网络的创建和管理由高层来完成
2、build:镜像的构建
3、volumes:volume管理:mounts,bind等针对volume的功能应该有高层来完成
4、logging
这里顺便介绍一下Containerd版本兼容规则:Containerd同一个大版本下的连续两个小版本是兼容的。例Containerd1.1.0和1.2.0却是兼容的,1.0.0和1.2.0却不保证兼容。
Docker的演进
下图介绍了containerd在1.11之前(不含)的Docker架构

可以看到在Docker1.11之前,没有containerd模块,由libcontainer直接操作主机os接口。
下图介绍了在Docker 1.11--Docker 17.10之间的docker架构

从图3-2看到这一时期的Docker架构变化就是引入了Containerd和runc,由Containerd完成容器生命期管理。
下图列出了Docker 17.11(Docker 17.12为真正的stable版)开始的架构

需要注意的一点图网络部分并不在containerd中,仍然在docker engine里。
Docker 17的具体架构演进
这里介绍的内容均来自于Moby社区的roadmap和Docker\docker-ce 的分析。
17.06---17.10的路线图描述此一时期,moby社区(引擎)的主要工作是:
1、插件功能的提升:方便插件的发布(通过registry以docker镜像方式发布),解决插件开发的共性问题(插件任何时候的需要active,在用户容器启动之前就start,以及插件写在困难)
2、引擎内部解藕:api已完成重构,builder实现在daemon中已完全独立。
3、提升引擎集群管理能力:当前跨节点网络(overlay网络)和节点发现已经整合到引擎里。但是引擎尚不能不依赖于swarmkit完成task调度
4、cli从engine中独立出来(这一点源自于github moby代码分析)。
17.11--18.03 的路线描述此一时期,moby社区(引擎)的主要工作:
1、引擎使用Containerd1.0
2、引擎内部解藕,计划整合buildkit工具
Docker架构演进大事记
1、Docker 1.9 推出swarm,作为独立工具,用于集群管理和服务编排
2、Docker 1.11 推出containerd和runc。
3、Docker 1.12 swarm进入引擎
4、Docker 17.06 引擎社区更名为moby,do c ke r社区版本更名为docker-ce(类似于红帽的fedora和rhel)
5、Docker 17.12 Docker正式引入containerd 1.0
k8s社区对Docker 17.03之后版本态度
在Docker 17.03后Docker因为moby和containerd等原因版本变动比较大,我们可以看到k8s r11发布后的2018年9月仍然没有将Docker 17.03以后(不含)版本作为k8s的兼容Docker版本。从社区的讨论来看社区已经推荐将containerd直接对接cri,完成k8s的集成。见https://github.com/kubernetes/kubernetes/issues/42926,其中cpuguy83(此人为moby社区的主要维护者)推荐直接使用containerd替代docker 17.03以后的版本对接k8s。