最新版本Docker Engine v1.12中,包含了多項與Docker Swarm緊密相關的功能變動。在今天的文章中,數人云將和你們探討如何利用Docker的Swarm Mode進行服務部署。node
在向Docker Engine Swarm部署一項服務以前,咱們首先須要設置一套Swarm集羣。因爲本文旨在展現1.12版本中的各項新增功能,所以咱們應當安裝Docker Engine的最新版本。linux
如下操做指南適用於Ubuntu 16.04環境下的Docker Engine安裝。對於其它版本及平臺,你們能夠查看Docker的官方安裝指南。redis
在安裝過程當中,咱們須要使用Ubuntu提供的標準安裝方法,即Apt軟件包管理器。因爲咱們將安裝Docker Engine的最新版本,所以須要配置Apt以從Docker官方Apt庫處獲取docker-engine軟件包,而非直接使用系統預配置庫。docker
配置Apt以使用新庫的第一步,須要使用apt-key命令將該庫的公鑰添加至Apt緩存當中。ubuntu
# apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
以上apt-key命令會向p80.pool.sks-keyservers.net密鑰服務器請求該特定密鑰(58118E89F3A912897C070ADBF76221572C52609D)。該公鑰將被用於驗證下載自此新庫的所有軟件包。緩存
如今Docker公鑰已經導入完成,咱們能夠配置Apt以使用Docker項目的庫服務器。要實現這一目標,咱們須要在/etc/apt/sources.list.d/目錄內添加如下條目。服務器
# echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" >> /etc/apt/sources.list.d/docker.list
在刷新Apt軟件包緩存時,Apt會對sources.list.d/目錄內的所有文件進行搜索,旨在查找新的軟件包庫。以上命令會建立(若尚不存在)一個名爲docker.list的新文件,並將對應條目添加至apt.dockerproject.org庫當中。負載均衡
要更新Apt的軟件包緩存,咱們能夠運行apt-get命令並添加update選項。ui
# apt-get update
如此一來,Apt會經過從新讀取所有配置文件以填充各庫列表,其中包括咱們剛剛添加的配置文件。另外,其還將查詢這些庫以緩存一份可用軟件包清單。this
在安裝Docker Engine以前,咱們還須要安裝另外一軟件包。linux-image-extra軟件包是一套特定內核軟件包,負責幫助Ubuntu系統支持aufs存儲驅動器。此驅動程序由Docker用於向容器內安裝各分卷。
要安裝此軟件包,咱們須要再次使用apt-get命令,但這一次配合install選項。
# apt-get install linux-image-extra-$(uname -r)
在此apt-get命令當中,$(uname -r)部分或者命令將返回當前運行中內核的實際版本。任何對此係統內核的更新都應包含對應linux-image-extra軟件包版本的安裝。若是此軟件包未進行更新,則Docker可能會在安裝分卷時出現某些問題。
Apt配置完成且linux-image-extra安裝完畢以後,咱們如今能夠着手安裝Docker Engine。要完成這項任務,咱們須要再次使用apt-get命令配合install選項,從而安裝docker-engine軟件包。
# apt-get install docker-engine
在這裏,咱們應當已經擁有Docker Engine v1.12.0或者更新版本。要驗證是否具有正確版本,能夠執行docker命令配合version選項。
# docker versionClient: Version: 1.12.0 API version: 1.24 Go version: go1.6.3 Git commit: 8eab29e Built: Thu Jul 28 22:11:10 2016 OS/Arch: linux/amd64 Server: Version: 1.12.0 API version: 1.24 Go version: go1.6.3 Git commit: 8eab29e Built: Thu Jul 28 22:11:10 2016 OS/Arch: linux/amd64
在這裏,咱們能夠看到服務器與客戶端版本皆爲1.12.0。下面開始建立Swarm。
在本篇教程中,咱們將跨越多臺設備執行此項任務。爲了清晰起見,這裏咱們在命令示例中包含主機名稱。
咱們首先創建一套雙節點Swarm集羣,其中的兩個節點皆應利用上述操做完成Docker Engine的安裝。
在建立該Swarm集羣時,咱們須要指定一個節點管理器。在本示例中,咱們將使用名稱爲swarm-01的主機做爲節點管理器。要讓swarm-01成爲節點管理器,咱們須要首先在swarm-01之上執行一條命令以建立Swarm集羣。這裏咱們使用docker命令配合swarm init選項。
root@swarm-01:~# docker swarm init --advertise-addr 10.0.0.1 Swarm initialized: current node (awwiap1z5vtxponawdqndl0e7) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \ 10.0.0.1:237 7To add a manager to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-bwex7fd4u5aov4naa5trcxs34 \ 10.0.0.1:2377
利用以上命令外加swarm init,咱們還利用10.0.0.1值指定了--advertise-addr標記。Swarm節點管理器將利用該IP聲明該Swarm集羣服務。儘管該地址屬於專有IP,但爲了讓各節點順利加入此Swarm,各節點都須要可以經過此IP在端口2377上接入此節點管理。
在運行docker swarm init命令以後,咱們會看到swarm-01已經被分配了一個節點名稱(awwiap1z5vtxponawdqndl0e7)併成爲此Swarm集羣中的管理器。其輸出結果分爲兩條命令:其一用於向該Swarm內添加一個工做節點,其二爲向該Swarm內添加另外一節點管理器。
Docker Swarm Mode可以支持多套節點管理器,不過其仍會選擇其中之一做爲主節點管理器,並由其負責Swarm集羣內部的編排工做。
在Swarm集羣建立完成後,如今咱們能夠利用由Swarm建立給出的輸出結果,經過docker命令添加新的工做節點。
root@swarm-02:~# docker swarm join \ > --token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \ > 10.0.0.1:2377 This node joined a swarm as a worker.
在本示例中,咱們將swarm-02添加至Swarm當中做爲工做節點。工做節點屬於Swarm集羣當中的一個成員,其角色在於運行各種任務; 而其中的任務則表現爲容器形式。在另外一方面,節點管理器則負責管理任務(容器)編排並維護Swarm集羣自己。
除了節點管理職責以外,節點管理器自己亦做爲工做節點存在,意味着其一樣可以爲Swarm集羣分擔部分任務。
在上述命令執行完畢以後,如今咱們已經擁有了一套基本的雙節點Swarm集羣。下面咱們執行docker命令與node ls選項以驗證集羣的當前狀態。
root@swarm-01:~# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 13evr7hmiujjanbnu3n92dphk swarm-02.example.com Ready Active awwiap1z5vtxponawdqndl0e7 * swarm-01.example.com Ready Active Leader
今後命令的輸出結果中,咱們能夠看到swarm-01與swarm-02都處於Ready與Active狀態。如此一來,如今咱們便可進一步向此套Swarm集羣部署服務了。
在Docker Swarm Mode當中,服務屬於一套長期運行的Docker容器,其可被部署在任意工做節點之上。另外,該服務亦容許任意Swarm集羣內的遠程系統或者容器進行接入與使用。
在本示例當中,咱們將部署一項Redis服務。
複製服務屬於一項Docker Swarm服務,其中包含特定數量的運行副本。這些副本由特定Docker容器的多個實例所構成。在本示例中,每套副本都將表現爲一個獨特的Redis實例。
要建立新服務,咱們使用docker命令並配合service create選項。如下命令將建立一項名爲redis的服務,其擁有2套副本並在整套集羣內經過6379端口進行發佈。
root@swarm-01:~# docker service create --name redis --replicas 2 --publish 6379:6379 redis er238pvukeqdev10nfmh9q1kr
除了指定service create選項以外,咱們還須要使用--name標記以命名redis服務,並由--replicas標記指定該服務應運行在2套不一樣節點之上。咱們能夠在兩個節點中執行docker命令配合service ls選項以實現這一效果。
root@swarm-01:~# docker service ls ID NAME REPLICAS IMAGE COMMAND er238pvukeqd redis 2/2 redis
在輸出結果中,咱們能夠看到2套副本中的2套正處於運行當中。若是咱們但願瞭解與這些任務相關的更多細節信息,則可運行docker命令配合service ps選項。
root@swarm-01:~# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 5lr10nbpy91csmc91cew5cul1 redis.1 redis swarm-02.example.com Running Running 40 minutes ago 1t77jsgo1qajxxdekbenl4pgk redis.2 redis swarm-01.example.com Running Running 40 minutes ago
其中service ps選項將顯示此特定服務的所有任務(容器)。在本示例中,咱們能夠看到redis服務擁有一項任務(容器),且同時運行在兩個Swarm節點之上。
因爲咱們已經證明此服務開始運行,所以接下來可利用redis-cli客戶端立足於遠程系統接入該項服務。
vagrant@vagrant:~$ redis-cli -h swarm-01.example.com -p 6379 swarm-01.example.com:6379>
經過以上鍊接,咱們可以成功接入該redis服務。這意味着咱們的服務已經啓動並處於可用狀態。
在建立此redis服務時,咱們使用了--publish標記並配合docker service create命令。此標記用於告知Docker公佈6379端口做爲該redis服務的可用端口。
而當Docker爲某項服務發佈端口時,其會在Swarm集羣內的所有節點之上監聽該端口。當有流量通過該端口,則對應流量會被路由至負責運行該服務的對應容器。儘管此概念在所有節點皆運行單一服務容器時可以以標準化方式實現,但在面對多套副本時則會發生一些變化。
要了解其工做原理,讓咱們向Swarm集羣中添加第三個工做節點。
要添加另外一工做節點,咱們只須要重複文章開頭處的安裝與設置步驟便可。這裏直接跳太重複部分,然後再次運行docker命令以檢查集羣中的當前運行狀態。
root@swarm-01:~# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 13evr7hmiujjanbnu3n92dphk swarm-02.example.com Ready Active awwiap1z5vtxponawdqndl0e7 * swarm-01.example.com Ready Active Leader e4ymm89082ooms0gs3iyn8vtl swarm-03.example.com Ready Active
如今能夠看到咱們的集羣由三個節點構成:
swarm-01
swarm-02
swarm-03
當咱們利用兩套副本建立服務時,其會在swarm-01與swarm-02之上建立任務(容器)。下面看看添加另外一工做節點會對此產生何種影響。
root@swarm-01:~# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 5lr10nbpy91csmc91cew5cul1 redis.1 redis swarm-02.example.com Running Running 55 minutes ago 1t77jsgo1qajxxdekbenl4pgk redis.2 redis swarm-01.example.com Running Running 55 minutes ago
利用複製服務,Docker Swarm可以確保每套指定副本皆擁有一個任務(容器)處於運行當中。在建立redis服務時,咱們指定其中應存在2套副本。這意味着即便添加第三個節點,Docker仍然不會在該節點上創建新的任務。
這樣一來,咱們就面對着一種有趣的狀態:咱們的服務運行在3個Swarm節點中的2個之上。在非Swarm環境下,這意味着redis服務將沒法接入第三個Swarm節點。然而因爲Swarm Mode的存在,這種接入關係仍可正常實現。
以前咱們已經探討了Docker如何公佈一個服務端口,當時提到該端口會被公佈至Swarm內的所有節點。而真正值得關注的是,當咱們接入某個並未運行服務相關容器(任務)的工做節點時,會發生怎樣的狀況。
下面咱們看看經由redis公開端口接入swarm-03,會有怎樣的結果。
vagrant@vagrant:~$ redis-cli -h swarm-03.example.com -p 6379 swarm-03.example.com:6379>
有趣的是,咱們的鏈接嘗試仍然可以成功。之因此成功,是由於儘管swarm-03並無運行任何redis容器,但Docker內部會將咱們的redis服務流量從新路由至運行有redis容器的工做節點。
Docker將此稱爲入口負載均衡。其工做原理在於,所有工做節點都會監聽指向公開服務端口的鏈接。當外部系統調用某項服務時,接收節點會接受流量並利用Docker提供的內部DNS服務對其進行負載均衡。
因此即便咱們將Swarm集羣擴展至包含100個工做節點,服務的最終用戶仍然可以輕鬆接入任意工做節點。他們的請求隨後會被從新定向至兩套運行有redis服務任務(容器)的Docker主機之一。
這種從新路由與負載均衡機制對於最終用戶是徹底透明的,且全程發生於Swarm集羣內部。
如今咱們設置的redis服務已經運行有2套副本,意味着其運行在3個節點中的2個之上。
若是但願咱們的redis服務在每一個工做節點上皆擁有實例,咱們能夠將服務的必要副本數量由2修改成3。這意味着只要添加或者除去工做節點,咱們就須要對副本數量作出調整。
固然,咱們也能夠將服務轉化爲全局服務從而自動完成上述調整。Docker Swarm Mode中的全局服務用於建立可以自動在各個工做節點上擁有運行任務的服務。這項機制適用於Redis等須要在內部由其它服務使用的常規服務。
要完成這一調整,咱們須要將本身的redis服務從新建立爲一項全局服務。
root@swarm-01:~# docker service create --name redis --mode global --publish 6379:6379 redis 5o8m338zmsped0cmqe0guh2to
以上命令一樣使用docker service create命令進行復制服務的建立,不過區別在於--mode標記以後添加了global值。
服務建立完成以後,能夠看到Docker如何一次執行docker命令與service ps選項將該服務的各項任務進行分發。
root@swarm-01:~# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 27s6q5yvmyjvty8jvp5k067ul redis redis swarm-03.example.com Running Running 26 seconds ago 2xohhkqvlw7969qj6j0ca70xx \_ redis redis swarm-02.example.com Running Running 38 seconds ago 22wrdkun5f5t9lku6sbprqi1k \_ redis redis swarm-01.example.com Running Running 38 seconds ago
如今該服務已經被建立爲全局服務,接下來Swarm集羣內的各個節點皆將運行與之相關的任務(容器)。
在本篇文章中,咱們不只完成了Docker Engine的安裝,同時亦設置了一套Swarm集羣,部署了複製服務然後建立了全局服務。
在將Docker Swarm Mode服務與Kubernetes服務進行比較時,咱們發現Swarm Mode服務的設置與建立更爲簡便易行。若是你們須要使用Kubernetes的「服務」功能但又用不到其它機制,那麼Docker Swarm Mode多是更爲理想的便捷選項。
(文章轉自:CODESHIP,做者 Ben Cane)