本節(jié)主要學(xué)習(xí)渗蟹,如何在不終止服務(wù)的情況下雌芽,升級(jí)服務(wù)中的應(yīng)用等世落。
為了做到零終端,通常屉佳,我們應(yīng)用的部署策略有三種:
- Rolling updates 滾動(dòng)部署
- Blue-green deployments 藍(lán)綠部署
- Canary releases 金絲雀部署
三者的一些比較:
微服務(wù)部署:藍(lán)綠部署、滾動(dòng)部署圆凰、灰度發(fā)布等部署方案對(duì)比與總結(jié)
藍(lán)綠部署送朱、金絲雀發(fā)布(灰度發(fā)布)干旁、A/B測(cè)試的準(zhǔn)確定義
docker swarm默認(rèn)支持Rolling updates的開箱即用争群。其他兩種方式可通過擴(kuò)展支持玉雾。
1. 滾動(dòng)部署
關(guān)于原理部分可參考上面的鏈接轻要,下面我們進(jìn)行實(shí)踐复旬。
定義一個(gè)包含rolling update相關(guān)配置的stack,命名為rolling-update.yml:
version: "3.5"
services:
web:
image: nginx:1.13-alpine
ports:
- 8080:80
deploy:
replicas: 10
update_config:
parallelism: 2
delay: 10s
上面的大部分內(nèi)容之前都學(xué)習(xí)過冲泥,我們這里主要看update_config部分驹碍。上面的配置表示,一共會(huì)啟用10個(gè)task凡恍,在升級(jí)時(shí)志秃,每2個(gè)task會(huì)成為一組進(jìn)行升級(jí)操作,每一組升級(jí)成功之后嚼酝,間隔10s開始下一組的升級(jí)浮还。
1、開始部署上面的stack:
用docker stack deploy -c rolling-update.yml web
命令執(zhí)行部署闽巩,部署完成后钧舌,可以使用watch docker stack ps web
命令查看,剛開始可能如下圖驾荣,正在Preparing的一般是鏡像還沒有拉取下來撼班,要等到超時(shí)之后下一次重試(每次重試間隔大約5分鐘,應(yīng)該是可以進(jìn)行相關(guān)設(shè)置的。在我沒換國(guó)內(nèi)鏡像倉(cāng)庫(kù)之前失敗的次數(shù)更多缅阳,不過鏡像下載一次之后超棺,后續(xù)就不用下載了,部署起來速度很快)适肠。
所有的task都必須正常啟動(dòng)了之后麸俘,才能開始進(jìn)行下面的升級(jí)工作,如下:
2、升級(jí)上面的stack
執(zhí)行升級(jí)之前昌渤,建議再開一個(gè)窗口了赵,并且將docker-machine環(huán)境變量設(shè)置為node-1,然后執(zhí)行watch docker stack ps web
已烤,可以實(shí)時(shí)查看相關(guān)進(jìn)度躁绸。
執(zhí)行如下命令,升級(jí)上面stack中的nginx版本:
docker service update --image nginx:1.14-alpine web_web
可以看到就是每次兩個(gè)task進(jìn)行升級(jí)操作,其他task繼續(xù)提供服務(wù)。
3姜骡、測(cè)試完成管引,刪除stack
docker stack rm web
2. 健康檢查
有時(shí)候重慢,你在查看容器運(yùn)行的狀態(tài)時(shí)稽煤,它可能是顯示OK的狀態(tài),但容器內(nèi)的應(yīng)用是否OK,你這個(gè)時(shí)候還無法確定。因此,我們通常使用健康檢查來確定一個(gè)服務(wù)是否確實(shí)在正常運(yùn)行。
我們通常有兩種方式來定義健康檢查。
2.1 Dockerfile定義健康檢查
我們可以在制作鏡像時(shí)裂垦,就為鏡像內(nèi)的服務(wù)定義健康檢查午乓,通常如下:
FROM alpine:3.6
...
HEALTHCHECK --interval=30s \
--timeout=10s
--retries=3
--start-period=60s
CMD curl -f http://localhost:3000/health || exit 1
...
--start-period=60s
:通常服務(wù)的啟動(dòng)库快,需要一定時(shí)間蝶怔,在這段時(shí)間內(nèi)不會(huì)執(zhí)行健康檢查扎瓶。
--interval=30s
:每次檢查的時(shí)間間隔。
--timeout=10s
:每次檢查的超時(shí)時(shí)間。
--retries=3
:重試多少次后,認(rèn)為服務(wù)不可用诱贿。
CMD curl -f http://localhost:3000/health || exit 1
:通過在容器內(nèi)執(zhí)行什么命令墅诡,來檢查服務(wù)是否可用。
2.2 stack file文件內(nèi)定義健康檢查
一個(gè)示例如下:
version: "3.5"
services:
web:
image: nginx:alpine
healthcheck:
test: ["CMD", "wget", "-qO", "-", "http://localhost"]
interval: 5s
timeout: 2s
retries: 3
start_period: 15s
參數(shù)與上面的Dockerfile中的類似梭纹,需要注意的是:1滔蝉、你必須為每個(gè)service定義一個(gè)健康檢查名扛,而不是對(duì)整個(gè)stack進(jìn)行区拳。2、如果你的service所引用的鏡像內(nèi)已經(jīng)包含健康檢查欠啤,那么這里的定義會(huì)覆蓋它落塑。
部署上面的示例看看:
docker stack deploy -c stack-health.yml myapp
你會(huì)看到與之前有所不同的地方是矾睦,在STATUS欄赁温,多了個(gè)healthy。
3. 回滾操作
可能有多種原因造成新的版本,確實(shí)新版無法正常運(yùn)行的時(shí)候祭务,我們需要預(yù)定義好回滾操作。
一個(gè)配置示例如下:
version: "3.5"
services:
web:
image: nginx:1.12-alpine
ports:
- 80:80
deploy:
replicas: 10
update_config:
parallelism: 2
delay: 10s
failure_action: rollback
monitor: 10s
healthcheck:
test: ["CMD", "wget", "-qO", "-", "http://localhost"]
interval: 2s
timeout: 2s
retries: 3
start_period: 2s
通過前面的知識(shí)膨更,我們知道矗漾,一個(gè)task要被確認(rèn)為不健康的狀態(tài),需要的時(shí)間是:start_period + interval*retries
甫男,因此且改,這里需要8秒鐘。
monitor: 10s
:定義在一個(gè)task開始部署后板驳,需要對(duì)它持續(xù)監(jiān)控的時(shí)間又跛,用來決定是否進(jìn)行下一組的升級(jí)操作。因此若治,需要大于上面的8秒慨蓝。
failure_action: rollback
:該參數(shù)在默認(rèn)情況下,如果發(fā)現(xiàn)升級(jí)失敗端幼,那么會(huì)立即停止這次升級(jí)礼烈,并保持這個(gè)狀態(tài)退出升級(jí)(例如前面包含10個(gè)task,每次升級(jí)2個(gè)的service婆跑,會(huì)保持其余8個(gè)task還是運(yùn)行老舊版本的狀態(tài)此熬,并對(duì)外提供服務(wù))。而我們?nèi)绻渲脼?code>rollback值的話滑进,表示進(jìn)行回滾操作犀忱,那2個(gè)失敗的task會(huì)恢復(fù)運(yùn)行之前的版本,并提供服務(wù)扶关。
4. 密碼管理
我們經(jīng)常需要向容器內(nèi)傳遞一些敏感信息阴汇,例如最常見的密碼。我們可以通過-e參數(shù)來指定傳入的變量以及對(duì)應(yīng)的值节槐,但是搀庶,這樣我們的密碼就以明文形式暴露了。為了解決這個(gè)問題铜异,docker swarm 提供了 secret 機(jī)制地来。
secret需要由manager節(jié)點(diǎn)創(chuàng)建,并保存熙掺。worker需要使用的時(shí)候未斑,通過tmpFS
文件系統(tǒng)掛載使用。
4.1 創(chuàng)建密碼
從標(biāo)準(zhǔn)輸出創(chuàng)建:
echo "sample secret value" | docker secret create sample-secret -
讀取文件內(nèi)容創(chuàng)建:
docker secret create other-secret ~/my-secrets/secret-value.txt
查看當(dāng)前已有的密碼和審查:
[root@node2 swarm]# docker secret ls
ID NAME DRIVER CREATED UPDATED
ams8zjhm15z8qpfv9mgv5wrv9 sample-secret 7 seconds ago 7 seconds ago
[root@node2 swarm]# docker secret inspect sample-secret
[
{
"ID": "ams8zjhm15z8qpfv9mgv5wrv9",
"Version": {
"Index": 893
},
"CreatedAt": "2018-11-05T03:20:51.9911386Z",
"UpdatedAt": "2018-11-05T03:20:51.9911386Z",
"Spec": {
"Name": "sample-secret",
"Labels": {}
}
}
]
4.2 使用密碼
[root@node2 swarm]# docker service create --name web \
> --secret sample-secret \
> --publish 8000:8000 \
> fundamentalsofdocker/whoami:latest
jwwd32a5qbld0lviruneezcl5
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
[root@node2 swarm]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
jwwd32a5qbld web replicated 1/1 fundamentalsofdocker/whoami:latest *:8000->8000/tcp
[root@node2 swarm]# docker service ps web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
kd8jknn6llb6 web.1 fundamentalsofdocker/whoami:latest node-3 Running Running 47 seconds ago
[root@node2 swarm]# docker-machine ssh node-3
docker@node-3:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf2952b075cc fundamentalsofdocker/whoami:latest "/app/http" 2 minutes ago Up 2 minutes 8000/tcp web.1.kd8jknn6llb6vfgne68of5v01
docker@node-3:~$ docker container exec -it cf2952b075cc cat /run/secrets/sample-secret
sample secret value
以上操作為:
1币绩、創(chuàng)建一個(gè)使用了sample-secret
密碼的service蜡秽。
2府阀、查看對(duì)應(yīng)的task在哪個(gè)節(jié)點(diǎn)上,node-3芽突。
3试浙、登錄到node-3上,查看對(duì)應(yīng)的容器寞蚌。
4田巴、在容器內(nèi)執(zhí)行cat /run/secrets/sample-secret
,可以得到明文的密碼挟秤。
以上操作表明了壹哺,默認(rèn)會(huì)把密碼掛載到容器的/run/secrets/
目錄下。
當(dāng)然艘刚,你也可以通過--secret
參數(shù)管宵,把密碼掛載到容器的指定目錄下:
--secret source=sample-secret,target=/run/my-secrets/api-secret-key