Docker Swarm系列——3.Swarm服務升級
在這篇文章中,大家將會了解如何在不停止服務的情況下進行配置更改和映象更新。我們可以通過動態更新來控制服務的各種設定和選項。對於一些命令,Docker會停止、刪除、重建容器,因此,必須考慮到如果同時停止所有的容器所帶來的服務連線中斷和正常執行時長問題。
1. 限制資源
通過docker service update --help
檢視服務更新幫助:
Usage: docker service update [OPTIONS] SERVICE Update a service Options: --args command Service command args --config-add config Add or update a config file on a service --config-rm list Remove a configuration file --constraint-add list Add or update a placement constraint --constraint-rm list Remove a constraint --container-label-add list Add or update a container label --container-label-rm list Remove a container label by its key --credential-spec credential-spec Credential spec for managed service account (Windows only) -d, --detach Exit immediately instead of waiting for the service to converge ...
我們將服務中容器的可用資源進行一下限制,cpu=2, memory=512m
,防止單個容器使用太多宿主機資源,docker service update --limit-cpu 2 --limit-memory 512m http
:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 85837a185c45 nandy/show-host-info:v1 "/app" 14 seconds ago Up 9 seconds 80/tcp http.2.kzxixawhsrnqzyyg3hkn9x11l 972337b445fb nandy/show-host-info:v1 "/app" 18 seconds ago Up 14 seconds 80/tcp http.1.0ry6cxmpfozkvko3wb2fuzbmp b31a2e1f1a47 nandy/show-host-info:v1 "/app" 30 seconds ago Exited (2) 15 seconds ago http.1.l8e2qtwln1ratctrs9zq8l5as 20c7d4a6c0ae nandy/show-host-info:v1 "/app" 31 seconds ago Exited (2) 11 seconds ago http.2.mzwi4vdrzvauq0xijap3cax75
執行docker service inspect --pretty http
檢視結果:
Resources:
Limits:
CPU: 2
Memory: 512MiB
...
注意,更新服務的資源限制會導致容器重建。
2. 更新副本
不是所有的更新都需要重建容器,更新副本就不會影響已經在執行的容器。
在第一篇文章中,我們通過docker service scale http=6
擴充套件服務。在這裡,我們通過docker service update --replicas=6 http
將服務更新為6個副本。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a5fcff23f737 nandy/show-host-info:v1 "/app" 12 seconds ago Up 8 seconds 80/tcp http.5.fpvkua6wmlotkicluolzjzki8 b7427b1cf664 nandy/show-host-info:v1 "/app" 12 seconds ago Up 8 seconds 80/tcp http.4.llftjraazc2k7l9g9rxnbzeg5 638436cd0bb2 nandy/show-host-info:v1 "/app" 12 seconds ago Up 8 seconds 80/tcp http.6.j2peb7hu7etmzr362mtyxomyz 32498f45da7a nandy/show-host-info:v1 "/app" 12 seconds ago Up 9 seconds 80/tcp http.3.3058xfvf8gsvj9wq68dykayw4 3217d333835c nandy/show-host-info:v1 "/app" 4 minutes ago Up 4 minutes 80/tcp http.2.yjjje6vhzaiaxtbo953e0flnr 07a5dbd7693b nandy/show-host-info:v1 "/app" 4 minutes ago Up 4 minutes 80/tcp http.1.jhq7etce5dkdbgyxeu59qr1rc fe0360d436ae nandy/show-host-info:v1 "/app" 4 minutes ago Exited (2) 4 minutes ago http.2.qt0w7lco6dpe2hoxvwgoyltyk 8c71bf61823b nandy/show-host-info:v1 "/app" 4 minutes ago Exited (2) 4 minutes ago http.1.kwc4zbadbpau0cslwt8jp1kh9
通過STATUS
的啟動時間可以看出,服務額外建立了4個新的容器,已有的容器不變。我們執行docker container inspect http.6.j2peb7hu7etmzr362mtyxomyz
:
...
"Memory": 536870912,
"CpuQuota": 200000,
...
可以看到,新建立的容器,它的資源已被限制,因為服務的設定已經被更新。
3. 更新映象
一般來說,服務在被建立的時候,各種設定、引數、副本等都是考慮好的,不怎麼會再更新。因此,最常更新的便是映象了。每當釋出一個新版本的時候,我們只需要更新一下服務的映象便可。
執行docker service update --image nandy/show-host-info:v2 http
:
overall progress: 3 out of 6 tasks
1/6: ready [======================================> ]
2/6: running [==================================================>]
3/6:
4/6:
5/6: running [==================================================>]
6/6: running [==================================================>]
更新映象也會導致所有容器停止並重建。但仔細觀察stdout
,容器是一個一個停止並重建的。也就是說,只要服務的副本數大於1個(高可用),那麼服務在更新的同時依然會對外提供服務,從而達到永久可用。
4. 滾動升級
滾動升級的目的是為了在釋出新版本的時候服務不停止,通過設定服務中容器的並行和延遲建立,Docker可以批量更新,從而實現零停機時間。
--update-parallelism
定義了可以並行更新的數量,這取決於服務的併發量和副本數。
--update-delay
定義了每次更新之間的等待時間。如果應用有預熱時間,比如啟動JVM或預載入資料,等待時間將很有用,這能確保服務在所有容器重建完成之前,已經有容器可以處理請求。
這兩個引數既可以在服務建立的時候指定,也可以通過服務更新實現。接下來,我們設定“1次更新1個容器,間隔10秒”,並進行版本升級:
docker service update --update-delay=10s --update-parallelism=1 --image nandy/show-host-info:v2 http
通過stdout, docker ps, curl
,我們可以看到容器新的v2版本啟動並替換舊的的v1。
$ curl 172.17.0.15:80
{"version":"v2","hostname":"400a6b335676","address":"10.0.0.18"}
$ curl 172.17.0.15:80
{"version":"v2","hostname":"e5854c99c632","address":"10.0.0.17"}
$ curl 172.17.0.15:80
{"version":"v2","hostname":"2152a6f28cab","address":"10.0.0.16"}
$ curl 172.17.0.15:80
{"version":"v2","hostname":"c758241498ad","address":"10.0.0.15"}
$ curl 172.17.0.15:80
{"version":"v2","hostname":"102a0494ccc5","address":"10.0.0.14"}
$ curl 172.17.0.15:80
{"version":"v2","hostname":"23c886ed18aa","address":"10.0.0.13"}
可以看到,新的版本"version":"v2"
已經對外服務了。
最後思考一個問題:版本更新時,一個服務將會同時存在兩個版本的容器,這是否符合自己公司的業務邏輯?