七夕你們過得怎麼樣?今天數人云帶你們迴歸技術和乾貨。雖然咱們可以在Swarm集羣當中部署任意數量的服務,但這並不表明各項服務所有可爲用戶所訪問。而新的Swarm網絡使得各項服務之間可以更爲輕鬆地實現彼此通訊。node
下面咱們將共同探討如何利用其對各服務進行公開。咱們還將嘗試將一套代理機制整合至Swarm網絡當中,從而更爲充分地發揮1.12版本帶來的優點。nginx
在開始進行以前,咱們須要設置一套用於演示的集羣。docker
要完成本示例,咱們假定你們已經擁有一套版本爲v0.8或者更高的Docker Machine,其中包含版本爲v1.12或者更高的Docker Engine。最便捷的獲取方法就是經過Docker Toolbox下載。數據庫
若是您是Windows用戶,請利用Git Bas運行所有示例(經過Docker Toolbox安裝)。後端
docker-machine create -d virtualbox node-1 docker-machine create -d virtualbox node-2 docker-machine create -d virtualbox node-3 eval $(docker-machine env node-1) docker swarm init \ --advertise-addr $(docker-machine ip node-1) \ --listen-addr $(docker-machine ip node-1):2377 TOKEN=$(docker swarm join-token -q worker) eval $(docker-machine env node-2) docker swarm join \ --token $TOKEN \ $(docker-machine ip node-1):2377 eval $(docker-machine env node-3) docker swarm join \ --token $TOKEN \ $(docker-machine ip node-1):2377`
如今咱們已經擁有了一套Swarm集羣,接下來是部署一項服務。服務器
包含三個節點的Docker Swarm集羣網絡
爲了檢驗新的Docker Swarm網絡功能,咱們首先建立如下兩套網絡。負載均衡
eval $(docker-machine env node-1) docker network create --driver overlay proxy docker network create --driver overlay go-demo
其一(proxy)將用於代理與面向API公開的服務之間的通訊。而其二(go-demo)則面向所有用於構建go-demo服務的容器。該服務包含兩套容器,且利用MongoDB用於存儲數據,而vfarcic/go-demo則做爲配備API的後端。frontend
咱們將從數據庫起步。因爲其不會公共開放,所以不須要將其添加至代理當中。這裏,咱們直接將其附加至go-demo網絡。curl
docker service create --name go-demo-db \ --network go-demo \ mongo
數據庫上線並開始運行後,咱們接下來部署後端。因爲咱們但願外部用戶可以使用該API,所以應當將其歸入代理。咱們將其同時附加至兩套網絡(proxy與go-demo)。
docker service create --name go-demo \ -e DB=go-demo-db \ --network go-demo \ --network proxy \ vfarcic/go-demo
由三臺節點、兩套網絡與多套容器構成的Docker Swarm集羣
如今兩套容器都運行在集羣當中,且可以彼此經過go-demo網絡進行通訊。下面將代理引入其中。咱們這裏使用HAProxy。
須要注意的是,咱們並無指定端口,這意味着沒有任何一套容器可以爲go-demo網絡以外的請求所訪問。
咱們能夠經過多種方式創建代理機制。其一利用HAProxy建立一套新鏡像,其中包含各配置文件。這種方式比較適合服務數量相對固定的狀況。不然,咱們應當建立一套每當有新服務(而非新版本發佈)出現時即進行新配置的鏡像。
經過第二種方法,其將以分卷形式存在,咱們可以在必要時僅修改配置文件而非整套新鏡像。然而,這種做法也存在弊端。在部署至一套集羣時,咱們應當儘量避免使用分卷。接下來你們會看到,代理就是不須要分卷的機制之一。另外,--volume可替換爲docker service命令中的—mount參數。
第三種選項是使用專門與Docker Swarm協做的代理之一。在這種狀況下,咱們將使用vfarcic/docker-flow-proxy容器,其由Docker Flow: Proxy項目建立而成。其基於HAProxy且擁有多項其它功能,容許咱們經過發送HTTP請求對其進行從新配置。
下面一塊兒來看:
docker service create --name proxy \ -p 80:80 \ -p 443:443 \ -p 8080:8080 \ --network proxy \ -e MODE=swarm \ vfarcic/docker-flow-proxy`
咱們開啓的端口80與443將負責處理互聯網流量(HTTP與HTTPS)。第三個端口則爲8080,咱們將利用它向代理髮送配置請求。另外,咱們強調其應當歸屬於proxy網絡。如此一來,因爲go-demo也被附加至同一套網絡,意味着代理可以經過SDN對其進行訪問。
在這套代理的幫助下,咱們實現了最實用的網絡路由功能之一。不管你們在哪臺服務器上運行該代理,咱們都可以向任意節點發送請求,而Docker網絡會確保其被從新定向至代理之一。
最後一項參數爲環境變量MODE,其負責告知該代理,各容器將被部署至Swarm集羣當中。請參閱項目的README文件以瞭解更多細節信息。
配合代理服務的Docker Swarm集羣
須要注意的是,該代理即便已經運行在某一節點當中,仍會被放置於其外以表達其在邏輯上的分離特性。
在開始以前,首先確認代理正在運行。
docker service ps proxy
若是其「最新狀態(Last state)」爲「運行(Running)」,則可繼續。若是否則,請等待直到該服務上線並開始運行。
如今代理已經部署完成,咱們應當確保其知曉go-demo服務的存在。
curl "$(docker-machine ip node-1):8080/v1/docker-flow-proxy/reconfigure?serviceName=go-demo&servicePath=/demo&port=8080"
這條請求的做用是從新配置代理以指定服務名稱(go-demo)、API的URL路徑(/demo)以及該服務的內部端口(8080)。從如今開始,全部指向該代理且使用以/demo開頭路徑的請求都將被從新定向至go-demo服務。
如今咱們能夠測試代理是否按預期運行——發送一條HTTP請求進行驗證。
curl -i $(docker-machine ip node-1)/demo/hello
該curl命令的輸出結果以下所示。
HTTP/1.1 200 OK Date: Mon, 18 Jul 2016 23:11:31 GMT Content-Length: 14 Content-Type: text/plain; charset=utf-8 hello, world!
代理正常起效!它響應了HTTP status 200並向API返回了hello,world!
須要注意的是,這一過程與咱們執行操做所在的具體節點無關。因爲Docker網絡(路由體系)負責實現負載均衡,所以咱們可以前往任意服務器。做爲示例,下面咱們發送一樣的請求,但這一次立足於node-3。
curl -i $(docker-machine ip node-3)/demo/hello
結果仍然徹底相同。
下面讓咱們一塊兒瞭解由該代理生成的配置。
若是你們選擇自行構建代理解決方案,那麼固然須要瞭解如何配置代理並利用Docker網絡中的各項新功能。
下面首先檢查Docker Flow: Proxy爲咱們建立的配置。咱們能夠進入當前運行的容器並經過/cfg/haproxy.cfg文件查看這部分信息。不過問題是,找到由Docker Swarm運行的一套容器須要配合一點技巧。舉例來講,若是咱們利用Docker Compose部署此容器,那麼其名稱會存在必定規律,即便用__格式。而docker service命令會利用散列後的名稱運行容器。在個人筆記本上,docker-flow-proxy的建立名稱爲proxy.1.e07jvhdb9e6s76mr9ol41u4sn。所以,要進入由Docker Swarm部署並運行的容器,咱們須要對鏡像名稱進行過濾。
第一步,咱們須要找到代理運行所在的具體節點。
docker service ps proxy
須要注意的是該node列中的值,同時確保在如下命令中使用該正確值。
eval $(docker-machine env node-1) # Change node-1 with the node value previously obtained
此命令將給出如下代理配置輸出結果。
docker exec -it \ $(docker ps -q --filter "ancestor=vfarcic/docker-flow-proxy") \ cat /cfg/haproxy.cfg exit
配置信息中最重要的部分以下所示。
frontend services bind *:80 bind *:443 option http-server-close acl url_go-demo path_beg /demo use_backend go-demo-be if url_go-demo backend go-demo-be server go-demo go-demo:8080
對於第一部分(frontend),熟悉HAProxy的朋友應該不會感到陌生。其接收來自端口80(HTTP)以及443(HTTPS)的請求。若是路徑以/demo開頭,其會被從新定向至後端go-demo處。在這裏,各請求會被髮送至go-demo在端口8080上的地址。此地址同時亦是咱們所部署的服務名稱。因爲go-demo同proxy存在於同一網絡當中,所以Docker可以確保該請求被從新定向至目標容器。很簡單,對吧?咱們無需再另行指定IP以及外部端口。
接下來的問題是,如何實現負載均衡。舉例來講,咱們要如何指定該代理跨越所有實例執行循環?
在開始進行負載均衡解釋以前,首先建立幾個go-demo服務實例。
eval $(docker-machine env node-1) docker service scale go-demo=5
稍等一下子,就將有5個go-demo服務實例開始運行。
包含規模化go-demo服務與代理實例的Docker Swarm集羣
咱們該如何讓代理將請求均衡至所有實例當中?答案是不用——咱們並不須要執行特別的操做。
正常來說,若是咱們不使用Docker Swarm功能,則可以使用如下配置方式:
backend go-demo-be server instance_1 <INSTANCE_1_IP>:<INSTANCE_1_PORT> server instance_2 <INSTANCE_2_IP>:<INSTANCE_2_PORT> server instance_3 <INSTANCE_3_IP>:<INSTANCE_3_PORT> server instance_4 <INSTANCE_4_IP>:<INSTANCE_4_PORT> server instance_5 <INSTANCE_5_IP>:<INSTANCE_5_PORT>
然而在新的Docker網絡當中,咱們將再也不須要進行上述配置。本來的做法只會在新副本添加或者刪除時,給咱們的實例監控與代理更新工做形成麻煩。
如今,Docker會幫助咱們完成所有負載均衡工做。更準確地講,當該代理將某條請求從新定向至go-demo時,其實際將其發送至Docker網絡並由後者執行跨越所有服務副本(實例)的負載均衡。這套方案的意義在於,代理負責將端口80(或者443)從新定向至網絡中的正確服務處,其它任務則所有由Docker完成。
你們能夠隨意向該服務發送更多請求,並檢查其中一套副本的日誌記錄。在這裏,你們會發現其接收到的請求約爲整體請求數量的五分之一——與咱們的服務實例數量剛好吻合。
Docker網絡與Docker 1.12及更高版本提供的Swarm相結合,無疑開啓了一道通向更多新機遇的大門。不一樣容器與負載均衡之間的內部通訊只是其中的一小部分,咱們亦能夠更爲輕鬆地配置公開代理。另外,咱們須要確保面向API進行公開的所有服務皆以代理形式接入同一網絡。在此以後,咱們要作的就是進行配置以將全部請求從新定向至目標服務名稱。這樣全部來自代理的請求都將指向Docker網絡,並由後者跨越所有實例執行負載均衡。
但新的問題在於,這套方案的具體效率是否理想。畢竟咱們在體系中引入了新的層。儘管過去咱們也會使用代理以及服務,但如今Docker網絡會在兩者之間創建負載均衡機制。答案是,由此帶來的運行負擔很是有限。Docker利用Linux IPVS實現負載均衡,其做爲Linux內核的組成部分已經擁有超過15年曆史,並且事實證實其是一種極爲高效的負載均衡實現方式。事實上,其速度表現遠遠優於nginx或者HAProxy。
下一個問題是,咱們是否須要代理機制。是的,固然須要。DOcker所使用的IPVS只負責實現負載均衡。咱們還須要一套代理以接收來自端口80與443的請求,並根據其實際路徑將其從新定向至各目標服務。在此基礎之上,咱們還能夠利用它執行多種任務,包括SSL握手以及驗證等等。
那麼這種做法存在哪些缺點?首先想到的確定是粘性會話。若是咱們但願同一用戶向同一實例發送請求,那麼這套方案顯然並不適用。另外一個問題是,咱們是否應當在服務以內實現粘性會話,或者應該將其做爲獨立實體。這個問題咱們在本文中暫時不做討論,只須要明確這裏提到的方案並不適用於粘性會話便可。
那麼其具有哪些優點?首先,整個實現過程很是簡單。咱們用不着在部署新副本時對代理進行從新配置。如此一來,整個流程將很是便捷。因爲咱們不須要包含所有端口IP及端口的列表,所以也就無需使用Registrator以及Consul Template之類的工具。過去,咱們須要利用Registrator以監控Docker事件,並將IP及端口保存在鍵值存儲方案(例如Consul)當中。信息存儲完成後,咱們會利用Consul Template從新建立代理配置。雖然很多項目都能簡化這一流程,但Docker Swarm與Docker網格的再現從根本上下降了其實施難度。
在本文中,咱們講述瞭如何利用Docker Flow: Proxy項目配置HAProxy。其中包含HAProxy及一系列其它API,容許咱們利用簡單的HTTP請求對代理進行從新配置。另外,其還消除了對手動配置或者模板的依賴性。
在另外一方面,創建自定義解決方案的流程也變得更爲簡單。本文只稍稍列舉幾項重點即解釋了整個構建過程,這在nginx或者HAProxy配置工做中是徹底沒法想象的。
因此個人建議是先嚐試一下Docker Flow: Proxy,然後再作決定。
今天咱們已經總結了Docker v1.12帶來的一系列Swarm與網絡新功能,特別是在公開代理方面的改進。
那麼咱們是否是就可以成功運行Swarm羣集了呢?還差得遠!本文僅僅只是開始,咱們還有大量問題有待回答。Docker Compose發生了哪些改變?咱們該如何在不形成停機的前提下部署新版本?是否還有其它值得一試的工具?
後續的內容,也敬請你們期待!