Docker的生态日趨成熟,開源社群也不斷孵化出優秀的周邊項目,覆寫網絡、監控、維護、部署、開發等方面。幫助開發、運維人員快速建構、營運Docker服務環境,其中也不乏有大公司的影子,如Google、IBM、Redhat,甚至微軟也宣稱後續将提供Docker在Windows平台的支援。
Docker的發展前景一片大好。但在企業當中,如何選擇适合自己的Docker建構方案?可選的方案有kubernetes與CoreOS(都已整合各類元件),另外一種方案為Haproxy+etcd+confd,采用松散式的組織結構,但各個元件之間的通訊是非常嚴密的,且可擴充性更強,定制也更加靈活。IEG資料中心業務平台首選此架構,已進入試營運階段。下面詳細介紹如何使用Haproxy+etcd+confd建構一個高可用及自動發現的Docker基礎架構。
約定由Haproxy+etcd+confd+Docker建構的基礎服務平台簡稱“HECD” 架構,整合了多種開源元件,看似松散的結構,事實上已經是一個有機的整體,它們互相聯系、互相作用,是Docker生态圈中最理想的組合之一,具有以下優勢:
自動、實時發現及無感覺服務重新整理;
支援任意多台Docker主宿機;
支援多種APP接入且打散至不分主宿機;
采用Etcd存儲資訊,叢集支援可靠性高;
采用Confd配置引擎,支援各類接入層,如Nginx;
支援負載均衡、故障遷移;
具備資源彈性,伸縮自如(通過生成、銷毀容器實作);
在HECD架構中,首先管理者操作Docker Client,除了送出容器(Container)啟動與停止指令外,還通過REST-API方式向Etcd(K/V)存儲元件注冊容器資訊,包括容器名稱、主宿機IP、映射端口等。Confd配置元件會定時查詢Etcd元件擷取最新的容器資訊,根據定義好的配置模闆生成Haproxy配置檔案Haproxy.cfg,并且自動reload haproxy服務。使用者在通路業務服務時,完全沒有感覺後端APP的上線、下線、切換及遷移,達到了自動發現、具備高可用等特點。詳細架構圖見圖1-1。

圖1-1 平台架構圖
為了友善大家了解各元件間的關系,通過圖1-2進行架構流程梳理,首先管理者通過Shell或api操作容器,下一步将容器資訊注冊到Etcd元件,Confd元件會定時查詢Etcd,擷取已經注冊到Etcd中容器資訊,最後通過Confd的模闆引擎生成Haprox配置,整個流程結束。
圖1-2 架構流程圖
了解架構流程後,我們逐一對流程中各元件進行詳細介紹。
1、 Etcd介紹
Etcd是一個高可用的 Key/Value 存儲系統,主要用于分享配置和服務發現。
簡單:支援 curl 方式的使用者 API (HTTP+JSON)
安全:可選 SSL 用戶端證書認證
快速:單執行個體可達每秒 1000 次寫操作
可靠:使用 Raft 實作分布式
2、 Confd介紹
Confd是一個輕量級的配置管理工具。通過查詢Etcd,結合配置模闆引擎,保持本地配置最新,同時具備定期探測機制,配置變更自動reload。
3、 Haproxy介紹
HAProxy是提供高可用性、負載均衡以及基于TCP和HTTP應用的代理,支援虛拟主機,它是免費、快速并且可靠的一種解決方案。(來源百科)
平台環境基于Centos6.5+Docker1.2建構,其中Etcd的版本為etcd version 0.5.0-alpha,Confd版本為confd 0.6.2,Haproxy版本為HA-Proxy version 1.4.24。下面對平台的運作環境、安裝部署、元件說明等進行詳細說明,環境裝置角色表如下:
角色
主機名
IP
環境說明
接入層
SN2013-08-020
192.168.1.20
Haproxy+confd
存儲層
SN2012-07-021
192.168.1.21
Etcd
主宿機
SN2012-07-022
192.168.1.22
Docker
主宿機N
…
1.1 Docker安裝
SSH終端登入192.168.1.22伺服器,執行以下指令:
1.2 Haproxy、confd安裝
SSH終端登入192.168.1.20伺服器,執行以下指令:
haproxy
<code># yum –y install haproxy</code>
confd
<code># wget https://github.com/kelseyhightower/confd/releases/download/v0.6.3/confd-0.6.3-linux-amd64</code> <code># mv confd /usr/local/bin/confd</code> <code># chmod +x /usr/local/bin/confd</code> <code># /usr/local/bin/confd -version</code> <code>confd</code> <code>0.6.2</code>
1.3 etcd安裝
SSH終端登入192.168.1.21伺服器,執行以下指令:
2.1 Etcd配置
由于etcd是一個輕量級的K/V存儲平台,啟動時指定相關參數即可,無需配置。
由于etcd具備多機支援,參數“-peer-addr”指定與其它節點通訊的位址;參數“-addr”指定服務監聽位址;參數“-data-dir”為指定資料存儲目錄。
由于etcd是通過REST-API方式進行互動,常見操作如下:
設定(set) key操作
擷取(get) key資訊
删除key資訊
更多操作API見https://github.com/coreos/etcd/tree/master/etcdctl
2.2 Confd+Haproxy配置
由于Haproxy的配置檔案是由Confd元件生成,要求Confd務必要與haproxy安裝在同一台主機上,Confd的配置有兩種,一種為Confd資源配置檔案,預設路徑為“/etc/confd/conf.d”目錄,另一種為配置模闆檔案,預設路徑為“/etc/confd/templates”。具體配置如下:
建立配置檔案目錄
(1) 配置資源檔案
詳細見以下配置檔案,其中“src”為指定模闆檔案名稱(預設到路徑/etc/confd/templates中查找);“dest”指定生成的Haproxy配置檔案路徑;“keys”指定關聯Etcd中key的URI清單;“reload_cmd”指定服務重載的指令,本例中配置成haproxy的reload指令。
【/etc/confd/conf.d/ haproxy.toml】
(2)配置模闆檔案
Confd模闆引擎采用了Go語言的文本模闆,更多見<code>http://golang.org/pkg/text/template/</code>,具備簡單的邏輯文法,包括循環體、處理函數等,本示例的模闆檔案如下,通過range循環輸出Key及Value資訊。
【/etc/confd/templates/haproxy.cfg.tmpl】
(3)模闆引擎說明
本小節詳細說明Confd模闆引擎基礎文法與示例,下面為示例用到的KEY資訊。
1、 base
作為path.Base函數的别名,擷取路徑最後一段。
{{ with get "/app/servers/prickly_blackwell"}}
{{end}}
2、 get
傳回一對比對的KV,找不到則傳回錯誤。
{{with get "/app/servers/prickly_blackwell"}}
3、 gets
傳回所有比對的KV,找不到則傳回錯誤。
{{range gets "/app/servers/*"}}
4、 getv
傳回一個比對key的字元串型Value,找不到則傳回錯誤。
{{getv "/app/servers/cocky_morse"}}
5、 getvs
傳回所有比對key的字元串型Value,找不到則傳回錯誤。
6、 split
對輸入的字元串做split處理,即将字元串按指定分隔符拆分成數組。
7、 ls
傳回所有的字元串型子key,找不到則傳回錯誤。
{{range ls "/app/servers/"}}
subkey: {{.}}
8、 lsdir
傳回所有的字元串型子目錄,找不到則傳回一個空清單。
{{range lsdir "/app/"}}
subdir: {{.}}
(4)啟動confd及haproxy服務
下面為啟動Confd服務指令行,參數“interval”為指定探測etcd的頻率,機關為秒,參數“<code>-node</code>”為指定etcd監聽服務主位址,以便擷取容器資訊。
前面HECD架構說明内容,有講到容器的操作會即時注冊到etcd元件中,是通過curl指令進行REST-API方式送出的,下面詳細介紹通過SHELL及Python-api兩種方式的實作方法,支援容器啟動、停止的關聯。
3.1、SHELL實作方法
實作的原理是通過擷取“<code>Docker run ***</code>”指令輸出的Container ID,通過“docker inspect Container ID”得到詳細的容器資訊,分析出容器服務映射的外部端口及容器名稱,将以“/app/servers/容器名稱”作為Key,“主宿機: 映射端口”作為Value注冊到etcd中。其中Key資訊字首(/app/servers)與“/etc/confd/conf.d/haproxy.toml”中的keys參數是保持一緻的。【docker.sh】
docker.sh使用方法:
1、啟動一個容器
2、停止一個容器
3.2、Docker-py API實作方法
通過Python語言調用<code>Docker-py</code>的API實作容器的遠端操作(建立、運作、停止),并結合<code>python-etcd</code>子產品對etcd進行操作(set、delete),達到與SHELL方式一樣的效果,很明顯,Docker-py方式更加容易擴充,可以無縫與現有營運平台對接。
為兼顧到遠端API支援,需對docker啟動檔案“exec”處進行修改,詳細見如下:
啟動容器的程式如下:
【docker_run.py】
停止容器的程式如下:
【docker_stop.py】
注意:
由于容器是無狀态的,盡量讓其以松散的形式存在,映射端口選項要求使用“-P”參數,即使用随機端口的模式,減少人手幹預。
HECD架構已部署完畢,接下來就是讓其為我們服務,案例中使用的鏡像“yorko/webserver:v3”為已經建構好的LAMP平台。類似的鏡像也可以在docker-pub中下載下傳到,開始跑起,運作dockery.sh建立兩個容器:
通路Haproxy監控位址:<code>http://192.168.1.20/admin-status</code>,剛建立的容器已經添加到haproxy中,見圖1-3。
圖1-3 Haproxy監控背景截圖
觀察Haproxy的配置檔案(更新部分):
通路php測試檔案<code>http://192.168.1.20/info.php</code>
圖1-4 php測試檔案截圖
從圖1-4可以看出,擷取的伺服器端IP為容器本身的IP位址(172.17.0.11),在System環境變量處輸出容器名為“598cf10a50a2”的資訊。
參考文章:
[1] Easy scaling with Docker, HAProxy and confd
[2] https://github.com/AVGP/forrest/blob/master/forrest.sh