此篇文章是《Using Docker》一書的作者 Adrian Mouat 編寫,詳細(xì)對比分析了Swarm、Fleet、K8s以及Mesos的區(qū)別。
大部分軟件系統(tǒng)是隨時(shí)間演進(jìn)的,添加新的修改舊的功能,不斷變化的用戶需求意味著一個(gè)高效的系統(tǒng)必須能夠迅速擴(kuò)展或收縮資源。為了達(dá)到接近零宕機(jī)的需求,通常在一個(gè)單獨(dú)的數(shù)據(jù)中心或區(qū)域需要自動地將故障轉(zhuǎn)移到預(yù)設(shè)的備份系統(tǒng)。
在此之上,一些大型企業(yè)經(jīng)常會運(yùn)行多個(gè)這樣的系統(tǒng)或是偶爾需要運(yùn)行一些獨(dú)立于主系統(tǒng)的任務(wù)比如數(shù)據(jù)挖掘,但又需要現(xiàn)存系統(tǒng)內(nèi)更多資源或通訊交互。
當(dāng)使用多個(gè)資源時(shí),重要的是確保他們得到有效地使用而不被閑置,但是還可以應(yīng)對需求高峰。成本效益與迅速擴(kuò)展的規(guī)模之前的權(quán)衡是困難的任務(wù),但是可以用各種方式加以處理。
所有這一切都意味著一個(gè)非凡系統(tǒng)的運(yùn)行充滿了各種管理任務(wù)、挑戰(zhàn)以及不應(yīng)低估的復(fù)雜性。很快在個(gè)體層面一個(gè)接一個(gè)地修補(bǔ)和更新某個(gè)機(jī)器將變?yōu)椴豢赡?,他們必須同等對待。?dāng)一臺機(jī)器發(fā)生問題時(shí),它應(yīng)該被摧毀并更換,而不是調(diào)養(yǎng)修復(fù)后再上線。
當(dāng)前有各種工具和解決方案能夠幫助解決這些挑戰(zhàn),這里主要集中講解幾個(gè)編排工具,這些工具能幫助我們以集群方式在主機(jī)上啟動容器,并能夠彼此連接,同時(shí)也考慮到了擴(kuò)展性和自動故障轉(zhuǎn)移的重要特性。
Swarm
Swarm是Docker的原生集群工具,Swarm使用標(biāo)準(zhǔn)的Docker API,這意味著容器能夠使用docker run命令啟動,Swarm會選擇合適的主機(jī)來運(yùn)行容器,這也意味著其他使用Docker API的工具比如Compose和bespoke腳本也能使用Swarm,從而利用集群而不是在單個(gè)主機(jī)上運(yùn)行。
Swarm的基本架構(gòu)很簡單:每個(gè)主機(jī)運(yùn)行一個(gè)Swarm代理,一個(gè)主機(jī)運(yùn)行Swarm管理器(在測試的集群中,這個(gè)主機(jī)也可以運(yùn)行代理),這個(gè)管理器負(fù)責(zé)主機(jī)上容器的編排和調(diào)度。Swarm能以高可用性模式(etcd、Consul 或ZooKeeper 中任何一個(gè)都可以用來將故障轉(zhuǎn)移給后備管理器處理)運(yùn)行。當(dāng)有新主機(jī)加入到集群,有幾種不同的方式來發(fā)現(xiàn)新加的主機(jī),在Swarm中也就是discovery。默認(rèn)情況下使用的是token,也就是在Docker Hub上會儲存一個(gè)主機(jī)地址的列表。
Fleet
Fleet是一個(gè)來自CoreOS的集群管理工具,自詡為“底層的集群引擎”,也就意味著它有望形成一個(gè)“基礎(chǔ)層”的更高級別的解決方案,如Kubernetes。
Fleet最顯著的特點(diǎn)是基于systemd(systemd提供單個(gè)機(jī)器的系統(tǒng)和服務(wù)初始化)建立的,F(xiàn)leet將其擴(kuò)展到集群上,F(xiàn)leet能夠讀取systemd單元文件,然后調(diào)度單個(gè)機(jī)器或集群。
每個(gè)機(jī)器運(yùn)行一個(gè)引擎和一個(gè)代理,任何時(shí)候在集群中只激活一個(gè)引擎,但是所有代理會一直運(yùn)行,Systemd單元文件被提交給引擎,然后在 least-loaded機(jī)器上調(diào)度任務(wù),單元文件會簡單運(yùn)行一個(gè)容器,代理會啟動單元和報(bào)告狀態(tài),Etcd用來激活機(jī)器間的通訊以及存儲集群和單元的狀態(tài)。
這個(gè)架構(gòu)用來設(shè)計(jì)容錯的,如果一個(gè)機(jī)器宕機(jī)了,這個(gè)機(jī)器上的所有單元會在新的主機(jī)上被重新啟動。
Fleet支持各種調(diào)度提示與約束。在最基本的層面,單元的調(diào)度可以是全局的:一個(gè)實(shí)例將在所有機(jī)器上運(yùn)行,或者作為一個(gè)單獨(dú)的單元運(yùn)行在一臺機(jī)器上。全局調(diào)度對于如日志和監(jiān)控容器任務(wù)非常實(shí)用。支持各種關(guān)聯(lián)類型約束,因此,例如規(guī)定在應(yīng)用服務(wù)器上運(yùn)行健康檢查的容器。元數(shù)據(jù)也可以連接到主機(jī)用于調(diào)度,所以你可以讓你的容器在某一區(qū)域或某些硬件設(shè)備上運(yùn)行。
由于Fleet是基于systemd的,它也支持socket activation概念;容器可以綁定到一個(gè)給定端口的連接響應(yīng)上。這樣做的主要優(yōu)點(diǎn)是進(jìn)程可以即時(shí)創(chuàng)建而不是閑置等待某些任務(wù)。有可能涉及到sockets管理的其他好處,如容器重啟的消息不丟失。
Kubernetes
Kubernetes是一個(gè)由google基于他們上個(gè)世紀(jì)容器產(chǎn)品化的經(jīng)驗(yàn)而推出的容器編排工具,Kubernetes有些固執(zhí)己見對于容器如何組織和網(wǎng)絡(luò)強(qiáng)制了一些概念,你需要了解的主要概念有:
Pods – Pods是容器一起部署與調(diào)度的群體。Pods與其他系統(tǒng)的單一容器相比,它組成了Kubernetes中調(diào)度的原子單元。Pod通常會包括1-5個(gè)一起提供服務(wù)的容器。除了這些用戶容器,Kubernetes還會運(yùn)行其他容器來提供日志和監(jiān)控服務(wù)。在Kubernetes中Pods壽命短暫;隨著系統(tǒng)的進(jìn)化他們不斷地構(gòu)建和銷毀。
Flat Networking Space – Kubernetes的網(wǎng)絡(luò)是跟默認(rèn)的Docker網(wǎng)絡(luò)不同。在默認(rèn)Docker網(wǎng)絡(luò)中, 容器存在于一個(gè)私有子網(wǎng)絡(luò)中,它需要賺翻主機(jī)上的端口或者使用代理才能與其他主機(jī)上的容器通訊。在Kubernetes,pod中的容器會分享一個(gè)IP地址,但是該地址空間跟所有的pods是“平”的,這意味著所有pods不用任何網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)就可以互相通訊。這就使得多主機(jī)群集更容易管理,不支持鏈接的代價(jià)使得建立單臺主機(jī)(更準(zhǔn)確地說是單個(gè)pod)網(wǎng)絡(luò)更為棘手。由于在同一個(gè)pod中的容器共享一個(gè)IP,它們可以通過使用本地主機(jī)地址端口進(jìn)行通信(這并不意味著你需要協(xié)調(diào)pod內(nèi)的端口使用)。
Labels – Labels是附在Kubernetes對象(主要是pods)上用于描述對象的識別特征的鍵值對,例如版本:開發(fā)與層級:前端。通常Labels不是唯一的;它們用來識別容器組。Labels選擇器可以用來識別對象或?qū)ο蠼M,例如設(shè)置所有在前端層的pods與環(huán)境設(shè)置為production。使用Labels可以很容易地處理分組任務(wù),例如分配pods到負(fù)載均衡組或者在組織之間移動pods。
Services – Services是通過名稱來定位的穩(wěn)定的節(jié)點(diǎn)。Services使用label選擇器來連接pods,比如“緩存”Service可以連接到標(biāo)識為 label選擇器“type”為“redis”的某些“redis”pods。該service將在這些pods之間自動循環(huán)地請求。以這種方式,Services可用于連接一個(gè)系統(tǒng)各部件。使用Services會提供一個(gè)抽象層,這意味著應(yīng)用程序并不需要知道他們調(diào)用的service的內(nèi)部細(xì)節(jié),例如pods內(nèi)部運(yùn)行的應(yīng)用程序只需要知道調(diào)用的數(shù)據(jù)庫service的名稱和接口,它不必關(guān)心有多少pods組成了那個(gè)數(shù)據(jù)庫,或者上次它調(diào)用了哪個(gè)pod。 Kubernetes會為集群建立一個(gè)DNS服務(wù)器,用于監(jiān)視新的services并允許他們在應(yīng)用程序代碼和配置文件中按名稱定位。
它也可以設(shè)置services不指向pods而是指向其他已經(jīng)存在的services,比如外部API或數(shù)據(jù)庫。
Replication Controllers - Replication controllers是Kubernetes實(shí)例化pods的正常方式(通常情況下,在Kubernetes中不使用Docker CLI)。它們?yōu)閟ervice來控制和監(jiān)視運(yùn)行的pods數(shù)量(稱為replicas)。例如,一個(gè)replication controller可以負(fù)責(zé)維持5個(gè)Redis的pods的運(yùn)行。如果一個(gè)失敗,它會立即啟動一個(gè)新的。如果replicas的數(shù)量減少,它會停止多余的pods。雖然使用Replication Controllers來實(shí)例化所有pods會增加一層額外的配置,但是它顯著提高容錯性和可靠性。
Mesos 和 Marathon
Apache Mesos是一個(gè)開源的集群管理器。它是為涉及數(shù)百或數(shù)千臺主機(jī)的大規(guī)模集群而設(shè)計(jì)的。 Mesos支持在多租戶間分發(fā)工作負(fù)載,一個(gè)用戶的Docker容器運(yùn)行緊接著另一個(gè)用戶的Hadoop任務(wù)。
Apache Mesos始于加州大學(xué)伯克利分校的一個(gè)項(xiàng)目,用來驅(qū)動Twitter的底層基礎(chǔ)架構(gòu),并且成為許多大公司如eBay和Airbnb的重要工具。后來 Mesosphere(共同創(chuàng)辦人之一:Ben Hindman - Mesos原始開發(fā)人員 )做了很多持續(xù)性的Mesos開發(fā)和支持工具(如Marathon)。
Mesos的體系結(jié)構(gòu)是圍繞高可用性和彈性而設(shè)計(jì)的。在一個(gè)Mesos群集的主要組成部分是:
Mesos Agent Nodes - 負(fù)責(zé)實(shí)際的運(yùn)行任務(wù)。所有代理向Master提交其可用資源。通常會有數(shù)十到上千的節(jié)點(diǎn)。
Mesos Master - 負(fù)責(zé)給Agents發(fā)送任務(wù)。它維護(hù)一個(gè)現(xiàn)有資源的列表并且將此“提供”給Frameworks。Master基于分配策略來決定提供多少資源。通常會有2個(gè)或4個(gè)備用Master來接替故障的Master。
ZooKeeper - 用于選擇和查找當(dāng)前Master地址。通常情況下會運(yùn)行3個(gè)或5個(gè)ZooKeeper實(shí)例以確??捎眯院凸收咸幚?。
Frameworks - 與Master協(xié)調(diào)調(diào)度任務(wù)到Agent節(jié)點(diǎn)。Frameworks由兩部分組成:executor進(jìn)程會運(yùn)行代理并維護(hù)運(yùn)行的任務(wù)以及那些已注冊的寄存器,還可以選擇使用那些基于來自主機(jī)提供的資源。Mesos集群為不同種類的任務(wù)可以運(yùn)行多種Frameworks。用戶希望與frameworks交互來提交任務(wù)而不是和Mesos交互。
上圖中我們可以看到Mesos集群使用framework作為調(diào)度器。Marathon調(diào)度器使用ZooKeeper來定位當(dāng)前要提交任務(wù)的Mesos master。無論是Marathon調(diào)度器還是Mesos master都有備用以便當(dāng)前master不可用的時(shí)候使用。
通常情況下,ZooKeeper,作為Mesos master以及備用,它會運(yùn)行在同一臺主機(jī)上。在一個(gè)小的集群中,這些主機(jī)也可以運(yùn)行代理,但是更大的集群做這些就不可行,因?yàn)樗鼈冃枰cmaster通信。Marathon也可以運(yùn)行在同一個(gè)主機(jī)上,或者運(yùn)行在存在于網(wǎng)絡(luò)邊界的獨(dú)立主機(jī)上,而且還可以為客戶端形成接入點(diǎn),從而保持客戶端與Mesos集群分離。
Marathon(來自 Mesosphere)是為開啟、監(jiān)控以及擴(kuò)展長期運(yùn)行應(yīng)用程序規(guī)模而設(shè)計(jì)的。Marathon啟動應(yīng)用程序的設(shè)計(jì)是靈活的,它甚至可以啟動其他互補(bǔ)的 frameworks,如Chronos(數(shù)據(jù)中心的“cron”)??梢赃x擇使用framework來運(yùn)行Docker容器,Marathon直接支持這樣做。就像我們見過的其他編排架構(gòu),Marathon支持各種親和與約束規(guī)則??蛻舳送ㄟ^REST API與Marathon交互。其他功能還包括支持健康檢查以及可用于與負(fù)載平衡器或分析指標(biāo)交互的事件流。
結(jié)論
編排、集群以及管理容器顯然有多種選擇。話雖如此,但這些選擇一般都是高度分化的。在編排方面,我們可以說:
Swarm具有使用標(biāo)準(zhǔn)Docker接口的優(yōu)勢(及劣勢)。雖然這樣使得它與現(xiàn)有的工作流程交互起來簡單易用,但也可能對于支持更為復(fù)雜的定義在定制接口的調(diào)度變得更加困難。
Fleet是底層級的而且相當(dāng)簡單的編排層,它被于運(yùn)行更高級別的編排工具,例如Kubernetes或者自定義系統(tǒng)。
Kubernetes是帶有服務(wù)發(fā)現(xiàn)和復(fù)制的編排工具。它可能需要重新設(shè)計(jì)一些現(xiàn)有的應(yīng)用程序,但是正確地使用可以提供一個(gè)可容錯和可擴(kuò)展的系統(tǒng)。
Mesos 是一種底層級、久經(jīng)沙場的調(diào)度器,對于容器的編排,它支持多種frameworks,包括Marathon、Kubernetes、和Swarm。在寫這篇文章的時(shí)候,Kubernetes和Mesos比Swarm開發(fā)的更多以及更為穩(wěn)定。在規(guī)模上,只有Mesos已經(jīng)證明了支持成百上千個(gè)節(jié)點(diǎn)的大型系統(tǒng)。但是,對于小的集群比方說,還不到十幾個(gè)節(jié)點(diǎn)的集群,用Mesos可能過于復(fù)雜。