該文為《深入淺出Docker》的學習筆記,感謝查看,如有錯誤,歡迎指正
一、簡介
Docker Stack 是為了解決大規模場景下的多服務部署和管理,提供了期望狀態
,滾動升級
,簡單易用
,擴縮容
,健康檢查
等特性,並且都封裝在一個聲明式模型當中。
- Docker Stack 部署應用的生命周期:
初始化部署 > 健康檢查 > 擴容 > 更新 > 回滾
。 - 使用單一聲明式文件即可完成部署,即只需要
docker-stack.yml
文件,使用docker stack deploy
命令即可完成部署。 - stack 文件其實就是 Docker compose 文件,唯一的要求就是 version 需要為 3.0 或者更高的值。
- Stack 完全集成到了 Docker 中,不像 compose 還需要單獨安裝。
Docker 適用於開發和測試,而 Docker Stack 則適用於大規模場景和生產環境
二、docker-stack.yml文件詳解
從 GitHub 中拉取示例代碼,分析其中的 docker-stack.yml
文件
[root@huanzi-001 daemon]# git clone https://github.com/dockersamples/atsea-sample-shop-app.git
可以看到有 5 個服務,3 個網絡,4 個秘鑰,3 組端口映射;
services:
reverse_proxy:
database:
appserver:
visualizer:
payment_gateway:
networks:
front-tier:
back-tier:
payment:
secrets:
postgres_password:
staging_token:
revprox_key:
revprox_cert:
2.1 網絡
Docker 根據 stack 文件部署的時候,第一步會檢查並創建 networks:關鍵字
對應的網絡。默認會創建覆蓋網絡(overlay),並且控制層會加密,如果需要對數據層加密,可以在 stack 文件的 driver_opts 之下指定 encrypted:'yes',數據層加密會導致額外開銷,但是一般不會超過10%。
networks:
front-tier:
back-tier:
payment:
driver: overlay
driver_opts:
encrypted: 'yes'
3 個網絡都會先於秘鑰和服務被創建
2.2 秘鑰
當前 Stack 文件中定義了 4 個秘鑰,並且都是external
,這表示在 Stack 部署前,這些秘鑰必須已存在
secrets:
postgres_password:
external: true
staging_token:
external: true
revprox_key:
external: true
revprox_cert:
external: true
2.3 服務
總共有 5 個服務,我們依次進行分析
2.3.1 reverse_proxy
服務
reverse_proxy:
image: dockersamples/atseasampleshopapp_reverse_proxy
ports:
- "80:80"
- "443:443"
secrets:
- source: revprox_cert
target: revprox_cert
- source: revprox_key
target: revprox_key
networks:
- front-tier
image
:必填項,指定了用於構建服務副本的 Docker 鏡像ports
:Swarm 節點的 80 端口映射到副本的 80 端口,443 端口映射到副本的 443 端口secrets
:2 個秘鑰以普通文件形式掛載至服務副本中,文件名稱就是 target 屬性的值,路徑為/run/secrets
networks
:所有副本都會連接到 front-tier 網絡,如果定義的網絡不存在,Docker 會以 Overlay 的網絡方式新建一個
2.3.2 database
服務
database:
image: dockersamples/atsea_db
environment:
POSTGRES_USER: gordonuser
POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
POSTGRES_DB: atsea
networks:
- back-tier
secrets:
- postgres_password
deploy:
placement:
constraints:
- 'node.role == worker'
多了以下幾項:
environment
:環境變量,定義了數據庫用戶,密碼位置,數據庫名稱deploy
:部署約束,服務只運行在 Swarm 集群的 Worker 節點上
Swarm 目前允許以下幾種部署約束方式:
- 節點 ID :
node.id == 85v90bioyy4s2fst4fa5vrlvf
- 節點名稱:
node.hostname == huanzi-002
- 節點角色:
node.role != manager
- 節點引擎標簽:
engine.labels.operatingsystem == Centos 7.5
- 節點自定義標簽:
node.labels.zone == test01
支持==
和!=
操作。
2.3.3 appserver
服務
appserver:
image: dockersamples/atsea_app
networks:
- front-tier
- back-tier
- payment
deploy:
replicas: 2
update_config:
parallelism: 2
failure_action: rollback
placement:
constraints:
- 'node.role == worker'
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
secrets:
- postgres_password
deploy-replicas
:部署的服務副本數量deploy-update_config
:滾動升級時的操作,每次更新 2 個副本(parallelism:2),升級失敗以后回滾(failure_action: rollback)failure_action
默認為 pause ,即服務升級失敗后阻止其它副本的升級,還支持 continuerestart_policy
:容器異常退出的重啟策略,當前策略為:如果某個副本以非 0 返回值退出(condition: on-failure),會立即重啟當前副本,重啟最多重試 3 次,每次最多等待 120s,每次重啟間隔是 5s。
2.3.4 visualizer
服務
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8001:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
update_config:
failure_action: rollback
placement:
constraints:
- 'node.role == manager'
stop_grace_period
:設置容器優雅停止時長(Docker 停止某個容器時,會給容器內 PID 為 1 的進程發送一個 SIGTERM 信號,容器內 PID 為 1 的進程有 10s 的優雅停止時長來執行清理操作)volumes
:掛載提前創建的卷或者主機目錄至某個服務副本中,本例中/var/run/docker.sock
為Docker 的 IPC 套接字,Docker daemon 通過該套接字對其它進程暴露 API 終端,如果某個容器有該文件的訪問權限,即允許該容器訪問所有的 API 終端,並且可以查詢及管理 Docker daemon。生產環境嚴禁使用該操作
2.3.5 payment_gateway
服務
payment_gateway:
image: dockersamples/atseasampleshopapp_payment_gateway
secrets:
- source: staging_token
target: payment_token
networks:
- payment
deploy:
update_config:
failure_action: rollback
placement:
constraints:
- 'node.role == worker'
- 'node.labels.pcidss == yes'
node.labels
:自定義節點標簽,可以通過docker node update
自定義,並添加至 Swarm 集群的指定節點。這說明,node.labels 配置只適用於 Swarm 集群中指定的節點。
三、部署docker stack
3.1 准備工作
- 自定義標簽(payment_gateway 服務需要用到)
- 密鑰(提前創建 4 個)
給工作節點 huanzi-002 新建一個自定義標簽,在管理節點上操作
[root@huanzi-001 atsea-sample-shop-app]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
8bet9fg0tnoqlfp0ebrrqdapn * huanzi-001 Ready Active Leader 19.03.5
85v90bioyy4s2fst4fa5vrlvf huanzi-002 Ready Active 19.03.5
8hxs2p5iblj19xg9uqpu8ar8g huanzi-003 Ready Active 19.03.5
[root@huanzi-001 atsea-sample-shop-app]# docker node update --label-add pcidss=yes huanzi-002
huanzi-002
[root@huanzi-001 atsea-sample-shop-app]# docker node inspect huanzi-002
[
{
"ID": "85v90bioyy4s2fst4fa5vrlvf",
"Version": {
"Index": 726
},
"CreatedAt": "2020-02-02T08:11:34.982719258Z",
"UpdatedAt": "2020-02-06T10:22:25.44331302Z",
"Spec": {
"Labels": {
"pcidss": "yes"
<...>
可以看到自定義標簽已經成功創建。
接下來創建密鑰,先創建加密 key
[root@huanzi-001 daemon]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout damain.key -x509 -days 365 -out domain.crt
Generating a 4096 bit RSA private key
....................................++
...........................................++
writing new private key to 'damain.key'
-----
<...>
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
[root@huanzi-001 daemon]# ls
atsea-sample-shop-app damain.key domain.crt
[root@huanzi-001 daemon]#
創建需要加密 key 的revprox_cert
,revprox_key
,postgres_password
這 3 個密鑰
[root@huanzi-001 daemon]# docker secret create revprox_cert domain.crt
lue5qk6ophxrr6aspyhnkhvsv
[root@huanzi-001 daemon]# docker secret create revprox_key damain.key
glvfk78kn6665lmkci7tslrw6
[root@huanzi-001 daemon]# docker secret create postgres_password damain.key
pxdfs28hb2897xuu7f3bub7ex
[root@huanzi-001 daemon]#
創建不需要加密 key 的staging_token
密鑰
[root@huanzi-001 daemon]# echo staging | docker secret create staging_token -
cyqfn9jocvnxd2vr57gn5pioj
[root@huanzi-001 daemon]# docker secret ls
ID NAME DRIVER CREATED UPDATED
pxdfs28hb2897xuu7f3bub7ex postgres_password 15 minutes ago 15 minutes ago
lue5qk6ophxrr6aspyhnkhvsv revprox_cert 16 minutes ago 16 minutes ago
glvfk78kn6665lmkci7tslrw6 revprox_key 16 minutes ago 16 minutes ago
cyqfn9jocvnxd2vr57gn5pioj staging_token About a minute ago About a minute ago
[root@huanzi-001 daemon]#
現在自定義標簽,及密鑰全部創建完畢。
3.2 開始部署
命令:docker stack deploy -c <docker-stack.yml> <stack name>
[root@huanzi-001 atsea-sample-shop-app]# docker stack deploy -c docker-stack.yml huanzi-stack
Creating network huanzi-stack_front-tier
Creating network huanzi-stack_back-tier
Creating network huanzi-stack_default
Creating network huanzi-stack_payment
Creating service huanzi-stack_payment_gateway
Creating service huanzi-stack_reverse_proxy
Creating service huanzi-stack_database
Creating service huanzi-stack_appserver
Creating service huanzi-stack_visualizer
[root@huanzi-001 atsea-sample-shop-app]#
可以看出,先創建了 4 個網絡,再創建的服務,我們驗證一下網絡是否創建了
[root@huanzi-001 atsea-sample-shop-app]# docker network ls
NETWORK ID NAME DRIVER SCOPE
34306420befb bridge bridge local
ac57c15024c7 docker_gwbridge bridge local
e863472805b3 host host local
ojt9cxg2qsxe huanzi-net overlay swarm
o74roe621idx huanzi-stack_back-tier overlay swarm
k55m237m11ct huanzi-stack_default overlay swarm
idpvc5xg2g2t huanzi-stack_front-tier overlay swarm
uvphcut0a825 huanzi-stack_payment overlay swarm
7d6iv5ilwbcn ingress overlay swarm
d302c895b455 lovehuanzi bridge local
eefd134326c4 none null local
[root@huanzi-001 atsea-sample-shop-app]#
看到了 4 個 huanzi-stack
前綴的網絡。為什么多了一個huanzi-stack-default
,因為visualizer
服務沒有指定網絡,因此 Docker 創建了一個 defalut 的網絡給它用。
再驗證下服務
root@huanzi-001 atsea-sample-shop-app]# docker stack ls
NAME SERVICES ORCHESTRATOR
huanzi-stack 5 Swarm
[root@huanzi-001 atsea-sample-shop-app]#
[root@huanzi-001 atsea-sample-shop-app]# docker stack ps huanzi-stack
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ex55yaz21mra huanzi-stack_appserver.1 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
jshmzquzxi8p huanzi-stack_database.1 dockersamples/atsea_db:latest huanzi-002 Running Preparing 2 minutes ago
k7mi1419ahwd huanzi-stack_reverse_proxy.1 dockersamples/atseasampleshopapp_reverse_proxy:latest huanzi-003 Running Preparing 2 minutes ago
09ocoutjfc70 huanzi-stack_payment_gateway.1 dockersamples/atseasampleshopapp_payment_gateway:latest huanzi-002 Running Preparing 2 minutes ago
y6lftn8g95b8 huanzi-stack_visualizer.1 dockersamples/visualizer:stable huanzi-001 Running Preparing 2 minutes ago
5twm1k4uj5ps huanzi-stack_appserver.2 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#
可以看到滿足 stack 文件的要求:
reverse_proxy
:副本數量1
database
:副本數量1
,位於worker
appserver
:副本數量2
,位於worker
visualizer
:副本數量1
,位於manager
payment_gateway
:副本數量1
,位於worker
,自定義標簽pcidss == yes
(即 huanzi-002 )
3.3 管理 Stack
3.3.1 擴容
將appserver
的副本數從 2 擴至 10,有 2 種方式:
- 通過
docker service scale appserver=10
- 直接修改
docker-stack.yml
文件,再通過docker stack deploy
重新部署
所有的變更都應該通過 Stack 文件進行聲明,然后通過 docker stack deploy 進行部署
修改docker-stack.yml
文件
appserver:
image: dockersamples/atsea_app
networks:
- front-tier
- back-tier
- payment
deploy:
replicas: 10
重新部署
[root@huanzi-001 atsea-sample-shop-app]# docker stack deploy -c docker-stack.yml huanzi-stack
Updating service huanzi-stack_reverse_proxy (id: i2yn8l50ofnmbx0a55mum1dw0)
Updating service huanzi-stack_database (id: ubrtixblmj685pnc97wql42cm)
Updating service huanzi-stack_appserver (id: yy447jdp1eiwb03ljdsqtyg1g)
Updating service huanzi-stack_visualizer (id: rhzzxov0jh1y38rxcj6bwe89y)
Updating service huanzi-stack_payment_gateway (id: niobpxv5vr1njoo37vnje8zic)
[root@huanzi-001 atsea-sample-shop-app]#
[root@huanzi-001 atsea-sample-shop-app]# docker stack ps huanzi-stack
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wrser9r5bbrz huanzi-stack_visualizer.1 dockersamples/visualizer:stable huanzi-001 Running Preparing 3 minutes ago
ex55yaz21mra huanzi-stack_appserver.1 dockersamples/atsea_app:latest huanzi-003 Running Preparing 20 minutes ago
jshmzquzxi8p huanzi-stack_database.1 dockersamples/atsea_db:latest huanzi-002 Running Preparing 20 minutes ago
k7mi1419ahwd huanzi-stack_reverse_proxy.1 dockersamples/atseasampleshopapp_reverse_proxy:latest huanzi-003 Running Preparing 20 minutes ago
09ocoutjfc70 huanzi-stack_payment_gateway.1 dockersamples/atseasampleshopapp_payment_gateway:latest huanzi-002 Running Preparing 20 minutes ago
5twm1k4uj5ps huanzi-stack_appserver.2 dockersamples/atsea_app:latest huanzi-002 Running Preparing 20 minutes ago
aydzla0zzv3p huanzi-stack_appserver.3 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
n3312auusvxi huanzi-stack_appserver.4 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
kg8jy3ei0beo huanzi-stack_appserver.5 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
tgai33mhlxyv huanzi-stack_appserver.6 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
n69nunaur3lz huanzi-stack_appserver.7 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
mqubx8hoddn8 huanzi-stack_appserver.8 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
p3mo3k8a5jvs huanzi-stack_appserver.9 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
xw8tvi5bwh53 huanzi-stack_appserver.10 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#
擴容完成。
3.3.2 刪除
命令:docker stack rm <stack name>
[root@huanzi-001 atsea-sample-shop-app]# docker stack rm huanzi-stack
Removing service huanzi-stack_appserver
Removing service huanzi-stack_database
Removing service huanzi-stack_payment_gateway
Removing service huanzi-stack_reverse_proxy
Removing service huanzi-stack_visualizer
Removing network huanzi-stack_front-tier
Removing network huanzi-stack_default
Removing network huanzi-stack_back-tier
Removing network huanzi-stack_payment
可以看出,rm
會刪除服務及網絡,但是密鑰和卷不會刪除
root@huanzi-001 atsea-sample-shop-app]# docker secret ls
ID NAME DRIVER CREATED UPDATED
pxdfs28hb2897xuu7f3bub7ex postgres_password 53 minutes ago 53 minutes ago
lue5qk6ophxrr6aspyhnkhvsv revprox_cert 55 minutes ago 55 minutes ago
glvfk78kn6665lmkci7tslrw6 revprox_key 54 minutes ago 54 minutes ago
cyqfn9jocvnxd2vr57gn5pioj staging_token 40 minutes ago 40 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#
一般一個環境需要一個stack文件。比如dev,test,prod。
感謝閱讀,有興趣的小伙伴可以關注我的微信公眾號DevOps探索之旅
,大家一起學習進步