概述
杏仁的容器化平臺(tái)基于Mesos和Marathon構(gòu)建,使用Calico提供容器的多主機(jī)網(wǎng)絡(luò),并通過(guò)Consul進(jìn)行服務(wù)的注冊(cè)和發(fā)現(xiàn)。
之所以選擇這套方案,是考慮到成本和可控性。由于使用的組件都是開(kāi)源項(xiàng)目,幾乎不需要二次開(kāi)發(fā),另外,每項(xiàng)功能都由不同組件提供,可以進(jìn)行很細(xì)粒度的控制。
總體架構(gòu)參見(jiàn)下圖:
資源分配
Docker本身提供了資源使用的管控,啟動(dòng)容器時(shí)可以指定CPU和內(nèi)存的限制,但在大規(guī)模多主機(jī)的環(huán)境中,需要一種更加高效、集成的資源管理方式。而分布式資源管理框架Mesos,經(jīng)過(guò)了Facebook、Twitter這些大型公司的萬(wàn)臺(tái)主機(jī)驗(yàn)證,無(wú)疑是一個(gè)很好的選擇。
Mesos實(shí)現(xiàn)了兩級(jí)調(diào)度架構(gòu),可以管理多種類(lèi)型的應(yīng)用程序,支持Docker。第一級(jí)調(diào)度是Master的守護(hù)進(jìn)程,管理Mesos集群中所有節(jié)點(diǎn)上運(yùn)行的Slave守護(hù)進(jìn)程。集群由物理服務(wù)器或虛擬服務(wù)器組成,用于運(yùn)行應(yīng)用程序的任務(wù),比如Hadoop和MPI作業(yè)。第二級(jí)調(diào)度由被稱(chēng)作Framework的“組件”組成。Framework包括調(diào)度器(Scheduler)和執(zhí)行器(Executor)進(jìn)程,其中每個(gè)節(jié)點(diǎn)上都會(huì)運(yùn)行執(zhí)行器。Mesos能和不同類(lèi)型的Framework通信,每種Framework由相應(yīng)的應(yīng)用集群管理。圖中只展示了Hadoop和MPI兩種類(lèi)型,其它類(lèi)型的應(yīng)用程序也有相應(yīng)的Framework。
Mesos Master協(xié)調(diào)全部的Slave,并確定每個(gè)節(jié)點(diǎn)的可用資源,然后向注冊(cè)到Master的Framework(作為Master的客戶(hù)端)發(fā)出resource offer。Framework可以根據(jù)應(yīng)用程序的需求,選擇接受或拒絕來(lái)自master的resource offer。一旦接受邀約,Master會(huì)協(xié)調(diào)Framework和Slave去運(yùn)行應(yīng)用,因此,Mesos可以將Hadoop、Cassandra等多個(gè)任務(wù)同時(shí)運(yùn)行在同一個(gè)節(jié)點(diǎn)。
通過(guò)下面的實(shí)例可以進(jìn)一步理解Mesos的資源分配:
- 各個(gè)Slave收集本機(jī)可用的CPU、內(nèi)存、磁盤(pán)資源,匯集到Master.
- Master將各個(gè)Slave收集的資源作為resource offer提供給Framework(Marathon).
- Marathon會(huì)選擇一個(gè)resource offer, 并將一個(gè)需要2核cpu、512M內(nèi)存和5GB磁盤(pán)的任務(wù)提交給Master.
- Master將該任務(wù)分配給slave,后者通過(guò)Executor運(yùn)行任務(wù).
- Master繼續(xù)將可用的資源作為resource offer提供給其它Framework,重復(fù)上面的步驟.
調(diào)度
在容器調(diào)度方面,我們選擇了Marathon。Marathon 是可以和 Mesos 一起協(xié)作的一個(gè) framework,用來(lái)運(yùn)行持久性的應(yīng)用,比如docker。用戶(hù)可以通過(guò)WEB UI和API將應(yīng)用發(fā)布到mesos集群中。
Marathon主要有以下特性:
- 高可用
- 支持多種容器技術(shù)
Mesos containers 和 Docker
- 資源控制,控制容器運(yùn)行在特定機(jī)器上
- 應(yīng)用擴(kuò)展和故障恢復(fù)
比如我們啟動(dòng)三個(gè)服務(wù),分別是一個(gè)節(jié)點(diǎn)的,三個(gè)節(jié)點(diǎn)的和五個(gè)節(jié)點(diǎn)的。我們想拓展這些服務(wù)的話,可以調(diào)用Marathon的API進(jìn)行擴(kuò)展,并且是秒級(jí)的。如果有一臺(tái)主機(jī)宕掉了, Marathon會(huì)均勻地把服務(wù)遷移到其他的機(jī)器上,選擇資源有空余的機(jī)器進(jìn)行遷移。這樣能就保證服務(wù)是動(dòng)態(tài)的調(diào)度,保證服務(wù)的高可用,并且這些都是它內(nèi)部自行處理的,不需要手動(dòng)干預(yù)。
- 提供健康檢查
支持Http,Tcp和自定義腳本測(cè)活
- 提供Web UI
- 提供API
界面如下:
網(wǎng)絡(luò)
在測(cè)試環(huán)境中docker一般通過(guò)映射主機(jī)端口來(lái)提供網(wǎng)絡(luò)功能,但在生產(chǎn)環(huán)境,考慮到性能和兼容性問(wèn)題(有的應(yīng)用需要獨(dú)享IP),1容器1 IP的方案必不可少。
目前Docker的網(wǎng)絡(luò)方案主要分為隧道和路由兩大類(lèi),通過(guò)不同的實(shí)現(xiàn)方式。
隧道
通過(guò)隧道,或者說(shuō)Overlay Networking的方式:
- Weave:UDP廣播,本機(jī)建立新的BR,通過(guò)PCAP互通。
- Open vSwitch(OVS):基于VxLAN和GRE協(xié)議,但是性能方面損失比較嚴(yán)重。
- Flannel:UDP廣播,VxLan。
隧道方案在IaaS層的網(wǎng)絡(luò)中應(yīng)用也比較多,大家共識(shí)是隨著節(jié)點(diǎn)規(guī)模的增長(zhǎng)復(fù)雜度會(huì)提升,而且出了網(wǎng)絡(luò)問(wèn)題跟蹤起來(lái)比較麻煩,大規(guī)模集群情況下這是需要考慮的一個(gè)點(diǎn)。
路由
比較典型的代表有:
- Calico:基于BGP協(xié)議的路由方案,支持很細(xì)致的ACL控制,對(duì)混合云親和度比較高。
- Macvlan:從邏輯和Kernel層來(lái)看隔離性和性能最優(yōu)的方案,基于二層隔離,所以需要二層路由器支持,大多數(shù)云服務(wù)商不支持,所以混合云上比較難以實(shí)現(xiàn)。
最終,考慮到性能和集成成本,我們選擇了Calico。
服務(wù)發(fā)現(xiàn)和負(fù)載
Marathon支持多種服務(wù)發(fā)現(xiàn)和負(fù)載方式:
- Mesos-DNS 通過(guò)Dns實(shí)現(xiàn)服務(wù)的發(fā)現(xiàn)
- Marathon-lb 使用Haproxy提供基于端口的服務(wù)發(fā)現(xiàn)
- haproxy-marathon-bridge (不推薦) 通過(guò)腳本將marathon中的服務(wù)信息更新到Haproxy。
在測(cè)試環(huán)境,考慮到易用性,我們使用Marathon-lb進(jìn)行服務(wù)注冊(cè)和負(fù)載,前端的nginx將請(qǐng)求二次轉(zhuǎn)發(fā)到haproxy的固定端口。
在生產(chǎn)環(huán)境中,為減少二次轉(zhuǎn)發(fā)的開(kāi)銷(xiāo)并兼容服務(wù)化使用的consul注冊(cè)方式,我們使用Registrator將應(yīng)用注冊(cè)到Consul,再通過(guò)consul-template將應(yīng)用的訪問(wèn)地址動(dòng)態(tài)寫(xiě)入到nginx,并由nginx提供負(fù)載功能。
遇到的問(wèn)題
- Registrator無(wú)法注冊(cè)
Registrator的latest版本鏡像無(wú)法注冊(cè)(很久沒(méi)更新了),需要使用master版本
- Marathon和Consul的測(cè)活間隔問(wèn)題
Marathon和Consul都有自己的測(cè)活配置,如果Consul的測(cè)活間隔大于Marathon的測(cè)活間隔,會(huì)導(dǎo)致應(yīng)用發(fā)布期間可能出現(xiàn)服務(wù)不可用。Marathon發(fā)布期間會(huì)保證整個(gè)過(guò)程灰度,但Registrator只要檢測(cè)到容器啟動(dòng)就會(huì)注冊(cè)到Consul,此時(shí)Consul中的應(yīng)用會(huì)同時(shí)存在可用和不可用的服務(wù)實(shí)例(不可用的實(shí)例不會(huì)加入nginx負(fù)載),但當(dāng)Marathon完成應(yīng)用測(cè)活后會(huì)立即殺掉老的應(yīng)用,這時(shí)Consul中不可用的服務(wù)器還沒(méi)有完成測(cè)活,但可用的服務(wù)已經(jīng)被殺掉,整個(gè)服務(wù)就處于不可用狀態(tài),reload nginx時(shí)因?yàn)闆](méi)有可用的upstream server會(huì)報(bào)錯(cuò)。所以一定要保證Consul的測(cè)活間隔小于Marathon的測(cè)活間隔,目前是1比5的測(cè)活間隔。
- 更改Mesos slave的配置后,mesos slave無(wú)法啟動(dòng)
Mesos slave的配置變更后,需要清理掉mesos slave的元數(shù)據(jù),才能啟動(dòng)。具體的命令可以參考slave的log。
參考資料
mesos : http://mesos.apache.org/documentation/latest/
marathon : https://mesosphere.github.io/marathon/docs/
Calico : http://docs.projectcalico.org/v1.6/getting-started/
Registrator : http://gliderlabs.com/registrator/latest/user/quickstart/
Consul : https://www.consul.io/intro/
Consul template : https://github.com/hashicorp/consul-template