docker swarm是docker官方提供的一套容器編排系統(tǒng)。它的架構(gòu)如下:
1. swarm節(jié)點(diǎn)
swarm是一系列節(jié)點(diǎn)的集合钳恕,而節(jié)點(diǎn)可以是一臺(tái)裸機(jī)或者一臺(tái)虛擬機(jī)。一個(gè)節(jié)點(diǎn)能扮演一個(gè)或者兩個(gè)角色课舍,manager或者worker霹俺。
1.1 manager節(jié)點(diǎn)
Docker Swarm集群需要至少一個(gè)manager節(jié)點(diǎn),節(jié)點(diǎn)之間使用Raft consensus protocol
進(jìn)行協(xié)同工作掰邢。
通常牺陶,第一個(gè)啟用docker swarm的節(jié)點(diǎn)將成為leader伟阔,后來(lái)加入的都是follower。當(dāng)前的leader如果掛掉掰伸,剩余的節(jié)點(diǎn)將重新選舉出一個(gè)新的leader皱炉。
每一個(gè)manager都有一個(gè)完整的當(dāng)前集群狀態(tài)的副本,可以保證manager的高可用碱工。
1.2 worker節(jié)點(diǎn)
worker節(jié)點(diǎn)是運(yùn)行實(shí)際應(yīng)用服務(wù)的容器所在的地方娃承。理論上,一個(gè)manager節(jié)點(diǎn)也能同時(shí)成為worker節(jié)點(diǎn)怕篷,但在生產(chǎn)環(huán)境中历筝,我們不建議這樣做。
worker節(jié)點(diǎn)之間廊谓,通過(guò)control plane
進(jìn)行通信梳猪,這種通信使用gossip
協(xié)議,并且是異步的蒸痹。
2. stacks, services, and tasks
集群中經(jīng)常談到的stacks, services, tasks春弥,他們之間的關(guān)系。
下面簡(jiǎn)單解釋一下這三者的含義:
2.1 services
swarm service是一個(gè)抽象的概念叠荠,它只是一個(gè)對(duì)運(yùn)行在swarm集群上的應(yīng)用服務(wù)匿沛,所期望狀態(tài)的描述。它就像一個(gè)描述了下面物品的清單列表一樣:
- 服務(wù)名稱(chēng)
- 使用哪個(gè)鏡像來(lái)創(chuàng)建容器
- 要運(yùn)行多少個(gè)副本
- 服務(wù)的容器要連接到哪個(gè)網(wǎng)絡(luò)上
- 應(yīng)該映射哪些端口
2.2 task
在Docker Swarm中榛鼎,task是一個(gè)部署的最小單元逃呼,task與容器是一對(duì)一的關(guān)系。
2.3 stack
stack是描述一系列相關(guān)services的集合者娱。我們通過(guò)在一個(gè)YAML文件中來(lái)定義一個(gè)stack抡笼。
3. 多主機(jī)網(wǎng)絡(luò)
在前面的章節(jié)中,我們學(xué)習(xí)過(guò)單主機(jī)網(wǎng)絡(luò)黄鳍,那個(gè)時(shí)候所有的容器都運(yùn)行在一個(gè)docker host上推姻,他們之間的通信一般使用本地的bridge網(wǎng)絡(luò)即可。
在Swarm集群中框沟,我們使用前面也簡(jiǎn)單提到過(guò)的overlay network driver來(lái)讓位于不同主機(jī)間的容器進(jìn)行通信藏古。網(wǎng)絡(luò)模式如下圖:
當(dāng)然你也可以使用第三方提供的其他網(wǎng)絡(luò)驅(qū)動(dòng),但對(duì)于swarm忍燥,還是推薦它自己的overlay network校翔。
4. 實(shí)戰(zhàn)
4.1 創(chuàng)建一個(gè)單一節(jié)點(diǎn)的swarm
創(chuàng)建一個(gè)docker swarm非常簡(jiǎn)單,現(xiàn)在假設(shè)我們只有一臺(tái)服務(wù)器(裸機(jī)或者虛擬機(jī)都行)灾前。運(yùn)行命令docker swarm init
防症,就可以創(chuàng)建一個(gè)swarm集群,并讓它成為manager leader:
[root@node2 ~]# docker swarm init
Swarm initialized: current node (pvj7k2urt8g5k1ucsao2rpiwu) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2121w9nkk2qsyrgg477bz2jq26iojd5u1agdfa2b0bi8wxi3rk-00octanaf09agpe9v77nsm670 10.10.10.73:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
上面也告訴了你,如何添加一個(gè)新的manager或者worker蔫敲。
查看swarm node信息:
[root@node2 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
pvj7k2urt8g5k1ucsao2rpiwu * node2.xxx.com Ready Active Leader 18.06.1-ce
[root@node2 ~]# docker node inspect pvj7k2urt8g5k1ucsao2rpiwu
4.2 使用virtualbox來(lái)創(chuàng)建一個(gè)swarm集群
上一章Docker Machine饲嗽,我們講到過(guò),可以使用docker machine結(jié)合virtualbox來(lái)創(chuàng)建多臺(tái)docker虛擬機(jī)奈嘿。下面我們進(jìn)行實(shí)踐:
之前貌虾,我們使用docker-machine create --driver virtualbox default
已經(jīng)創(chuàng)建了一臺(tái)虛擬機(jī)。
[root@node2 ~]# docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v18.06.1-ce
通過(guò)上面方式創(chuàng)建的虛擬機(jī)裙犹,默認(rèn)都將分配1G的內(nèi)存尽狠。后面創(chuàng)建多臺(tái)虛擬機(jī)時(shí),請(qǐng)確保你的實(shí)驗(yàn)機(jī)器有足夠的內(nèi)存叶圃。
1袄膏、創(chuàng)建5臺(tái)虛擬機(jī)
[root@node2 ~]# for NODE in `seq 1 5`; do docker-machine create --driver virtualbox "node-${NODE}"; done
整個(gè)過(guò)程需要一段時(shí)間,請(qǐng)耐心等待掺冠。創(chuàng)建完成后可以通過(guò)docker-machine ls
查看沉馆。
[root@node2 ~]# docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v18.06.1-ce
node-1 - virtualbox Running tcp://192.168.99.101:2376 v18.06.1-ce
node-2 - virtualbox Running tcp://192.168.99.102:2376 v18.06.1-ce
node-3 - virtualbox Running tcp://192.168.99.103:2376 v18.06.1-ce
node-4 - virtualbox Running tcp://192.168.99.104:2376 v18.06.1-ce
node-5 - virtualbox Running tcp://192.168.99.105:2376 v18.06.1-ce
2、創(chuàng)建swarm集群
按照下面的腳本創(chuàng)建swarm集群德崭,當(dāng)然你也可以用命令手動(dòng)逐個(gè)創(chuàng)建:
#!/bin/bash
# 這個(gè)腳本用于在創(chuàng)建了5個(gè)docker虛擬機(jī)之后斥黑,創(chuàng)建swarm集群。
# 集群內(nèi)配置如下:node-1為manager leader眉厨,node-2和node-3為manager follower
# node-4和node-5為worker
export IP=$(docker-machine ip node-1)
#ssh登錄到node-1锌奴,讓他成為swarm leader
docker-machine ssh node-1 docker swarm init --advertise-addr $IP
#獲取leader的token,方便后面其他主機(jī)加入
export JOIN_TOKEN=$(docker-machine ssh node-1 docker swarm join-token worker -q)
for NODE in `seq 2 5`
do
docker-machine ssh node-${NODE} docker swarm join --token ${JOIN_TOKEN} ${IP}:2377
done
#將node-2和node-3主機(jī)提權(quán)為manager
docker-machine ssh node-1 docker node promote node-2 node-3
完成后憾股,可以在node-1上查看當(dāng)前集群節(jié)點(diǎn)信息
[root@node2 swarm]# docker-machine ssh node-1 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
zycyeyod3fctve54efs9oms55 * node-1 Ready Active Leader 18.06.1-ce
cwerk7kvtxybp7fgkicpgxe4y node-2 Ready Active Reachable 18.06.1-ce
l3dtf4l64z3bm5eb1sb4uuq2x node-3 Ready Active Reachable 18.06.1-ce
wg5ptfk4suctqvndjo81dqewq node-4 Ready Active 18.06.1-ce
wcog4ty7anqdixgm5n7ta8bxb node-5 Ready Active 18.06.1-ce
3鹿蜀、在集群上部署一個(gè)單service的stack
現(xiàn)在我們可以使用這5臺(tái)虛擬機(jī)組成的集群,來(lái)實(shí)踐一個(gè)案例了荔燎。
前面我們提到過(guò)耻姥,一個(gè)stack才是所有相關(guān)services的集合销钝,組成一個(gè)完整的應(yīng)用服務(wù)有咨。可以通過(guò)yaml文本來(lái)定義一個(gè)stack:
version: "3.5"
services:
whoami:
image: training/whoami:latest
networks:
- test-net
ports:
- 81:8000
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
labels:
app: sample-app
enviroment: prod-south
networks:
test-net:
driver: overlay
解讀:
- 服務(wù)的名稱(chēng)叫
whoami
蒸健。 - 使用的鏡像為
training/whoami:latest
座享。 - 使用了一個(gè)自定的網(wǎng)絡(luò)
test-net
。 - 將主機(jī)端口81映射至容器內(nèi)的8000端口似忧。
- 運(yùn)行6個(gè)副本(也就是task渣叛,也對(duì)應(yīng)6個(gè)容器)
- 升級(jí)策略:每2個(gè)task為一組進(jìn)行升級(jí),且當(dāng)前組升級(jí)成功后盯捌,延遲10秒才開(kāi)始升級(jí)下一組淳衙。
- 定義了兩個(gè)標(biāo)簽。
實(shí)際上,還有很多其他的設(shè)置箫攀,我們這里沒(méi)有列出來(lái)肠牲,它們都有自己的默認(rèn)值。
請(qǐng)注意靴跛,services里面各個(gè)service的名字在swarm中必須唯一缀雳。
現(xiàn)在,我們使用這個(gè)配置文件來(lái)部署我們的一個(gè)集群服務(wù)吧:
# 為了更直觀的查看過(guò)程梢睛,我們可以登錄到manager leader上進(jìn)行部署
[root@node2 swarm]# docker-machine ssh node-1
# 在manager leader上創(chuàng)建上面的yaml文件
docker@node-1:~$ vi stack.yaml
docker@node-1:~$ docker stack deploy -c stack.yaml samle-stack
# 創(chuàng)建過(guò)程需要一定的時(shí)間肥印,請(qǐng)耐心等待
docker@node-1:~$ docker stack ls
NAME SERVICES ORCHESTRATOR
samle-stack 1 Swarm
docker@node-1:~$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
mjx5rdvluyeb samle-stack_whoami replicated 6/6 training/whoami:latest *:81->8000/tcp
在docker stack deploy
執(zhí)行完成后,我使用docker service ls
命令绝葡,剛開(kāi)始在REPLICAS那一欄始終都是看到3/6深碱,代表只啟動(dòng)了3個(gè)task,但是實(shí)際應(yīng)該啟動(dòng)6個(gè)挤牛。過(guò)一段時(shí)候之后莹痢,我再次查看發(fā)現(xiàn)就是6個(gè)都啟動(dòng)了。我當(dāng)時(shí)猜測(cè)墓赴,有些node可能是拉取鏡像的時(shí)候超時(shí)了竞膳,導(dǎo)致沒(méi)有完全啟動(dòng),下面命令的輸出也印證了我的猜測(cè)诫硕。node1坦辟、2、5都自動(dòng)創(chuàng)建了一個(gè)新的task章办。
docker@node-1:~$ docker service ps samle-stack_whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
35gp71dh9sgl samle-stack_whoami.1 training/whoami:latest node-4 Running Running 36 minutes ago
b79jr4suvuc2 samle-stack_whoami.2 training/whoami:latest node-5 Running Running 29 minutes ago
noferwnjjr5s \_ samle-stack_whoami.2 training/whoami:latest node-5 Shutdown Rejected 29 minutes ago "No such image: training/whoam…"
wd59fklp6ayg samle-stack_whoami.3 training/whoami:latest node-1 Running Running 29 minutes ago
z0gxnngq5ipt \_ samle-stack_whoami.3 training/whoami:latest node-1 Shutdown Rejected 29 minutes ago "No such image: training/whoam…"
zcf9x5c61a6f samle-stack_whoami.4 training/whoami:latest node-2 Running Running 29 minutes ago
lb3plbt9b3c2 \_ samle-stack_whoami.4 training/whoami:latest node-2 Shutdown Rejected 29 minutes ago "No such image: training/whoam…"
xfxk4ngiggf3 samle-stack_whoami.5 training/whoami:latest node-3 Running Running 36 minutes ago
m647fsycr4rx samle-stack_whoami.6 training/whoami:latest node-4 Running Running 36 minutes ago
查看node-1節(jié)點(diǎn)上運(yùn)行的容器
docker@node-1:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39c616331871 training/whoami:latest "/app/http" 33 minutes ago Up 33 minutes 8000/tcp samle-stack_whoami.3.wd59fklp6aygpua8289gt978l
查看服務(wù)的詳細(xì)信息
docker@node-1:~$ docker service inspect samle-stack_whoami
查看services的日志:
docker@node-1:~$ docker service logs samle-stack_whoami
samle-stack_whoami.4.zcf9x5c61a6f@node-2 | Listening on :8000
samle-stack_whoami.6.m647fsycr4rx@node-4 | Listening on :8000
samle-stack_whoami.1.35gp71dh9sgl@node-4 | Listening on :8000
samle-stack_whoami.2.b79jr4suvuc2@node-5 | Listening on :8000
samle-stack_whoami.5.xfxk4ngiggf3@node-3 | Listening on :8000
samle-stack_whoami.3.wd59fklp6ayg@node-1 | Listening on :8000
下面我們來(lái)看看集群的高可用锉走,和狀態(tài)一致性(意思是集群始終會(huì)保持你所期待的樣子),通過(guò)上面的輸出藕届,我們可以看到在node-4上是運(yùn)行了2個(gè)容器的挪蹭,我們手動(dòng)的刪除一個(gè)容器看看:
docker@node-4:~$ docker container rm -f samle-stack_whoami.6.m647fsycr4rxk2epx542bx8n6
samle-stack_whoami.6.m647fsycr4rxk2epx542bx8n6
我們刪除的是編號(hào)為6的容器,samle-stack_whoami.6
以上命令顯示休偶,在node-1上重新啟用了一個(gè)新的容器梁厉,名稱(chēng)為:samle-stack_whoami.6。
除了像上面這樣踏兜,可能某個(gè)容器出現(xiàn)問(wèn)題词顾。但有些時(shí)候,也有可能出現(xiàn)某個(gè)節(jié)點(diǎn)故障碱妆,我們可以用如下命令模擬節(jié)點(diǎn)故障:
docker-machine stop node-2
相應(yīng)的node-2上的task就都會(huì)自動(dòng)轉(zhuǎn)移到其他主機(jī)上肉盹。
刪除一個(gè)stack或者service可以使用如下命令:
docker stack rm
,將會(huì)刪除整個(gè)stack以及service疹尾,還有主機(jī)上的task上忍。
docker service rm
骤肛,會(huì)刪除service,還有主機(jī)上的task窍蓝。
4萌衬、在集群上部署一個(gè)多service的stack
上面的示例在services中只有一個(gè)service卵沉,下面我們演示一個(gè)多service的中符。
stack配置文件為:
version: "3.5"
services:
web:
image: fundamentalsofdocker/ch08-web:1.0
networks:
- pets-net
ports:
- 3000:3000
deploy:
replicas: 3
db:
image: fundamentalsofdocker/ch08-db:1.0
networks:
- pets-net
volumes:
- pets-data:/var/lib/postgresql/data
volumes:
pets-data:
networks:
pets-net:
driver: overlay
實(shí)際在node-1上運(yùn)行:
docker@node-1:~$ docker stack deploy -c pet_stack.yaml pets_web
Creating network pets_web_pets-net
Creating service pets_web_web
Creating service pets_web_db
docker@node-1:~$ docker stack ls
NAME SERVICES ORCHESTRATOR
pets_web 2 Swarm
docker@node-1:~$ docker stack ps pets_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
t4sl5hmq4xbr pets_web_db.1 fundamentalsofdocker/ch08-db:1.0 node-4 Running Running 7 minutes ago
arqpt9p3bqws pets_web_web.1 fundamentalsofdocker/ch08-web:1.0 node-2 Running Running 7 minutes ago
k05n7x67kmig \_ pets_web_web.1 fundamentalsofdocker/ch08-web:1.0 node-2 Shutdown Rejected 7 minutes ago "No such image: fundamentalsof…"
sivxrv71npj1 pets_web_web.2 fundamentalsofdocker/ch08-web:1.0 node-3 Running Running 13 minutes ago
bw2h8z3yd3p0 pets_web_web.3 fundamentalsofdocker/ch08-web:1.0 node-1 Running Running 13 minutes ago
和上一小節(jié)區(qū)別不大,下面我們驗(yàn)證一下web服務(wù)是否可用霎褐。
docker@node-1:~$ curl http://localhost:3000/pet
<html>
<head>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<h4>Cat Gif of the day</h4>
<img src="http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-25158-1381844793-0.gif"" />
<p><small>Courtesy: <a >Buzzfeed</a></small></p>
<p>Delivered to you by container 8c6780b1b264<p>
</div>
</body>
4.3 swarm的路由網(wǎng)絡(luò)
對(duì)于上面最后一步的驗(yàn)證過(guò)程观蓄,我們可以看到3個(gè)web的task分別運(yùn)行在node1混移、2、3上侮穿,但為什么能夠在node-1節(jié)點(diǎn)上通過(guò)localhost來(lái)訪問(wèn)web服務(wù)歌径,并且得到從node-2上的容器返回的結(jié)果呢?這一切都?xì)w功于swarm routing mesh
亲茅,它的工作原理如下圖:
對(duì)于每一個(gè)service回铛,docker swarm都會(huì)自動(dòng)的給它分配一個(gè)virtual IP,對(duì)外暴露的也是這個(gè)VIP克锣,當(dāng)有數(shù)據(jù)請(qǐng)求達(dá)到VIP時(shí)茵肃,它會(huì)進(jìn)行負(fù)載均衡,將請(qǐng)求分配到某一個(gè)實(shí)際正在運(yùn)行task的節(jié)點(diǎn)上袭祟。