Docker 架構(gòu)演進(jìn)之路

前言

Docker已經(jīng)推出了5年,在這5年中它極大的改變了互聯(lián)網(wǎng)產(chǎn)品的架構(gòu),推進(jìn)了新的產(chǎn)品開(kāi)發(fā)、測(cè)試和運(yùn)維方法。但是它自身也在激烈變化中。特別是最近2年隨著Docker開(kāi)源項(xiàng)目的不斷演化,Docker內(nèi)部結(jié)構(gòu)發(fā)生了翻天覆地的變化。作為一個(gè)容器平臺(tái)的使用者,可以不用關(guān)注具體的Docker演進(jìn)細(xì)則,但是必須明白Docker的衍化會(huì)對(duì)自己的PaaS平臺(tái)帶來(lái)什么樣的影響(如果您對(duì)Docker技術(shù)細(xì)節(jié)不關(guān)注,你可以直接看第2章和最后兩章)。本文材料來(lái)自于Docker社區(qū),對(duì)Docker最近幾年的變化趨勢(shì)做出了總結(jié)。同時(shí)在結(jié)尾處給出了基于k8s PaaS平臺(tái)在底層容器上選型建議?!?/p>

演進(jìn)方向


圖2-1 Docker結(jié)構(gòu)圖

這里先把結(jié)論拋出來(lái),Docker這幾年的架構(gòu)演進(jìn)方向:

1、原有引擎功能下沉入containerd,containerd向著獨(dú)立于Docker 作為通用容器運(yùn)行時(shí)工具方向演進(jìn)

2、swarm功能整合入引擎,swarmkit模塊不斷弱化,最終將被引擎吸收

3、引擎內(nèi)部功能不斷解藕出新模塊,同時(shí)新功能不斷加入Docker 引擎。

一言以蔽之:containerd核心化,引擎集群化。

背景

Docker公司在集群管理服務(wù)編排工具競(jìng)爭(zhēng)上落敗

Docker公司在2015年Docker 1.9推出了自己的集群管理服務(wù)編排工具swarm,剛開(kāi)始swarm作為一個(gè)獨(dú)立的工具,在Docker 引擎之外。但是從Docker 1.12開(kāi)始Docker公司將swarm整合入了Docker引擎。至此Docker swarm作為一個(gè)完整的服務(wù)編排工具和谷歌主導(dǎo)、紅帽支持的kubernetes社區(qū)直接沖突。于此同時(shí)Docker公司在2015開(kāi)啟了自己的商業(yè)化之路,開(kāi)源社區(qū)為了避免Docker公司商業(yè)化過(guò)程中將Docker淪為綁架社區(qū)的工具,所以順勢(shì)推出了多個(gè)Docker替代方案例如rkt。kubernetes社區(qū)推出了CRI-O標(biāo)準(zhǔn),只要是遵從此標(biāo)準(zhǔn)的容器運(yùn)行時(shí)都可以被K8s支持。一時(shí)間Docker大有被主流社區(qū)拋棄之勢(shì)!經(jīng)過(guò)2年和K8s的競(jìng)爭(zhēng)時(shí)間來(lái)到2017年,Docker swarm已經(jīng)在事實(shí)上徹底落敗,Kubernetes社區(qū)已經(jīng)成為開(kāi)源項(xiàng)目中熱度最高的項(xiàng)目。為了應(yīng)對(duì)如此多的不利因素,Docker公司在2017年將自己主導(dǎo)的containerd捐獻(xiàn)給CNCF基金會(huì)(k8s是旗下的子項(xiàng)目);并且將更多的Docker引擎的功能下沉到Containerd中。借此避免自己在開(kāi)源社區(qū)中被邊緣化。

容器世界的標(biāo)準(zhǔn)化不斷推進(jìn)

Docker公司在2013念推出Docker后,極大的顛覆了這個(gè)行業(yè),也推進(jìn)了業(yè)務(wù)容器化過(guò)程。2015 Docker公司主導(dǎo)之下社區(qū)推出了容器的第一個(gè)行業(yè)標(biāo)準(zhǔn)OCI標(biāo)準(zhǔn)(開(kāi)放容器協(xié)議)。彼時(shí)Docker公司推出了第一個(gè)OCI標(biāo)準(zhǔn)的容器運(yùn)行時(shí)runc。runc作為第一個(gè)oci標(biāo)準(zhǔn)運(yùn)行時(shí)(runtime),只是一個(gè)參考實(shí)現(xiàn),僅僅承擔(dān)容器與主機(jī)之間的交互。容器運(yùn)行狀態(tài)檢查、監(jiān)控,容器生命期管理,io管理、信號(hào)傳遞等一些列容器運(yùn)行必不可少的功能卻“無(wú)處安放”。所以Docker公司將Containerd定位為一個(gè)生產(chǎn)環(huán)境下的OCI 標(biāo)準(zhǔn)運(yùn)行時(shí)。它承擔(dān)了runc所缺少的大部分容器運(yùn)行必要功能:生命期管理,io管理,信號(hào)管理。在2017年的時(shí)候OCI v1標(biāo)準(zhǔn)發(fā)布,Docker公司將Docker鏡像格式捐獻(xiàn)給了OCI協(xié)議。所以在2017年發(fā)布的Containerd1.0中存儲(chǔ)管理這些原來(lái)由引擎承擔(dān)的功能也進(jìn)入了Containerd(網(wǎng)絡(luò)管理功能,在https://containerd.io路線圖中被列為roadmap,但是在2016年12月份Containerd的主要維護(hù)者投票中,網(wǎng)絡(luò)功能不被列入containerd的功能范疇 而繼續(xù)交給上層完成,在github containerd的readme中2017 1月12日正式將網(wǎng)絡(luò)部分功能從containerd 維護(hù)范疇中刪除)

Containerd

Containerd在Docker 1.11中才正式出現(xiàn),剛開(kāi)始時(shí)0.x版本;2017年才推出了1.x標(biāo)準(zhǔn)。如上文所說(shuō),Container?d作為一個(gè)生產(chǎn)環(huán)境可用的Oci 實(shí)現(xiàn),它利用了OCI 運(yùn)行時(shí)和鏡像格式.下圖展現(xiàn)了Containerd對(duì)自己在社區(qū)中地位作出了詮釋


圖2-1 Containerd在Paas社區(qū)上的定位

可以看到Containerd作為PaaS工具的通用容器運(yùn)行時(shí)適配層,它利用已有的oci運(yùn)行時(shí)(Containerd使用runc作為運(yùn)行時(shí),在windows上則是hcsshim),屏蔽底層操作系統(tǒng)的差異;為Paas提供通用的容器支撐。從這個(gè)圖可以看到Containerd計(jì)劃支持所有現(xiàn)有應(yīng)用廣泛的Paas平臺(tái)工具。現(xiàn)在可以確認(rèn)的是AWS ECS,k8s,Docker上使用containerd。Mesos和cloud foundry今天(2018年9月)尚未確定。

下圖為Containerd 1.x的架構(gòu)圖


圖2-2 Containerd1.x架構(gòu)圖

從此架構(gòu)圖可以清楚的看到Containerd對(duì)上提供grpc接口方式的api,而Metric api是度量功能使用的。所有的編排工具容器適配層都可以使用grpc api作為containerd的客戶端,使用containerd操作容器。

Distribution用于容器鏡像的pull和push動(dòng)作(這部分出現(xiàn)在Containerd中完全是因?yàn)閛ci v1標(biāo)準(zhǔn)推出Docker公司將自己鏡像格式貢獻(xiàn)了出去,所以containerd理所當(dāng)然需要對(duì)鏡像進(jìn)行管理了)。Bundle(在docker的語(yǔ)景里是容器運(yùn)行的目錄集)子系統(tǒng)用于容器存儲(chǔ)管理它的作用就是原來(lái)的graphdriver,它提供將容器鏡像拆解成容器運(yùn)行時(shí)刻需要的Bundle。Runtime子系統(tǒng)用于容器執(zhí)行和監(jiān)控,就是它直接操作runtime,傳遞和接收信號(hào)(signal),中轉(zhuǎn)fifo,記錄日志。Content、Metadata和Snapshots是存儲(chǔ)管理組建,Excutor和Supervisor是執(zhí)行體組建。整個(gè)系統(tǒng)通過(guò)Event事件驅(qū)動(dòng)。

根據(jù)github上containerd的介紹containerd項(xiàng)目工作內(nèi)容集中在如下幾個(gè)領(lǐng)域上:

1、執(zhí)行:容器創(chuàng)建、運(yùn)行、停止、暫停、恢復(fù),exec,信號(hào)傳遞、和刪除。

2、cow 文件系統(tǒng)支持:在overlay,aufs和其他cow文件系統(tǒng)上內(nèi)置了存儲(chǔ)功能

3、度量系統(tǒng)

4、發(fā)布:容器鏡像的pull和push,鏡像的管理和獲取

下面內(nèi)容不作為containerd項(xiàng)目的工作范疇:

1、網(wǎng)絡(luò):網(wǎng)絡(luò)的創(chuàng)建和管理由高層來(lái)完成

2、build:鏡像的構(gòu)建

3、volumes:volume管理:mounts,bind等針對(duì)volume的功能應(yīng)該有高層來(lái)完成

4、logging

此處需要說(shuō)明一下網(wǎng)絡(luò)曾經(jīng)作為containerd社區(qū)爭(zhēng)論的焦點(diǎn)。但是在16年年底的社區(qū)維護(hù)者投票中多數(shù)人支持網(wǎng)絡(luò)不留在containerd中,因?yàn)榘凑沾蠖鄶?shù)維護(hù)者的認(rèn)識(shí)網(wǎng)絡(luò)過(guò)于復(fù)雜,而且網(wǎng)絡(luò)設(shè)置常常需要跨越節(jié)點(diǎn)。這部分功能由containerd的客戶端(Docker Engine 或k8s)做更合適。

這里順便介紹一下Containerd版本兼容規(guī)則:Containerd同一個(gè)大版本下的連續(xù)兩個(gè)小版本是兼容的。例Containerd1.1.0和1.2.0卻是兼容的,1.0.0和1.2.0卻不保證兼容。

Docker的演進(jìn)

下圖介紹了containerd在1.11之前(不含)的Docker架構(gòu)


圖3-1Docker1.11(不含)之前的架構(gòu)

可以看到在Docker1.11之前,沒(méi)有containerd模塊,由libcontainer直接操作主機(jī)os接口。

下圖介紹了在Docker 1.11--Docker 17.10之間的docker架構(gòu)


圖3-2 Docker 1.12-17.10之前(含)架構(gòu)

從圖3-2看到這一時(shí)期的Docker架構(gòu)變化就是引入了Containerd和runc,由Containerd完成容器生命期管理。

下圖列出了Docker 17.11(Docker 17.12為真正的stable版)開(kāi)始的架構(gòu)


圖3-3 docker 17.12以后架構(gòu)


需要注意的一點(diǎn)圖網(wǎng)絡(luò)部分并不在containerd中,仍然在docker engine里。

Docker 17的具體架構(gòu)演進(jìn)

這里介紹的內(nèi)容均來(lái)自于Moby社區(qū)的roadmap和Docker\docker-ce 的分析。

17.06---17.10的路線圖描述此一時(shí)期,moby社區(qū)(引擎)的主要工作是:

1、插件功能的提升:方便插件的發(fā)布(通過(guò)registry以docker鏡像方式發(fā)布),解決插件開(kāi)發(fā)的共性問(wèn)題(插件任何時(shí)候的需要active,在用戶容器啟動(dòng)之前就start,以及插件寫(xiě)在困難)

2、引擎內(nèi)部解藕:api已完成重構(gòu),builder實(shí)現(xiàn)在daemon中已完全獨(dú)立。

3、提升引擎集群管理能力:當(dāng)前跨節(jié)點(diǎn)網(wǎng)絡(luò)(overlay網(wǎng)絡(luò))和節(jié)點(diǎn)發(fā)現(xiàn)已經(jīng)整合到引擎里。但是引擎尚不能不依賴于swarmkit完成task調(diào)度

4、cli從engine中獨(dú)立出來(lái)(這一點(diǎn)源自于github moby代碼分析)。

17.11--18.03 的路線描述此一時(shí)期,moby社區(qū)(引擎)的主要工作:

1、引擎使用Containerd1.0

2、引擎內(nèi)部解藕,計(jì)劃整合buildkit工具

Docker架構(gòu)演進(jìn)大事記

1、Docker 1.9 推出swarm,作為獨(dú)立工具,用于集群管理和服務(wù)編排

2、Docker 1.11 推出containerd和runc。

3、Docker 1.12 swarm進(jìn)入引擎

4、Docker 17.06 引擎社區(qū)更名為moby,do?c?ke?r社區(qū)版本更名為docker-ce(類似于紅帽的fedora和rhel)

5、Docker 17.12 Docker正式引入containerd 1.0

6、Docker 18.06 正式在engine里加入了buildkit,在設(shè)置一個(gè)環(huán)境變量后可以使用buildkit完成docker build過(guò)程。

Docker 18.06.1正式將containerd 1.1引入docker。


k8s社區(qū)對(duì)Docker 17.03之后版本態(tài)度

在Docker 17.03后Docker因?yàn)閙oby和containerd等原因版本變動(dòng)比較大,我們可以看到k8s r11發(fā)布后的2018年9月仍然沒(méi)有將Docker 17.03以后(不含)版本作為k8s的兼容Docker版本。從社區(qū)的討論來(lái)看社區(qū)已經(jīng)推薦將containerd直接對(duì)接cri,完成k8s的集成。見(jiàn)https://github.com/kubernetes/kubernetes/issues/42926,其中cpuguy83(此人為moby社區(qū)的主要維護(hù)者)推薦直接使用containerd替代docker 17.03以后的版本對(duì)接k8s。本來(lái)docker在k8s社區(qū)中的兼容性測(cè)試由k8s sig-node 工作組完成,但是通過(guò)k8s討論可以看到sig-node并沒(méi)有計(jì)劃做docker 17.03以后docker的兼容性測(cè)試。

最新消息是2018年9月27日k8s出r12 rc的時(shí)候,kubeadm里已經(jīng)加入了對(duì)docker18.06的支持,且完成了ci測(cè)試。12 rc 文檔里將docker17.12,18.03,18.06之后列入支持表。但在k8s中 sig-node工作組負(fù)責(zé)底層容器接口,docker在k8s版本的兼容性測(cè)試本應(yīng)由此工作組完成,但是sig-node對(duì)于docker 17.03版本以后docker版本的態(tài)度依然冷淡,一直未列入明確的工作計(jì)劃中。sig-node工作組兩位主席是谷歌和紅帽的,它們對(duì)于cri更感興趣。在2018年5月,sig-node和containerd社區(qū)共同完成了cri-containerd合入containerd1.1的工作,并發(fā)布了containerd 整合到kubenetes的GA。完成此部分工作后,k8s驅(qū)動(dòng)containerd的結(jié)構(gòu)更簡(jiǎn)單明確。下圖介紹了docker,containerd在k8s上的架構(gòu)圖:


docker在k8s上的架構(gòu)圖




containerd1.1在k8s上的架構(gòu)圖

從上面兩幅圖我們可以看到containerd1.1在k8s上擁有更簡(jiǎn)單的結(jié)構(gòu)圖,驅(qū)動(dòng)更為簡(jiǎn)單。而且根據(jù)k8s社區(qū)的測(cè)試,直接使用containerd替代docker可以獲得容器啟動(dòng)時(shí)間、內(nèi)存消耗和cpu消耗減少的紅利。上述結(jié)論來(lái)自于:

https://kubernetes.io/blog/2018/05/24/kubernetes-containerd-integration-goes-ga/

所以sig-node工作組對(duì)docker 高版本不感冒。目前多方力量博弈,未來(lái)k8s下層的runtime花落誰(shuí)家還再觀察。


kubelet調(diào)用docker容器的方式

docker-manager是老的kubelet介入docker的方式。

cri從k8s 1.6開(kāi)始正式進(jìn)入k8s

cri直接介入containerd是從18年4月,containerd1.1開(kāi)始


PaaS平臺(tái)選型建議

如果你正在對(duì)基于k8s的PaaS平臺(tái)進(jìn)行生產(chǎn)環(huán)境選型,我建議你使用Docker17.03,因?yàn)樗墒旆€(wěn)定且k8s r9,r10和r11做過(guò)穩(wěn)定、兼容性測(cè)試。如果你喜歡嘗試新事物,我建議你跳過(guò)Docker17.03之后,直接在kublet上使用containerd1.1。如果你喜歡docker新版本,那么你可以嘗試docker18.06,因?yàn)镈ocker17.12是Docker變化最劇烈的一個(gè)版本穩(wěn)定性不好說(shuō),且kuberadm中r12 rc里加入了對(duì)18.06的支持所以用最新的好了。而且更關(guān)鍵的一點(diǎn)docker 18.06.1使用containerd 1.1,它支持一個(gè)特性:上層容器控制平臺(tái)的namespace隔離,簡(jiǎn)單點(diǎn)說(shuō)就是docker和k8s均可以在同一個(gè)節(jié)點(diǎn)上操作同一個(gè)containerd,且相互隔離不可見(jiàn)。如此可以預(yù)留選擇傳統(tǒng)k8s+docker組合時(shí)刻,保留將來(lái)切換成k8s+containerd組合的可能性,進(jìn)而為自己的框架保持演進(jìn)的靈活性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容