Docker Stack 學習筆記

該文爲《深入淺出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 ,即服務升級失敗後阻止其它副本的升級,還支持 continue
  • restart_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_certrevprox_keypostgres_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探索之旅,大家一起學習進步
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章