標(biāo)簽: 翻譯 虛擬化 rancher
自從Rancher的Beta版本發(fā)布的幾周以來僧叉,平臺新的調(diào)度和服務(wù)發(fā)現(xiàn)的功能讓我略嗨。為了幫助大家理解這些功能是鬼,今天我將展示如何利用這些功能部署一個且實現(xiàn)了HA的Node.js應(yīng)用集群莹捡。我會用Let's Chat作為示例程序,這是一個八錯的開源的聊天工具边篮,有點像Slack。Rancher的首席架構(gòu)師Darren Shepherd在上次的Rancher Meetup上展示了一點Let's Chat奏甫,如果有興趣可以看一下會議記錄戈轿,但是今天我主要介紹的是部署的一些細(xì)節(jié)。Let's Chat 是一個自托管的聊天應(yīng)用阵子,比較適用于小團(tuán)隊思杯,支持很多功能比如:聊天室,通知,警報色乾,XMPP(可擴(kuò)展通訊和表示協(xié)議)聊天誊册,并且還支持多種認(rèn)證方式∨担可以從Let's Chat的github主頁上得到更多的信息案怯。
原文:
http://rancher.com/clustering-a-node-js-application-with-mongo-docker-and-rancher/
Hussein Galal on August 18, 2015
1 應(yīng)用所需組件
Let's Chat正常運行需要以下幾個組件:
- Node.js(0.10+)執(zhí)行應(yīng)用代碼
- MongoDB(2.6+)存儲應(yīng)用數(shù)據(jù)
- Python(2.7.X)支持應(yīng)用中的一些工具
值得慶幸的是,Let's Chat有自己的Docker image(sdelements/lets-chat)了澎办,鏡像中安裝了應(yīng)用所有的依賴并且定義了應(yīng)用所需的環(huán)境變量嘲碱,比如:LCB_DATABASE_URI,用來定義單個或者多個MongoDB服務(wù)的地址局蚀。
部署一個Mongo后端的Let’s Chat超簡單的麦锯,因為已經(jīng)有可用的Docker compose file了。但我們的目的是建立一個高可用的應(yīng)用集群琅绅,這樣可以解決主機(jī)故障(host failure咋翻譯扶欣?感覺是單點故障),所以奉件,我需要起多個MongoDB容器宵蛀,并創(chuàng)建一個副本集備份多個容器的數(shù)據(jù),當(dāng)主服務(wù)節(jié)點掛掉的時候副本集可以指定一個新的節(jié)點作為主服務(wù)節(jié)點县貌。
Let’s Chat使用mongoose驅(qū)動來連接MongoDB服務(wù)器,通過配置凑懂,可以用它連接一個副本集并把數(shù)據(jù)發(fā)送給新的朱服務(wù)節(jié)點煤痕。
2 Rancher環(huán)境
如果還沒有Rancher環(huán)境,不用擔(dān)心接谨,很輕松就可以搞定的摆碉。總的來說脓豪,我們需要用4個機(jī)器來部署:一個用來運行Rancher巷帝,其他三個用來運行應(yīng)用的容器奋隶。
Rancher可以在任何一個linux(Docker 1.6 or later)上運行汪榔。
執(zhí)行命令:
# docker run -d --restart=always -p 8080:8080 rancher/server
Rancher將會花幾分鐘時間啟動,使用的是主機(jī)的8080端口(命令行中指定的)庶诡。一點Rancher啟動并開始運行笤闯,通過“Add Host”按鈕添加其他三個主機(jī)到Rancher堕阔,可以是通過Docker Machine部署所支持的云上的主機(jī),也可以通過“custom”添加本地主機(jī)颗味。( 翻譯的有點糾結(jié)超陆,待改進(jìn)[Once Rancher is up and running, add three new hosts to your environment by clicking the“Add Host” button, and using either the Docker Machine drivers to deploy hosts on one of the supported clouds, or click on “custom” to add any host to your environment.])
只需復(fù)制上圖中Step4的命令復(fù)制粘貼到需要添加的機(jī)器上執(zhí)行即可將主機(jī)注冊到Rancher上。命令中包含了Rancher服務(wù)端的信息以及注冊需要的key浦马,這樣就可以將機(jī)器自動的注冊到Rancher的環(huán)境中了时呀。
另外张漂,也可以通過任何一個自動化工具創(chuàng)建Rancher環(huán)境。我曾經(jīng)創(chuàng)建了一個Ansible roles用來在所有的機(jī)器上安裝Docker并且運行Rancher谨娜,也能實現(xiàn)注冊機(jī)器到Rancher上航攒,有這樣幾個role:
- Docker Role:安裝并配置Docker在Ubuntu 14.04上
- Rancher Role:安裝并啟動Rancher 服務(wù)端
- Rancher Agent:在機(jī)器上運行Rancher agent容器并注冊到Rancher服務(wù)端
可以在playbook中使用這些role來部署Rnacher環(huán)境,最后應(yīng)該有一個3個主機(jī)的環(huán)境(這里應(yīng)該說的是Rancher上注冊了三個主機(jī)[不確定])瞧预。
3 構(gòu)建應(yīng)用集群
環(huán)境準(zhǔn)備好屎债,就可以開始部署應(yīng)用了。在Rancher界面的最上面垢油,點擊”Application”-> 點擊“add stack”盆驹,一個stack就是一組相關(guān)的service的集合,一個service就是執(zhí)行特定功能的容器滩愁,可以在一個或多個主機(jī)上調(diào)度躯喇。
每一個stack定義了服務(wù)發(fā)現(xiàn)的范圍,應(yīng)用可以用來連接不同的service硝枉,比如我們后面就會在一個新的stack中連接Let's Chat與Mongo數(shù)據(jù)庫廉丽。
閱讀Rancher官方文檔可以了解更多service以及其配置信息。我們這次安裝主要包括兩個service:
- MongoDB數(shù)據(jù)庫 service.
- 應(yīng)用程序service.
3.1 部署MongoDB數(shù)據(jù)庫 service
我已經(jīng)修改了Let’s Chat的MongoDB鏡像妻味,使每一個容器都能自動的連接到副本集正压,為了實現(xiàn)這個功能,我寫了一個python的小腳本责球,把它加到了entrypoint.sh里面焦履,在原始的鏡像中,entrypoint.sh負(fù)責(zé)啟動MongoDB服務(wù)雏逾,你可以在Github中找到嘉裤。
這個腳本首先檢測運行MongoDB的容器的IP,然后將其連接到MongoDB主服務(wù)栖博,并把自己加到副本集里面屑宠,如果它發(fā)現(xiàn)MongoDB服務(wù)的數(shù)量小于3個,就不會進(jìn)行連接仇让,因為這表示沒有已經(jīng)啟動的副本典奉。(有點費解……[The script will first detect the IP of the running MongoDB container and then tries to connect to the primary MongoDB server and add itself to the existing replica set, if it finds that less than three MongoDB servers exist it will not initiate a connection because it means that no replication has been started.])
這個鏡像需要一個環(huán)境變量:MONGO_SERVICE_NAME,它的默認(rèn)值是“mongo”妹孙,它的目的是用來查找已經(jīng)啟動的MongoDB容器的IP秋柄,這個功能是由Rancher中的DNS服務(wù)提供的,所有的容器的IP都會被加到DNS服務(wù)中的同一個service名下蠢正。
那我們先從MongoDB service開始骇笔,點擊“Add New Service”進(jìn)入service的配置頁面:
注意,配置頁面中的command中“-replSet letschat”指定了服務(wù)是作為副本集“l(fā)etschat”的一部分,也可以分配一個主機(jī)上的卷笨触,保證數(shù)據(jù)的安全懦傍。
我們想要在每一個主機(jī)上運行一個MongoDB容器,所以在scale里選擇Always run one instance of this containeron every host芦劣,可以使每一個主機(jī)上都運行一個容器粗俱,實現(xiàn)可擴(kuò)展。
現(xiàn)在啟動這個service就可以看到在每一個主機(jī)上都運行了一個容器:
3.2 部署應(yīng)用程序service
現(xiàn)在創(chuàng)建一個運行應(yīng)用程序的service虚吟,也就是在每一個主機(jī)上都運行一個“Let's Chat”容器寸认。我如果用原始的Docker鏡像連接分布式的Mongo后端,就會產(chǎn)生些問題串慰。
問題
第一個問題是當(dāng)應(yīng)用程序的service連接到mongo service偏塞,比如叫“mongo”,會使let’s chat只連接一個MongoDB服務(wù)器邦鲫,但這個服務(wù)器可能不是主服務(wù)幾點灸叼,這種情況下寫入的數(shù)據(jù)沒有備份。
解決辦法
為了解決這個問題我調(diào)整了let's chat容器來執(zhí)行一個python腳本連接Rancher的DNS服務(wù)庆捺,并查找到所有的MongoDB容器古今,然后修改Let’s Chat的環(huán)境變量LCB_DATABASE_URI來添加MongoDB容器的IP列表,現(xiàn)在mongoose驅(qū)動就會將請求重新路由到主服務(wù)器滔以,比如新的LCB_DATABASE_URI:
mongodb://x.x.x.x:27017,y.y.y.y:27017/letschat
會代替原來的:
mongodb://mongo:27017/letschat
需要給腳本提供兩個環(huán)境變量:MONGO_SERVICE_NAME捉腥,提供要搜索的mongo服務(wù)的名字,用來得到所有相關(guān)的容器IP你画;RANCHER_CLUSTER但狭,如果不想原來的Docker鏡像改變可以不使用。
下面開始配置應(yīng)用程序的service:
注意我添加了mongo as a service links撬即,因為一旦一個service鏈接另一個的話,一個DNS記錄就會自動的被映射到每一個容器上呈队,也可以被其他服務(wù)的容器發(fā)現(xiàn)剥槐。
環(huán)境變量的設(shè)置:
想要看到整個service的配置,可以查看自動生成的docker-compose.yml和rancher-compose.yml文件:
docker-compose.yml:
rancher_compose.yml:
3.3 啟動應(yīng)用
我們啟動的第一個service是MongoDB宪摧,啟動后我們需要對MongoDB服務(wù)器間的備份做一些配置:
進(jìn)入到一個mongo服務(wù)器粒竖,然后執(zhí)行下面的命令進(jìn)行初始化:
> config = {
"_id" : "letschat",
"members" : [
{"_id" : 0, "host" : "<private-ip-of-the-1st-container>:27017"},
{"_id" : 1, "host" : "<private-ip-of-the-2nd-container>:27017"},
{"_id" : 2, "host" : "<private-ip-of-the-3rd-container>:27017"}
] }
> rs.initiate(config)
letschat:PRIMARY>
這個步驟不需要每一次我們添加或者移除主機(jī)的時候都做,修改的MongoDB鏡像會處理這個的几于。啟動副本集后蕊苗,我們可以啟動其他的service,可以看到這樣的效果:
現(xiàn)在如果可以查看下每一個主機(jī)上letschat容器的日志就可以看到:
mongodb://10.42.249.151:27017,10.42.236.117:27017,10.42.211.234:27017/letschat
lets-chat@0.4.2 prestart /usr/src/app
migroose
> lets-chat@0.4.2 start /usr/src/app
> node app.js
██╗ ███████╗████████╗███████╗ ██████╗██╗ ██╗ █████╗ ████████╗
██║ ██╔════╝╚══██╔══╝██╔════╝ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝
██║ █████╗ ██║ ███████╗ ██║ ███████║███████║ ██║
██║ ██╔══╝ ██║ ╚════██║ ██║ ██╔══██║██╔══██║ ██║
███████╗███████╗ ██║ ███████║ ╚██████╗██║ ██║██║ ██║ ██║
══════╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
Release [33m0.4.2[39m
這表明修改過的letschat鏡像能夠檢測到所有服務(wù)名為mongo的已經(jīng)啟動的MongoDB容器沿彭。
3.4 添加Load Balancer
另一個不錯的功能是load balancer朽砰,下面的例子中我將添加一個load balance,更多的關(guān)于Load Balancers的信息,可以參考文檔瞧柔。
首先在stack中點擊“Add Load Balancer”, 下面的選項使得負(fù)載均衡以輪詢的方式處理請求漆弄,但是會做會話的Stickiness配置(the following options will make the load balancer to distribute requests in round robin fashion but with a session stickiness翻譯的有點難受啊)
示例中的load balancer連接到了我們已經(jīng)創(chuàng)的letschat service上造锅,并且會輪詢service下的所有容器撼唾,,[]下面是stickiness選項,保證同一個會話的請求會路由到相同的服務(wù)器上哥蔚,應(yīng)用使用了一個名叫connect.sid的cookie倒谷。
創(chuàng)建好load balancer后,就可以通過訪問load balancer的地址來使用應(yīng)用了:
3.5 測試擴(kuò)展性
為了確保應(yīng)用是可伸縮的糙箍,所以創(chuàng)建一個新機(jī)器渤愁,注冊到rancher上,檢查配置好的容器會自動運行并添加到集群中:
這表示新的主機(jī)已經(jīng)被成功添加進(jìn)去倍靡,容器也自動的在其上運行了猴伶,也可以檢查新的mangodb容器,會顯示已經(jīng)添加到了副本集中:
2015-07-27T02:09:12.139+0000 I REPL [WriteReplSetConfig] Starting replication applier threads
2015-07-27T02:09:12.141+0000 I REPL [ReplicationExecutor] New replica set config in use: { _id: "letschat", version: 6, members: [ { _id: 0, host: "10.42.236.117:27017", arbiterOnly: false, ……...
我希望這會對理解怎么使用Rancher調(diào)度mongo副本集有幫助塌西。Letschat對于學(xué)習(xí)部署容器化的他挎,帶容錯的應(yīng)用,是一個非常好的例子捡需。如果有興趣用手上的Rancher嘗試一下办桨,可以在github上下載,加入Beta可以獲得更多的支持站辉,有任何問題都可以訪問我們的論壇呢撞,或者注冊我們下個月的線上會議提問,和開發(fā)們聊饰剥。