這一部分,咱們讓accountservice服務在本地部署的Docker Swarm集羣上運行,並探討容器編排的核心概念。java
本文處理下面的內容:node
其實這一部分和Go語言沒有什麼直接關係,具體來講它是關於Docker以及Docker Swarm的。一樣但願你能喜歡這篇文章。linux
在開始實操以前,快速介紹一下容器編排的概念可能會有用。git
隨着應用程序變得愈來愈複雜,而且須要處理更高的負載,咱們不得不處理這樣的一個事實,咱們成千上萬的服務實例遍及大量物理硬件上。容器編排讓咱們把全部硬件看成單個邏輯實體看待。github
容器編排這篇文章總結以下:golang
容器編排: 經過抽象主機基礎設施,編排工具容許用戶將整個集羣看成單個部署目標看待。
abstracting the host infrastructure, orchestration tools allow users to treat the entire cluster as a single deployment target.
我本身不能很好的總結它 - 使用容器編排器,例如Kubernetes或Docker Swarm,能夠容許咱們在一個或多個可用的基礎設施上將咱們的軟件組件部署爲服務。 在Docker的狀況中 - Swarm模式是關於管理叫作swarm的Docker引擎集羣的。 Kubernetes使用了一種稍微不一樣的術語和關鍵抽象層次結構, 可是整體上來講概念大體相同。docker
容器編排器不只爲咱們處理服務的生命週期,還爲服務發現、負載均衡、內部尋址和日誌提供了機制。shell
在Docker Swarm中有三個概念須要介紹:windows
下圖展現了微服務景觀的一種可能(簡化版)部署,其中兩個節點運行了五個容器實例,抽象成兩個服務accountservice和quotes-service。瀏覽器
這一部分沒有對Go代碼進行任何修改,只是添加了一些新的文件,用於將服務運行在Docker上。代碼地址: https://github.com/callistaen...。
Docker安裝,參考官網安裝指導。
Dockerfile是Docker用於構建docker容器映像的, 包含全部你但願包含的東西。讓咱們開始在/accountservice目錄下面建立一個Dockerfile吧。
FROM iron/base EXPOSE 6767 ADD accountservice-linux-amd64 / ENTRYPOINT ["./accountservice-linux-amd64"]
快速解釋:
如你所見,咱們在文件名後面添加了linux-amd64。固然咱們能夠隨意使用名字來指定Go語言可執行文件,可是我喜歡這樣的約定,將OS和目標CPU平臺放到可執行文件名中。我寫這個博客的時候,使用的是mac OS X。所以若是我只是直接在accountservice目錄下面運行go build來構建的話,會在同一個目錄下面產生一個accountservice可執行文件。可是這樣的文件在Docker容器中,底層OS是基於Linux的。所以,咱們在構建以前,須要設置一些環境變量, 這樣編譯器和連接器知道咱們在爲另外的OS、CPU架構進行構建, 咱們這裏的例子是linux。
export GOOS=linux go build -o accountservice-linux-amd64 export GOOS=darwin
上面使用-o標誌產生一個可執行二進制文件。 我一般寫一個小腳原本幫我執行一些可能須要重複執行的事情。
既然OS X和linux-based的容器都是運行在AMD64 CPU架構,由於咱們無需設置(並重置)GOARCH環境變量。 可是若是你爲32位OS構建或ARM處理器構建,就須要在構建以前恰當的設置GOARCH。
那麼如今能夠構建咱們第一個Docker映像來包含咱們的可執行文件。進入accountservice父級目錄, 應該是$GOPATH/src/github.com/callistaenterprise/goblog。
當構建Docker容器映像時,咱們一般使用[prefix]/[name]的命名約定來對其名字打標籤。我通常使用咱們的github用戶名作前綴, 例如eriklupander/myservicename。對於這個博客系列,咱們使用someprefix前綴。 在項目根目錄(eg: ./goblog)下面執行下面的命令來基於上面的Dockerfile來構建一個Docker映像。
// 在goblog目錄執行構建Docker鏡像 docker build -t someprefix/accountservice accountservice/ Sending build context to Docker daemon 14.34kB Step 1/4 : FROM iron/base latest: Pulling from iron/base ff3a5c916c92: Pull complete 43f18fea29ad: Pull complete Digest: sha256:1489e9c1536af14937ac7f975b8529cbe335672b7b87dae36c6b385d3e4020c0 Status: Downloaded newer image for iron/base:latest ---> b438fe7f76e9 Step 2/4 : EXPOSE 6767 ---> Running in 4246258b66c1 Removing intermediate container 4246258b66c1 ---> 5113056caf24 Step 3/4 : ADD accountservice-linux-amd64 / ADD failed: stat /var/lib/docker/tmp/docker-builder076553391/accountservice-linux-amd64: no such file or directory AppledeMacBook-Pro-2:goblog apple$ docker build -t someprefix/accountservice accountservice/ Sending build context to Docker daemon 7.457MB Step 1/4 : FROM iron/base ---> b438fe7f76e9 Step 2/4 : EXPOSE 6767 ---> Using cache ---> 5113056caf24 Step 3/4 : ADD accountservice-linux-amd64 / ---> 7a21b55920e3 Step 4/4 : ENTRYPOINT ["./accountservice-linux-amd64"] ---> Running in 5b7115e2f89d Removing intermediate container 5b7115e2f89d ---> 3e23a4268533 Successfully built 3e23a4268533 Successfully tagged someprefix/accountservice:latest
很好,咱們如今本地docker鏡像倉庫包含了名爲someprefix/accountservice的映像。 若是咱們想要運行多個節點或者想要共享咱們的鏡像, 咱們可使用docker push來將鏡像對其餘咱們當前Docker引擎提供的host以外的host拉取後可用。
而後咱們能夠直接經過命令行運行這個映像。
docker run --rm someprefix/accountservice Starting accountservice Seeded 100 fake accounts... 2018/05/16 02:57:37 Starting HTTP service at 6767
然而請注意,容器再也不是運行在你主機OS的localhost了。它如今位於它本身的網絡上下文,而且咱們不能直接從咱們的實際主機操做系統訪問。 固然有辦法修復,可是咱們先不深刻下去,咱們先對Docker Swarm進行局部設置,並部署accountservice。
咱們先使用Ctrl + C終止這個運行的鏡像。
本博客的一個目標就是咱們想讓咱們的微服務運行在容器編排上。 對於咱們不少人來講,通常意味着Kubernetes或Docker Swarm。 固然也有其餘編排器, 例如Apache Mesos和Apcera, 可是本文明確聚焦的是Docker 1.13的Docker Swarm上的。
當在你的開發計算機上配置單節點Docker Swarm集羣的時所需作的任務可能依賴於Docker自身怎麼安裝有關。 建議遵守Swarm Tutorial, 或者你可使用個人方式, 使用Docker Toolbox, Oracle Virtualbox和docker-machine, 是基於我同事Magnus lab-repo的關於服務發現的文章。
VirtualBox是一款開源的虛擬機軟件。若是使用Windows或OS X系統安裝Docker Swarm, 須要安裝這個軟件。
下載地址: http://download.virtualbox.or...
boot2docker是一個專爲Docker而設計的輕量級Linux髮型包,解決Windows或者OS X用戶不能安裝Docker的問題。 Boot2Docker徹底運行於內存中,24M大小,啓動僅5-6秒。
下載地址: https://github.com/boot2docke...。
Docker Swarm集羣至少包含一個Swarm管理器和零到多個Swarm worker。 這裏爲了簡單起見,咱們只使用一個Swarm管理器 - 這裏最少一個。在這節以後,重要的是你須要讓Swarm Manager啓動並運行起來。
咱們這裏的例子,使用docker-machine並製做一個虛擬linux機器運行在咱們的Swarm管理器的VirtualBox。 這裏咱們使用"swarm-manager-1"來標示這個管理器。 你也能夠參看官方文檔看如何建立Swarm。
咱們使用下面的命令來初始化docker-machine主機,並標示其爲swarm-manager-1做爲swarm-manager-1節點相同的swarm節點的ip地址。
docker $(docker-machine config swarm-manager-1) swarm init --advertise-addr $(docker-machine ip swarm-manager-1)
若是咱們須要建立多節點的Swarm集羣,咱們將確保存儲上面命令產生的鏈接token, 稍後若是咱們須要添加額外節點到swarm中。
Docker的覆蓋網絡是一種當咱們給Swarm添加相似"accountservice"到上面的時候使用的一種機制,這樣它能訪問在同一個Swarm集羣中的其餘容器,而無需知道實際的集羣拓撲結構。
使用下面的命令建立一個網絡:
docker network create --driver overlay my_network
這裏咱們給網絡起名爲my_network。
幾乎都已就緒,如今讓咱們開始部署咱們本身的"accountservice"來做爲一個Swarm服務吧。docker service create命令接收不少參數,但的確也不瘋狂。 下面是咱們發佈"accountservice"的命令:
docker service create --name=accountservice --replicas=1 --network=my_network -p=6767:6767 someprefix/accountservice
下面是參數的快速解釋:
就是這樣了。運行下面的命令來看咱們的服務是否成功啓動了。
> docker service ls ID NAME REPLICAS IMAGE ntg3zsgb3f7a accountservice 1/1 someprefix/accountservice
很甜美。 咱們如今可使用curl或經過瀏覽器來查詢咱們的API。惟一須要知道的就是前面是Swarm的公網IP。即使咱們在不少節點的swarm中爲咱們的服務只運行了一個實例, 覆蓋網絡和Docker Swarm容許咱們請求任意的swarm主機基於端口號來訪問服務。也就是說,兩個服務在外部不能使用同一端口號暴露。 他們內部端口號能夠相同, 可是對外來講必須惟一。
不管如何,請記住咱們以前保存的環境變量ManagerIP的值。
> echo $ManagerIP 192.168.99.100
若是已經改變了終端會話,能夠從新導出它。
export ManageIP=`docker-machine ip swarm-manager-0`
下面curl請求API:
> curl $ManagerIP:6767/accounts/10000 {"id":"10000","name":"Person_0"}
很是不錯,成功了。
使用docker的命令行API來檢查Swarm的狀態是徹底可行的(docker service ls), 可是使用更加圖形化的呈現,看起來更有意思。 例如可視化的有Docker Swarm Visualizer, 咱們一樣能夠像部署剛纔accountservice服務同樣的方式部署這個可視化服務工具。 這樣咱們能夠有另一種方式來查看咱們的集羣拓撲結構。 也能夠用於確保集羣中咱們是否讓某個服務暴露到給定端口號。
咱們能夠從預烘培的容器鏡像來安裝visualizer, 就一行命令:
docker service create \ --name=viz \ --publish=8080:8080/tcp \ --constraint=node.role==manager \ --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ dockersamples/visualizer
這樣咱們就能夠經過8000端口來訪問它。直接經過http://$ManagerIP:8000, 記住剛纔的ManagerIP的值。
我也開發了一個小的Swarm可視化器,叫作dvizz, 使用的是Go語言、Docker Remote API和D3.js產生圖形。 一樣可使用下面的命令安裝這個服務:
docker service create \ --constraint node.role==manager \ --replicas 1 --name dvizz -p 6969:6969 \ --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \ --network my_network \ eriklupander/dvizz
直接訪問http://$ManagerIP:6969, 能夠看到相似的展現:
看起來有點潦草, 可是不要太認真,它仍是很是有趣的, 看看塗上蹦蹦跳跳、上下縮放服務器、隨意拖放每一個節點。
微服務領域如今只有一個服務(咱們廣泛存在的accountservice)。 下面咱們部署一個前面提到的Spring Boot類型的微服務"Quotes-service", 這個微服務我已經放在公共的Docker倉庫中,能夠直接部署它。
docker service create --name=quotes-service --replicas=1 --network=my_network eriklupander/quotes-service
若是使用docker ps來列舉運行的Docker容器,咱們可能會看到它已經啓動了(或正在啓動中)。
> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 98867f3514a1 eriklupander/quotes-service "java -Djava.security" 12 seconds ago Up 10 seconds (health: starting) 8080/tcp
注意這裏咱們沒有導出這個服務的端口映射,意味着它不能從集羣外部訪問,只有內部經過內部端口8080訪問。 咱們會在後面第七部分服務發現和負載均衡中來集成這個服務。
若是你已經在集羣中添加了dvizz服務,你會看到圖中會多出一個quotes-service。
要簡化事情,咱們能夠添加一個shell腳原本幫咱們作從新構建和從新部署的自動化工做。在goblog的根目錄下面,建立一個copyall.sh文件:
#!/bin/bash export GOOS=linux export CGO_ENABLED=0 cd accountservice;go get;go build -o accountservice-linux-amd64;echo built `pwd`;cd .. export GOOS=darwin docker build -t someprefix/accountservice accountservice/ docker service rm accountservice docker service create --name=accountservice --replicas=1 --network=my_network -p=6767:6767 someprefix/accountservice
這個腳本設置了GOOS環境變量,這樣咱們能夠安全的爲Linux/AMD64架構構建靜態連接二進制文件, 而後運行一些docker命令來從新構建映像文件以及從新部署到Swarm服務裏邊。 能夠節約時間,而且少輸入不少字母。
Go語言項目的構建,我不在本文中深刻介紹。 我的認爲,我喜歡shell腳本的簡潔,雖然我本身也常用gradle插件,而且也知道一個好的ol的make也是至關流行。
從如今起,全部的基準測試和蒐集CPU/內存度量將用於Docker Swarm中部署的服務。 這意味着以前的文章結果和如今開始以後的結果不可比。
CPU使用和內存使用將使用Docker stats蒐集,同時咱們會使用以前使用的Gatling測試。
若是你本身運行負載測試, 那麼在第二部分引入的要求依然適用。 請注意,須要修改baseUrl參數爲Swarm Manager節點的IP, 例如:
mvn gatling:execute -Dusers=1000 -Dduration=30 -DbaseUrl=http://$ManagerIP:6767
到目前爲止,咱們已經學到如何在本地啓動Docker Swarm領域(只有一個節點), 以及如何打包和部署咱們的accountservice微服務做爲Docker Swarm的服務。
下一節,咱們會給咱們的微服務添加心跳檢查。