首先我們的問(wèn)題是:產(chǎn)品包含了大量的服務(wù)孵睬,并且服務(wù)之間存在復(fù)雜的依賴(lài)關(guān)系标捺,以拓?fù)涞男问竭\(yùn)行并相互協(xié)作炫欺,部署的時(shí)候需要手動(dòng)解決整體的依賴(lài)乎完,配制通信的協(xié)議和地址,重新部署新環(huán)境復(fù)雜度非常高品洛。因此树姨,我們希望有一種容器技術(shù)可以讓我們構(gòu)建產(chǎn)品所需要的所有的服務(wù)能夠迅速快捷的重新部署,并且可以根據(jù)需求橫向的擴(kuò)展桥状,且保證高可用性帽揪,在出現(xiàn)問(wèn)題的時(shí)候可以自動(dòng)重啟或者啟動(dòng)備份服務(wù)。
目前有多種解決方案辅斟,考慮我們有私有云台丛,亞馬遜云以及物理機(jī)的幾種部署方式,所以Docker作為解決方案的基礎(chǔ),在其之上選擇合適的容器拓?fù)涔芾砉ぞ呔统闪酥饕蝿?wù)挽霉,常見(jiàn)的解決方案有:
- Fleet防嗡,最早CoreOS集成的解決方案,基于Systemd管理操作系統(tǒng)上的容器侠坎,通過(guò)Systemd描述文件來(lái)表達(dá)容器之間啟動(dòng)的依賴(lài)關(guān)系蚁趁,并且擴(kuò)展支持Global, Single等類(lèi)型的啟動(dòng)方式,跟系統(tǒng)契合的非常好实胸,使用簡(jiǎn)單他嫡,處于比較高的應(yīng)用級(jí)別,由于現(xiàn)在CoreOS跟Docker目前處于比較尷尬的關(guān)系庐完,各自都想獨(dú)立形成自己完整的生態(tài)系統(tǒng)钢属,對(duì)其發(fā)展前景不是非常樂(lè)觀;
- Kubernetes门躯,Google根據(jù)自身很多年的容器部署經(jīng)驗(yàn)所開(kāi)源的容器管理解決方案淆党,具有服務(wù)、節(jié)點(diǎn)讶凉、Pod等一系列不同層級(jí)的概念劃分染乌,通過(guò)自身的DNS服務(wù)發(fā)現(xiàn)可以實(shí)現(xiàn)很復(fù)雜的服務(wù)編排部署,對(duì)Docker兼容不錯(cuò)懂讯,不過(guò)略復(fù)雜些荷憋。
- Mesos+Marathon,Mesos是一個(gè)通用的資源管理調(diào)度框架褐望,目前比較成熟的應(yīng)用可以外接各種常用的計(jì)算框架勒庄,比如Hadoop MR, Storm, Spark等瘫里, Docker container作為一種long running的Framework也可以很自然的被Mesos所托管实蔽,Marathon作為Mesos之上的一種Scheduler比較擅長(zhǎng)管理Docker這種長(zhǎng)時(shí)間運(yùn)行的“計(jì)算框架”,因此經(jīng)常與Mesos綁定在一起作為Docker服務(wù)生產(chǎn)環(huán)境部署的解決方案討論减宣。
- Machine+Swarm+Compose盐须, Docker官方提供的工具組合玩荠,特點(diǎn)就是與Docker engine的結(jié)合非常好漆腌,可以說(shuō)能夠無(wú)縫的替換原來(lái)Docker engine所使用的地方,最終所形成的容器集合可以作為單一的Docker容器來(lái)使用阶冈,從不同層面上實(shí)現(xiàn)了使用方法和調(diào)用的統(tǒng)一闷尿,缺點(diǎn)就是還不夠成熟。
多種解決方案中我們優(yōu)先選擇官方提供的工具女坑,一般來(lái)說(shuō)官方提供的工具跟自己的原生服務(wù)結(jié)合的更好填具,也具有更長(zhǎng)遠(yuǎn)的規(guī)劃,在官方工具確實(shí)不足的情況下輔助以第三方的工具,因此初步我們決定采用Docker原生的工具M(jìn)achine+Swarm+Compose輔助以Mesos來(lái)實(shí)現(xiàn)整個(gè)工程的部署劳景,其中Swarm負(fù)責(zé)某一功能模塊小規(guī)模的容器分配調(diào)度誉简,Mesos負(fù)責(zé)整個(gè)集群最外層大規(guī)模容器資源調(diào)度,可以說(shuō)以Mesos為主盟广,Swarm為輔助闷串,因?yàn)镸esos是比較成熟的資源管理框架,也有非常適合的調(diào)度引擎筋量,Swarm還相對(duì)初步隨著時(shí)間演進(jìn)烹吵,也許會(huì)接管更多的調(diào)度。
簡(jiǎn)單介紹下Docker官方原生的工具:
- Machine桨武,在一臺(tái)機(jī)器上管理多個(gè)Docker 環(huán)境變量配置肋拔,方便快捷的啟動(dòng)本地或者遠(yuǎn)程的Docker容器,切換環(huán)境變量后呀酸,Docker command可以像在本地執(zhí)行一樣操作遠(yuǎn)程的Docker容器凉蜂,依賴(lài)于其多種多樣的Driver實(shí)現(xiàn),降低了ssh登陸到各個(gè)機(jī)器去執(zhí)行各種命令的復(fù)雜度七咧;
- Swarm跃惫,將多個(gè)Docker host集成在一起作為一個(gè)虛擬的Docker host來(lái)使用,使用方式跟普通的Docker命令相同艾栋,通潮妫可以用來(lái)實(shí)現(xiàn)小規(guī)模容器的負(fù)載均衡以及高可用的服務(wù)備份,其架構(gòu)特點(diǎn)比較直接蝗砾,就是在多臺(tái)機(jī)器上安裝Swarm agent與manager溝通先较,服務(wù)發(fā)現(xiàn)可以采用etcd/zookeeper/consul進(jìn)行服務(wù)注冊(cè)。這樣確實(shí)實(shí)現(xiàn)了容器的分布式部署悼粮,不過(guò)只應(yīng)對(duì)于相對(duì)簡(jiǎn)單的情況闲勺,調(diào)度算法也比較簡(jiǎn)單,適合于實(shí)現(xiàn)相對(duì)結(jié)構(gòu)比較簡(jiǎn)單的Web應(yīng)用扣猫,對(duì)于大規(guī)模的拓?fù)浠蛘叻?wù)編排可能不夠成熟菜循;
- Compose,通過(guò)編寫(xiě)yaml格式的服務(wù)組織編排文件申尤,我們可以通過(guò)一個(gè)命令來(lái)啟動(dòng)多個(gè)容器并連接在一起作為一個(gè)完整的服務(wù)來(lái)使用癌幕,通常來(lái)說(shuō)面向的是開(kāi)發(fā)和測(cè)試,默認(rèn)多個(gè)容器都是在一個(gè)host啟動(dòng)的昧穿,不能作為生產(chǎn)環(huán)境使用勺远,如果希望compose的服務(wù)可以在生產(chǎn)環(huán)境中使用,可以獨(dú)立于測(cè)試的配置文件新建一個(gè)production.yaml时鸵, 結(jié)合machine和swarm來(lái)管理多個(gè)遠(yuǎn)程host并組織成一個(gè)虛擬的host來(lái)使用胶逢,這樣一個(gè)compose包含的服務(wù)會(huì)部署到實(shí)際不同的機(jī)器,滿(mǎn)足生產(chǎn)的需要。Compose通過(guò)link將不同容器的端口連接在一起初坠,如果服務(wù)運(yùn)行于不同的host和簸,需要給這個(gè)Swarm集群設(shè)置共同的overlay網(wǎng)絡(luò),否則默認(rèn)的bridge網(wǎng)絡(luò)只能在單個(gè)host聯(lián)通碟刺。
關(guān)于Docker網(wǎng)絡(luò)解決方案的爭(zhēng)論比較多了比搭,CoreOS和Kubernetes都有自己的解決方案,前兩者都是比較通用的PAAS工具南誊,作為通用性的服務(wù)編排工具容器的具體實(shí)現(xiàn)可以是多種身诺,Docker只是其中之一,而Docker libnetwork的解決方案過(guò)于底層抄囚,不適合作為通用的插件集成到Kubernetes或者CoreOS中霉赡,因此這兩家都有自己CNI類(lèi)型的解決方案,對(duì)于使用者來(lái)說(shuō)我們不那么關(guān)心到底這個(gè)工具支持多少種容器幔托,只需要知道Docker這種容器能夠滿(mǎn)足當(dāng)前產(chǎn)品部署的需求就好穴亏,因此我們?nèi)匀灰訢ocker的工具為主,盡管不那么通用重挑,但是能夠解決我們目前服務(wù)編排的問(wèn)題嗓化。
官方的工具看起來(lái)很美好,解決方案也足夠優(yōu)雅和簡(jiǎn)潔谬哀,問(wèn)題就是成熟程度刺覆,compose和swarm的結(jié)合仍然是在試驗(yàn)階段,對(duì)于處于不同host的container史煎,進(jìn)行l(wèi)ink仍然需要手動(dòng)對(duì)整個(gè)Swarm集群設(shè)置網(wǎng)絡(luò)谦屑,對(duì)于大規(guī)模或者復(fù)雜拓?fù)涞牟渴鸸ぷ髁坎恍∑螅虼宋覀兘柚贛esos來(lái)做第一級(jí)的資源或者容器管理氢橙,其中第二級(jí)或者說(shuō)小規(guī)模容器部署是可以在swarm中實(shí)現(xiàn)。
Mesos作為資深的資源管理平臺(tái)恬偷,在Docker出現(xiàn)之前就已經(jīng)被廣泛利用了悍手,基本上所有的主從類(lèi)型的分布式計(jì)算框架都支持使用Mesos來(lái)做基本的資源分配調(diào)度,比如hadoop, storm袍患,spark等等坦康,同時(shí)Mesos的設(shè)計(jì)也可允許長(zhǎng)時(shí)間運(yùn)行的application, 不管是batch job, stream job還是普通的應(yīng)用服務(wù)都可以接入Mesos來(lái)申請(qǐng)資源啟動(dòng)自身的容器协怒。早期Mesos只支持LXC形式的資源限制涝焙,在Docker崛起之后Mesos也開(kāi)始支持直接使用Docker容器來(lái)運(yùn)行具體的計(jì)算框架卑笨,可以說(shuō)二者既有競(jìng)爭(zhēng)又相輔相成孕暇。說(shuō)競(jìng)爭(zhēng)是因?yàn)槟壳癉ocker自己的工具已經(jīng)慢慢的可以替代一部分Mesos的應(yīng)用場(chǎng)景了,只要機(jī)器上安裝了Docker engine就可以無(wú)差別的管理所有主機(jī),比如Swarm就可以組建簡(jiǎn)單的服務(wù)集群妖滔,管理容器在集群中的運(yùn)行隧哮,同時(shí)也能夠利用Machine來(lái)進(jìn)行遠(yuǎn)程管理,說(shuō)相輔是因?yàn)镾warm的設(shè)計(jì)是可以替換具體的調(diào)度后端的座舍,默認(rèn)情況使用自己的調(diào)度器在服務(wù)發(fā)現(xiàn)的基礎(chǔ)上選擇一個(gè)host來(lái)啟動(dòng)容器沮翔,通過(guò)配置可以選擇Mesos作為其調(diào)度后端,將Swarm 作為跟Spark同等的Compute Framework來(lái)運(yùn)行曲秉,這樣Swarm就能夠使用Mesos更加成熟和靈活的調(diào)度機(jī)制來(lái)管理容器采蚀,在此之上Compose就可以把編排好的服務(wù)運(yùn)行在Mesos集群,可見(jiàn)Mesos和Docker結(jié)合的生態(tài)系統(tǒng)在當(dāng)前階段是比較和諧的承二。
這樣榆鼠,最終我們的解決方案就基本確定了,Mesos作為最基礎(chǔ)的集群資源管理或者調(diào)度工具運(yùn)行在所有的服務(wù)器上亥鸠,Spark等計(jì)算框架不再獨(dú)立部署妆够,而是使用Mesos最初的LXC容器來(lái)運(yùn)行,Swarm使用Docker容器通過(guò)Mesos來(lái)調(diào)度负蚊,Compose文件用來(lái)啟動(dòng)結(jié)合比較緊密服務(wù)堆棧神妹,比如Tachyon集群,我們自己所開(kāi)發(fā)的應(yīng)用服務(wù)以及ACO集群也作為一個(gè)Docker服務(wù)堆棧在Swarm上運(yùn)行家妆。所以我們的Mesos集群上目前運(yùn)行兩種計(jì)算框架鸵荠,Spark和Swarm,負(fù)責(zé)我們的應(yīng)用和分布式計(jì)算的部署伤极,具體的應(yīng)用和服務(wù)編排都是在Compose中完成腰鬼,個(gè)別復(fù)雜的應(yīng)用需要手動(dòng)去處理關(guān)聯(lián)關(guān)系,依然是以Docker的形式運(yùn)行在Mesos中塑荒。
Mesos可以把我們的機(jī)器聚合在一起作為一個(gè)機(jī)器來(lái)使用熄赡,不管是我們的應(yīng)用還是分布式計(jì)算的任務(wù),都直接提交給Mesos來(lái)進(jìn)行調(diào)度齿税,減少了對(duì)服務(wù)器的垂直劃分彼硫,不存在Spark的集群, Hadoop的集群等概念凌箕,Spark或者Hadoop的job直接在Mesos的slave中分配資源并運(yùn)行各自job相關(guān)的Executor, 運(yùn)行結(jié)束后釋放資源拧篮,就像Spark沒(méi)有存在過(guò)一樣, 因此從更高的角度看Mesos的Framework其實(shí)就是一個(gè)調(diào)度器加一個(gè)運(yùn)行時(shí)的處理流程牵舱,不用再需要Spark或者Storm等框架的Standalone 模式自己來(lái)處理調(diào)度串绩,只需要使用Mesos的API,實(shí)現(xiàn)自己的scheduler和具體啟動(dòng)停止運(yùn)行過(guò)程的Executor就好芜壁, 而對(duì)于我們自己的應(yīng)用如果要作為Framework存在也需要實(shí)現(xiàn)對(duì)應(yīng)的Scheduler和Executor礁凡, 不過(guò)可以利用現(xiàn)成的比較好的調(diào)度器比如Marathon來(lái)托管我們的應(yīng)用高氮,減少開(kāi)發(fā)Framework的工作量。使用Mesos這樣的好處是資源的利用率更高顷牌, 因此我們?cè)谝膊恍枰薓esos之外的long running 集群剪芍, 即使有Long running的服務(wù),也是在Mesos分配好的容器內(nèi)運(yùn)行窟蓝。
Framework = Scheduler + Executor
Mesos的安裝過(guò)程稍微有點(diǎn)服務(wù)罪裹,雖然Docker鏡像可以減少M(fèi)esos的部署復(fù)雜度,但是這樣就存在了兩層容器运挫, Mesos在Docker 容器中運(yùn)行状共,而Mesos里邊的任務(wù)也是在自己的Docker容器里運(yùn)行,如果有些長(zhǎng)時(shí)間運(yùn)行的任務(wù)需要暴露出端口跟外界交互谁帕,就需要先Expose port到Mesos slave級(jí)別的容器口芍, 然后再Expose到最外層的物理機(jī),復(fù)雜度增加且對(duì)性能有損耗雇卷,因此我們最終還是傾向于在物理機(jī)上部署Mesos鬓椭, 只保留一層Docker容器不推薦嵌套,而且有了Mesosphere的DCOS系統(tǒng)关划,在AWS上部署Mesos就比較簡(jiǎn)單了小染。
Mesos看起來(lái)很完美,那我們?yōu)槭裁催€需要Docker容器呢贮折, 直接使用LXC標(biāo)準(zhǔn)Linux kernel支持的容器不就可以了裤翩,在這個(gè)解決方案中我們期望所有運(yùn)行的應(yīng)用或者分布式計(jì)算框架的任務(wù)的Executor都是在Docker容器中運(yùn)行,也是因?yàn)镈ocker殺手級(jí)的功能调榄,一個(gè)Docker容器就像一個(gè)集裝箱踊赠,里邊包含了需要運(yùn)行一個(gè)服務(wù)或者任務(wù)的所有的依賴(lài)條件或者配置,都可以根據(jù)需求自身靈活的修改每庆,并且一次裝箱隨處運(yùn)行筐带,不用關(guān)心外在環(huán)境,舉個(gè)例子假如直接使用LXC來(lái)運(yùn)行Spark的某個(gè)任務(wù)的Executor缤灵,需要提供Spark jar包的地址伦籍,相關(guān)的配置集成到ExecutorInfo中才能運(yùn)行,而如果使用Docker container就簡(jiǎn)單很多腮出,Spark executor運(yùn)行需要的信息都在某個(gè)Docker image中帖鸦,Mesos slave只要調(diào)用Docker client啟動(dòng)某個(gè)鏡像就足以運(yùn)行一個(gè)Framework的某個(gè)任務(wù),任務(wù)的執(zhí)行在Docker 容器中胚嘲。對(duì)于我們自己開(kāi)發(fā)的各種服務(wù)同理也是組織成鏡像最終在Docker容器中運(yùn)行作儿, Scheduler依賴(lài)Marathon就可以。