Docker Swarm架構、特性與基本實踐

Docker集羣管理和編排的特性是經過SwarmKit進行構建的, 其中Swarm mode是Docker Engine內置支持的一種默認實現。Docker 1.12以及更新的版本,都支持Swarm mode,咱們能夠基於Docker Engine來構建Swarm集羣,而後就能夠將咱們的應用服務(Application Service)部署到Swarm集羣中。建立Swarm集羣的方式很簡單,先初始化一個Swarm集羣,而後將其餘的Node加入到該集羣便可。本文主要基於Docker Swarm官網文檔,學習總結。
基本特性
Docker Swarm具備以下基本特性:
集羣管理集成進Docker Engine前端

使用內置的集羣管理功能,咱們能夠直接經過Docker CLI命令來建立Swarm集羣,而後去部署應用服務,而再也不須要其它外部的軟件來建立和管理一個Swarm集羣。
去中心化設計node

Swarm集羣中包含Manager和Worker兩類Node,咱們能夠直接基於Docker Engine來部署任何類型的Node。並且,在Swarm集羣運行期間,咱們既能夠對其做出任何改變,實現對集羣的擴容和縮容等,如添加Manager Node,如刪除Worker Node,而作這些操做不須要暫停或重啓當前的Swarm集羣服務。
聲明式服務模型(Declarative Service Model)linux

在咱們實現的應用棧中,Docker Engine使用了一種聲明的方式,讓咱們能夠定義咱們所指望的各類服務的狀態,例如,咱們建立了一個應用服務棧:一個Web前端服務、一個後端數據庫服務、Web前端服務又依賴於一個消息隊列服務。
服務擴容縮容nginx

對於咱們部署的每個應用服務,咱們能夠經過命令行的方式,設置啓動多少個Docker容器去運行它。已經部署完成的應用,若是有擴容或縮容的需求,只須要經過命令行指定須要幾個Docker容器便可,Swarm集羣運行時便能自動地、靈活地進行調整。
協調預期狀態與實際狀態的一致性web

Swarm集羣Manager Node會不斷地監控集羣的狀態,協調集羣狀態使得咱們預期狀態和實際狀態保持一致。例如咱們啓動了一個應用服務,指定服務副本爲10,則會啓動10個Docker容器去運行,若是某個Worker Node上面運行的2個Docker容器掛掉了,則Swarm Manager會選擇集羣中其它可用的Worker Node,並建立2個服務副本,使實際運行的Docker容器數仍然保持與預期的10個一致。
多主機網絡redis

咱們能夠爲待部署應用服務指定一個Overlay網絡,當應用服務初始化或者進行更新時,Swarm Manager在給定的Overlay網絡中爲Docker容器自動地分配IP地址,實際是一個虛擬IP地址(VIP)。
服務發現docker

Swarm Manager會給集羣中每個服務分配一個惟一的DNS名稱,對運行中的Docker容器進行負載均衡。咱們能夠經過Swarm內置的DNS Server,查詢Swarm集羣中運行的Docker容器狀態。
負載均衡數據庫

在Swarm內部,能夠指定如何在各個Node之間分發服務容器(Service Container),實現負載均衡。若是想要使用Swarm集羣外部的負載均衡器,能夠將服務容器的端口暴露到外部。
安全策略後端

在Swarm集羣內部的Node,強制使用基於TLS的雙向認證,而且在單個Node上以及在集羣中的Node之間,都進行安全的加密通訊。咱們能夠選擇使用自簽名的根證書,或者使用自定義的根CA(Root CA)證書。
滾動更新(Rolling Update)安全

對於服務須要更新的場景,咱們能夠在多個Node上進行增量部署更新,Swarm Manager支持經過使用Docker CLI設置一個delay時間間隔,實現多個服務在多個Node上依次進行部署。這樣能夠很是靈活地控制,若是有一個服務更新失敗,則暫停後面的更新操做,從新回滾到更新以前的版本。
基本架構
Docker Swarm提供了基本的集羣能力,可以使多個Docker Engine組合成一個group,提供多容器服務。Swarm使用標準的Docker API,啓動容器能夠直接使用docker run命令。Swarm更核心的則是關注如何選擇一個主機並在其上啓動容器,最終運行服務。
Docker Swarm基本架構,以下圖所示(來自網絡,詳見後面參考連接):
Docker Swarm架構、特性與基本實踐

如上圖所示,Swarm Node表示加入Swarm集羣中的一個Docker Engine實例,基於該Docker Engine能夠建立並管理多個Docker容器。其中,最開始建立Swarm集羣的時候,Swarm Manager即是集羣中的第一個Swarm Node。在全部的Node中,又根據其職能劃分爲Manager Node和Worker Node,具體分別以下所示:

Manager Node

Manager Node負責調度Task,一個Task表示要在Swarm集羣中的某個Node上啓動Docker容器,一個或多個Docker容器運行在Swarm集羣中的某個Worker Node上。同時,Manager Node還負責編排容器和集羣管理功能(或者更準確地說,是具備Manager管理職能的Node),維護集羣的狀態。須要注意的是,默認狀況下,Manager Node也做爲一個Worker Node來執行Task。Swarm支持配置Manager只做爲一個專用的管理Node,後面咱們會詳細說明。
Worker Node

Worker Node接收由Manager Node調度並指派的Task,啓動一個Docker容器來運行指定的服務,而且Worker Node須要向Manager Node彙報被指派的Task的執行狀態。
構建Swarm集羣
咱們實踐Swarm集羣,包括三個節Node,對應的主機名和IP地址分別以下所示:
manager 192.168.1.107worker1 192.168.1.108worker2 192.168.1.109
首先,須要保證各個Node上,docker daemon進程已經正常啓動,若是沒有則執行以下命令啓動:
systemctl start docker
接下來就能夠建立Swarm集羣,建立Swarm的命令,格式以下所示:
docker swarm init --advertise-addr <MANAGER-IP>
咱們在準備好的manager Node上,登陸到該Node,建立一個Swarm,執行以下命令:
docker swarm init --advertise-addr 192.168.1.107
上面–advertise-addr選項指定Manager Node會publish它的地址爲192.168.1.107,後續Worker Node加入到該Swarm集羣,必需要可以訪問到Manager的該IP地址。能夠看到,上述命令執行結果,以下所示:
Swarm initialized: current node (5pe2p4dlxku6z2a6jnvxc4ve6) is now a manager.To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-4dm09nzp3xic15uebqja69o2552b75pcg7or0g9t2eld9ehqt3-1kb79trnv6fbydvl9vif3fsch \ 192.168.1.107:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
該結果中給出了後續操做引導信息,告訴咱們如何將一個Worker Node加入到Swarm集羣中。也能夠經過以下命令,來獲取該提示信息:
docker swarm join-token worker
在任什麼時候候,若是咱們須要向已經建立的Swarm集羣中增長Worker Node,只要新增一個主機(物理機、雲主機等均可以),並在其上安裝好Docker Engine並啓動,而後執行上述docker swarm join命令,就能夠加入到Swarm集羣中。
這時,咱們也能夠查看當前Manager Node的基本信息,執行docker info命令,輸出信息中能夠看到,包含以下關於Swarm的狀態信息:
Swarm: active NodeID: qc42f6myqfpoevfkrzmx08n0r Is Manager: true ClusterID: qi4i0vh7lgb60qxy3mdygb27f Managers: 1 Nodes: 1
能夠看出,目前Swarm集羣只有Manager一個Node,並且狀態是active。也能夠在Manager Node上執行docker node ls命令查看Node狀態,以下所示:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUSqc42f6myqfpoevfkrzmx08n0r manager Ready Active Leader
接下來,咱們能夠根據上面提示信息,咱們分別在worker一、worker2兩個Worker Node 上,執行命令將Worker Node加入到Swarm集羣中,命令以下所示:
docker swarm join \ --token SWMTKN-1-4dm09nzp3xic15uebqja69o2552b75pcg7or0g9t2eld9ehqt3-1kb79trnv6fbydvl9vif3fsch \ 192.168.1.107:2377
若是成功,能夠看到成功加入Swarm集羣的信息。這時,也能夠在Manager Node上,查看Swarm集羣的信息,示例以下所示:
Swarm: active NodeID: qc42f6myqfpoevfkrzmx08n0r Is Manager: true ClusterID: qi4i0vh7lgb60qxy3mdygb27f Managers: 1 Nodes: 3
想要查看Swarm集羣中所有Node的詳細狀態信息,能夠執行以下所示命令:
docker node ls
Swarm集羣Node的狀態信息,以下所示:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUSoibbiiwrgwjkw0ni38ydrfsre worker1 Ready Active oocli2uzdt2hy6o50g5z6j7dq worker2 Ready Active qc42f6myqfpoevfkrzmx08n0r
manager Ready Active Leader
上面信息中,AVAILABILITY表示Swarm Scheduler是否能夠向集羣中的某個Node指派Task,對應有以下三種狀態:
Active:集羣中該Node能夠被指派Task
Pause:集羣中該Node不能夠被指派新的Task,可是其餘已經存在的Task保持運行
Drain:集羣中該Node不能夠被指派新的Task,Swarm Scheduler停掉已經存在的Task,並將它們調度到可用的Node上

查看某一個Node的狀態信息,能夠在該Node上執行以下命令:
docker node inspect self
咱們在Manager Node上執行上述命令,查看的狀態信息以下所示:
[ { "ID": "qc42f6myqfpoevfkrzmx08n0r", "Version": { "Index": 9 }, "CreatedAt": "2017-03-12T15:25:51.725341879Z", "UpdatedAt": "2017-03-12T15:25:51.84308356Z", "Spec": { "Role": "manager", "Availability": "active" }, "Description": { "Hostname": "manager", "Platform": { "Architecture": "x86_64", "OS": "linux" }, "Resources": { "NanoCPUs": 1000000000, "MemoryBytes": 1912082432 }, "Engine": { "EngineVersion": "17.03.0-ce", "Plugins": [ { "Type": "Network", "Name": "bridge" }, { "Type": "Network", "Name": "host" }, { "Type": "Network", "Name": "macvlan" }, { "Type": "Network", "Name": "null" }, { "Type": "Network", "Name": "overlay" }, { "Type": "Volume", "Name": "local" } ] } }, "Status": { "State": "ready", "Addr": "127.0.0.1" }, "ManagerStatus": { "Leader": true, "Reachability": "reachable", "Addr": "192.168.1.107:2377" } }]
管理Swarm Node
Swarm支持設置一組Manager Node,經過支持多Manager Node實現HA。那麼這些Manager Node之間的狀態的一致性就很是重要了,多Manager Node的Warm集羣架構,以下圖所示(出自Docker官網):
Docker Swarm架構、特性與基本實踐

經過上圖能夠看到,Swarm使用了Raft協議來保證多個Manager之間狀態的一致性。基於Raft協議,Manager Node具備必定的容錯功能,假設Swarm集羣中有個N個Manager Node,那麼整個集羣能夠容忍最多有(N-1)/2個節點失效。若是是一個三Manager Node的Swarm集羣,則最多隻能容忍一個Manager Node掛掉。
下面,咱們按照對Node的不一樣操做,經過命令的方式來詳細說明:

(1)Node狀態變動管理
前面咱們已經提到過,Node的AVAILABILITY有三種狀態:Active、Pause、Drain,對某個Node進行變動,能夠將其AVAILABILITY值經過Docker CLI修改成對應的狀態便可,下面是常見的變動操做:
設置Manager Node只具備管理功能
對服務進行停機維護,能夠修改AVAILABILITY爲Drain狀態
暫停一個Node,而後該Node就再也不接收新的Task
恢復一個不可用或者暫停的Node

例如,將Manager Node的AVAILABILITY值修改成Drain狀態,使其只具有管理功能,執行以下命令:
docker node update --availability drain manager
這樣,Manager Node不能被指派Task,也就是不能部署實際的Docker容器來運行服務,而只是做爲管理Node的角色。
(2)給Node添加標籤元數據
每一個Node的主機配置狀況可能不一樣,好比有的適合運行CPU密集型應用,有的適合運行IO密集型應用,Swarm支持給每一個Node添加標籤元數據,這樣能夠根據Node的標籤,來選擇性地調度某個服務部署到指望的一組Node上。
給SWarm集羣中的某個Worker Node添加標籤,執行以下命令格式以下:
docker node update --label-add 鍵名稱=值
例如,worker1主機在名稱爲bjidc這個數據中心,執行以下命令添加標籤:
docker node update --label-add datacenter=bjidc
(3)Node提權/降權
改變Node的角色,Worker Node能夠變爲Manager Node,這樣實際Worker Node有工做Node變成了管理Node,對應提權操做,例如將worker1和worker2都升級爲Manager Node,執行以下命令:
docker node promote worker1 worker2
對上面已提權的worker1和worker2執行降權,須要執行以下命令:
docker node demote worker1 worker2
(4)退出Swarm集羣
若是Manager想要退出Swarm集羣, 在Manager Node上執行以下命令:
docker swarm node leave
就能夠退出集羣,若是集羣中還存在其它的Worker Node,還但願Manager退出集羣,則加上一個強制選項,命令行以下所示:
docker swarm node leave --force
一樣,若是Worker想要退出Swarm集羣,在Worker Node上,執行以下命令:
docker swarm node leave
即便Manager已經退出SWarm集羣,執行上述命令也可使得Worker Node退出集羣,而後又能夠加入到其它新建的Swarm集羣中。
管理服務
在Swarm集羣上部署服務,必須在Manager Node上進行操做。先說明一下Service、Task、Container(容器)這個三個概念的關係,以下圖(出自Docker官網)很是清晰地描述了這個三個概念的含義:

Docker Swarm架構、特性與基本實踐

在Swarm mode下使用Docker,能夠實現部署運行服務、服務擴容縮容、刪除服務、滾動升級等功能,下面咱們詳細說明。

(1)建立服務
建立Docker服務,可使用docker service create命令實現,例如,咱們要建立以下兩個服務,執行以下命令:
docker service create --replicas 1 --name myapp alpine ping shiyanjun.cndocker service create --replicas 2 --name myredis redis
第一個命令行,從Docker鏡像alpine建立了一個名稱爲myapp的服務,其中指定服務副本數爲1,也就是啓動一個Docker容器來運行該服務。第二個命令行, 建立一個Redis服務,服務副本數爲2,那麼會啓動兩個Docker容器來運行myredis服務。查看當前,已經部署啓動的所有應用服務,執行以下命令:
docker service ls
執行結果,以下所示:
ID NAME MODE REPLICAS IMAGEkilpacb9uy4q myapp replicated 1/1 alpine:latestvf1kcgtd5byc myredis replicated 2/2 redis
也能夠查詢指定服務的詳細信息,執行以下命令:
docker service ps myredis
查看結果信息,以下所示:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS0p3r9zm2uxpl myredis.1 redis manager Running Running 48 seconds ago ty3undmoielo myredis.2 redis worker1 Running Running 44 seconds ago
上面信息中,在manager和worker1這兩個Node上部署了myredis這個應用服務,也包含了它們對應的當前狀態信息。此時,也能夠經過執行docker ps命令,在Manager Node上查看當前啓動的Docker容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES07f93f82a407 redis:latest "docker-entrypoint..." 7 minutes ago Up 7 minutes 6379/tcp myredis.1.0p3r9zm2uxple5i1e2mqgnl3r
在Worker1上查看當前啓動的Docker容器,也就是咱們的另外一個myredis實例在該Node上:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES41c31e96cccb redis:latest "docker-entrypoint..." 8 minutes ago Up 8 minutes 6379/tcp myredis.2.ty3undmoielo18g7pnvh0nutz
建立服務時,咱們能夠對運行時服務容器進行配置,例如以下命令:
docker service create --name helloworld \ --env MYVAR=myvalue \ --workdir /tmp \ --user my_user \ alpine ping docker.com
上面,經過 --env
選項來設置環境變量,經過 --workdir
選項來設置工做目錄,經過 --user
選項來設置用戶信息。
(2)擴容縮容服務
Docker Swarm支持服務的擴容縮容,Swarm經過 --mode
選項設置服務類型,提供了兩種模式:一種是replicated,咱們能夠指定服務Task的個數(也就是須要建立幾個冗餘副本),這也是Swarm默認使用的服務類型;另外一種是global,這樣會在Swarm集羣的每一個Node上都建立一個服務。以下圖所示(出自Docker官網),是一個包含replicated和global模式的Swarm集羣:

上圖中,×××表示的replicated模式下的Service Replicas,灰色表示global模式下Service的分佈。
服務擴容縮容,在Manager Node上執行命令的格式,以下所示:

docker service scale 服務ID=服務Task總數
例如,將前面咱們部署的2個副本的myredis服務,擴容到3個副本,執行以下命令:
docker service scale myredis=3
經過命令docker service ls 查看,擴容操做結果以下所示:
ID NAME MODE REPLICAS IMAGEkilpacb9uy4q myapp replicated 1/1 alpine:latestvf1kcgtd5byc myredis replicated 3/3 redis
進一步經過docker service ps myredis查看一下myredis的各個副本的狀態信息,以下所示:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS0p3r9zm2uxpl myredis.1 redis manager Running Running 14 minutes ago ty3undmoielo myredis.2 redis worker1 Running Running 14 minutes ago zxsvynsgqmpk myredis.3 redis worker2 Running Running less than a second ago
能夠看到,咱們目前3個Node的Swarm集羣,每一個Node上都有一個myredis應用服務的副本,可見也實現了很好的負載均衡。
縮容服務,只須要將副本數小於當前應用服務擁有的副本數便可實現,大於指定縮容副本數的副本會被刪除。
(3)刪除服務
刪除服務,只須要在Manager Node上執行以下命令便可:
docker service rm 服務ID
例如,刪除myredis應用服務,執行docker service rm myredis,則應用服務myredis的所有副本都會被刪除。
(4)滾動更新
服務的滾動更新,這裏我參考官網文檔的例子說明。在Manager Node上執行以下命令:
docker service create \ --replicas 3 \ --name redis \ --update-delay 10s \ redis:3.0.6
上面經過指定 --update-delay
選項,表示須要進行更新的服務,每次成功部署一個,延遲10秒鐘,而後再更新下一個服務。若是某個服務更新失敗,則Swarm的調度器就會暫停本次服務的部署更新。
另外,也能夠更新已經部署的服務所在容器中使用的Image的版本,例如執行以下命令:
docker service update --image redis:3.0.7 redis
將Redis服務對應的Image版本有3.0.6更新爲3.0.7,一樣,若是更新失敗,則暫停本次更新。
(5)添加Overlay網絡
在Swarm集羣中可使用Overlay網絡來鏈接到一個或多個服務。具體添加Overlay網絡,首先,咱們須要建立在Manager Node上建立一個Overlay網絡,執行以下命令:
docker network create --driver overlay my-network
建立完Overlay網絡my-network之後,Swarm集羣中全部的Manager Node均可以訪問該網絡。而後,咱們在建立服務的時候,只須要指定使用的網絡爲已存在的Overlay網絡便可,以下命令所示:
docker service create \ --replicas 3 \ --network my-network \ --name myweb \ nginx
這樣,若是Swarm集羣中其餘Node上的Docker容器也使用my-network這個網絡,那麼處於該Overlay網絡中的全部容器之間,經過網絡能夠連通。
參考連接
https://docs.docker.com/engine/swarm/
https://docs.docker.com/engine/swarm/swarm-mode/
https://docs.docker.com/engine/swarm/key-concepts/
https://docs.docker.com/engine/swarm/swarm-tutorial/
https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm/
https://docs.docker.com/engine/swarm/swarm-tutorial/add-nodes/
https://docs.docker.com/engine/swarm/swarm-tutorial/deploy-service/
https://docs.docker.com/engine/swarm/swarm-tutorial/inspect-service/
https://docs.docker.com/engine/swarm/swarm-tutorial/scale-service/
https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/
https://docs.docker.com/engine/swarm/manage-nodes/
https://docs.docker.com/engine/swarm/swarm_manager_locking/
https://docs.docker.com/engine/swarm/services/
https://docs.docker.com/engine/swarm/networking/
https://docs.docker.com/engine/swarm/admin_guide/
https://docs.docker.com/engine/swarm/raft/
https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/
https://docs.docker.com/engine/swarm/ingress/
https://platform9.com/blog/compare-kubernetes-vs-docker-swarm/

本文基於 署名-非商業性使用-相同方式共享 4.0 許可協議發佈,歡迎轉載、使用、從新發布,但務必保留文章署名時延軍(包含連接:http://shiyanjun.cn),不得用於商業目的,基於本文修改後的做品務必以相同的許可發佈

相關文章
相關標籤/搜索