1. 程式人生 > >Docker Swarm 叢集環境搭建及彈性服務部署

Docker Swarm 叢集環境搭建及彈性服務部署

  上一篇文章《Docker Swarm 叢集管理利器核心概念掃盲》中我們把 Swarm 重要的概念性知識給大家講解了一波,理論完事就該實戰了,這篇文章帶大家從零開始,搭建 Docker Swarm 叢集環境,並通過 Swarm 實現服務的彈性部署,滾動更新服務及回滾服務等功能。    ## 叢集搭建    ### 環境準備    ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4652b366ab674e25b0859db1fe2c8381~tplv-k3u1fbpfcp-zoom-1.image) - 五臺安裝了 Docker 的 CentOS 機器,版本為:`CentOS 7.8.2003` - Docker Engine 1.12+(最低要求 1.12,本文使用 19.03.12) - 防火牆開啟以下埠或者關閉防火牆: - TCP 埠 2377,用於叢集管理通訊; - TCP 和 UDP 埠 7946,用於節點之間通訊; - UDP 埠 4789,用於覆蓋網路。    ### 機器分佈    | 角色 | IP | HOSTNAME | Docker 版本 | | ------- | -------------- | -------- | ----------- | | Manager | 192.168.10.101 | manager1 | 19.03.12 | | Manager | 192.168.10.102 | manager2 | 19.03.12 | | Manager | 192.168.10.103 | manager3 | 19.03.12 | | Worker | 192.168.10.10 | worker1 | 19.03.12 | | Worker | 192.168.10.11 | worker2 | 19.03.12 | - 可以通過 `hostname 主機名` 修改機器的主機名(立即生效,重啟後失效); - 或者 `hostnamectl set-hostname 主機名` 修改機器的主機名(立即生效,重啟也生效); - 或者 `vi /etc/hosts` 編輯 hosts 檔案,如下所示, 給 127.0.0.1 新增主機名(重啟生效)。 ```hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 manager1 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 ```    ### 建立叢集      在任意節點下通過 `docker swarm init` 命令建立一個新的 Swarm 叢集並加入,且該節點會預設成為 Manager 節點。根據我們預先定義的角色,在 101 ~ 103 的任意一臺機器上執行該命令即可。   通常,第一個加入叢集的管理節點將成為 `Leader`,後來加入的管理節點都是 `Reachable`。當前的 Leader 如果掛掉,所有的 Reachable 將重新選舉一個新的 Leader。 ```shell [root@localhost ~]# docker swarm init --advertise-addr 192.168.10.101 Swarm initialized: current node (clumstpieg0qzzxt1caeazg8g) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-5ob7jlej85qsygxubqypjuftiwruvew8e2cr4u3iuo4thxyrhg-3hbf2u3i1iagurdprl3n3yra1 192.168.10.101:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4a2bba0743504b14a4b3a96ce06bb534~tplv-k3u1fbpfcp-zoom-1.image)    ### 加入叢集      Docker 中內建的叢集模式自帶了公鑰基礎設施(PKI)系統,使得安全部署容器變得簡單。叢集中的節點使用傳輸層安全協議(TLS)對叢集中其他節點的通訊進行身份驗證、授權和加密。   預設情況下,通過 `docker swarm init` 命令建立一個新的 Swarm 叢集時,Manager 節點會生成新的根證書頒發機構(CA)和金鑰對,用於保護與加入群集的其他節點之間的通訊安全。   Manager 節點會生成兩個令牌,供其他節點加入叢集時使用:一個 Worker 令牌,一個 Manager 令牌。每個令牌都包括根 CA 證書的摘要和隨機生成的金鑰。當節點加入群集時,加入的節點使用摘要來驗證來自遠端管理節點的根 CA 證書。遠端管理節點使用金鑰來確保加入的節點是批准的節點。    ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b2ef66975e154909bb9e86e9281ebd41~tplv-k3u1fbpfcp-zoom-1.image)    #### Manager      若要向該叢集新增 Manager 節點,管理節點先執行 `docker swarm join-token manager` 命令檢視管理節點的令牌資訊。 ```shell docker swarm join-token manager ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b6d03076e304b3a8a321044cbc8c85a~tplv-k3u1fbpfcp-zoom-1.image) ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/420a31db7d9145fe9905a32f94f73fa8~tplv-k3u1fbpfcp-zoom-1.image)      然後在其他節點上執行 `docker swarm join` 並攜帶令牌引數加入 Swarm 叢集,該節點角色為 Manager。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aeeb38860ef84940a5fa5464cca8f217~tplv-k3u1fbpfcp-zoom-1.image) ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/520968b3dc3e434c8221afdfee0403ba~tplv-k3u1fbpfcp-zoom-1.image)    #### Worker      通過建立叢集時返回的結果可以得知,要向這個叢集新增一個 Worker 節點,執行下圖中的命令即可。或者管理節點先執行 `docker swarm join-token worker` 命令檢視工作節點的令牌資訊。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5df1108aa50b4cf994d9cb38b1273d56~tplv-k3u1fbpfcp-zoom-1.image)      然後在其他節點上執行 `docker swarm join` 並攜帶令牌引數加入 Swarm 叢集,該節點角色為 Worker。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f1f4ef9d23b4546a1f183190218e4e9~tplv-k3u1fbpfcp-zoom-1.image) ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d7ee43717c4843f4b5ce71037fd4092b~tplv-k3u1fbpfcp-zoom-1.image)    ### 檢視叢集資訊      在任意 Manager 節點中執行 `docker info` 可以檢視當前叢集的資訊。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/335d15d8e7704c7db789a37f024c990e~tplv-k3u1fbpfcp-zoom-1.image)    ### 檢視叢集節點      在任意 Manager 節點中執行 `docker node ls` 可以檢視當前叢集節點資訊。 ```shell docker node ls ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7e1d31dea43d4b05af8ea9bcdb93baeb~tplv-k3u1fbpfcp-zoom-1.image) > `*` 代表當前節點,現在的環境為 3 個管理節點構成 1 主 2 從,以及 2 個工作節點。      節點 `MANAGER STATUS` 說明:表示節點是屬於 Manager 還是 Worker,沒有值則屬於 Worker 節點。 - `Leader`:該節點是管理節點中的主節點,負責該叢集的叢集管理和編排決策; - `Reachable`:該節點是管理節點中的從節點,如果 Leader 節點不可用,該節點有資格被選為新的 Leader; - `Unavailable`:該管理節點已不能與其他管理節點通訊。如果管理節點不可用,應該將新的管理節點加入群集,或者將工作節點升級為管理節點。      節點 `AVAILABILITY` 說明:表示排程程式是否可以將任務分配給該節點。 - `Active`:排程程式可以將任務分配給該節點; - `Pause`:排程程式不會將新任務分配給該節點,但現有任務仍可以執行; - `Drain`:排程程式不會將新任務分配給該節點,並且會關閉該節點所有現有任務,並將它們排程在可用的節點上。    ### 刪除節點    #### Manager      刪除節點之前需要先將該節點的 `AVAILABILITY` 改為 `Drain`。其目的是為了將該節點的服務遷移到其他可用節點上,確保服務正常。最好檢查一下容器遷移情況,確保這一步已經處理完成再繼續往下。 ```shell docker node update --availability drain 節點名稱|節點ID ```      然後,將該 Manager 節點進行降級處理,降級為 Worker 節點。 ```shell docker node demote 節點名稱|節點ID ```      然後,在已經降級為 Worker 的節點中執行以下命令,離開叢集。 ```shell docker swarm leave ```      最後,在管理節點中對剛才離開的節點進行刪除。 ```shell docker node rm 節點名稱|節點ID ```    #### Worker      刪除節點之前需要先將該節點的 `AVAILABILITY` 改為 `Drain`。其目的是為了將該節點的服務遷移到其他可用節點上,確保服務正常。最好檢查一下容器遷移情況,確保這一步已經處理完成再繼續往下。 ```shell docker node update --availability drain 節點名稱|節點ID ```      然後,在準備刪除的 Worker 節點中執行以下命令,離開叢集。 ```shell docker swarm leave ```      最後,在管理節點中對剛才離開的節點進行刪除。 ```shell docker node rm 節點名稱|節點ID ```    ## 服務部署    > 注意:跟叢集管理有關的任何操作,都是在 Manager 節點上操作的。    ### 建立服務      下面這個案例,使用 nginx 映象建立了一個名為 mynginx 的服務,該服務會被隨機指派給一個工作節點執行。 ```shell docker service create --replicas 1 --name mynginx -p 80:80 nginx ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aad553ce2562402bb0bd2fca5a63418e~tplv-k3u1fbpfcp-zoom-1.image) - `docker service create`:建立服務; - `--replicas`:指定一個服務有幾個例項執行; - `--name`:服務名稱。    ### 檢視服務      可以通過 `docker service ls` 檢視執行的服務。 ```shell [root@manager1 ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS hepx06k5ik5n mynginx replicated 1/1 nginx:latest *:80->80/tcp ```      可以通過 `docker service inspect 服務名稱|服務ID` 檢視服務的詳細資訊。 ```shell [root@manager1 ~]# docker service inspect mynginx [ { "ID": "k0dbjg1zzy3l3g71kdwa56ect", "Version": { "Index": 127 }, "CreatedAt": "2020-09-16T10:05:55.627974095Z", "UpdatedAt": "2020-09-16T10:05:55.629507771Z", "Spec": { "Name": "mynginx", "Labels": {}, "TaskTemplate": { "ContainerSpec": { "Image": "nginx:latest@sha256:c628b67d21744fce822d22fdcc0389f6bd763daac23a6b77147d0712ea7102d0", "Init": false, "StopGracePeriod": 10000000000, "DNSConfig": {}, "Isolation": "default" }, "Resources": { "Limits": {}, "Reservations": {} }, "RestartPolicy": { "Condition": "any", "Delay": 5000000000, "MaxAttempts": 0 }, "Placement": { "Platforms": [ { "Architecture": "amd64", "OS": "linux" }, { "OS": "linux" }, { "OS": "linux" }, { "Architecture": "arm64", "OS": "linux" }, { "Architecture": "386", "OS": "linux" }, { "Architecture": "mips64le", "OS": "linux" }, { "Architecture": "ppc64le", "OS": "linux" }, { "Architecture": "s390x", "OS": "linux" } ] }, "ForceUpdate": 0, "Runtime": "container" }, "Mode": { "Replicated": { "Replicas": 1 } }, "UpdateConfig": { "Parallelism": 1, "FailureAction": "pause", "Monitor": 5000000000, "MaxFailureRatio": 0, "Order": "stop-first" }, "RollbackConfig": { "Parallelism": 1, "FailureAction": "pause", "Monitor": 5000000000, "MaxFailureRatio": 0, "Order": "stop-first" }, "EndpointSpec": { "Mode": "vip", "Ports": [ { "Protocol": "tcp", "TargetPort": 80, "PublishedPort": 80, "PublishMode": "ingress" } ] } }, "Endpoint": { "Spec": { "Mode": "vip", "Ports": [ { "Protocol": "tcp", "TargetPort": 80, "PublishedPort": 80, "PublishMode": "ingress" } ] }, "Ports": [ { "Protocol": "tcp", "TargetPort": 80, "PublishedPort": 80, "PublishMode": "ingress" } ], "VirtualIPs": [ { "NetworkID": "st2xiy7pjzap093wz4w4u6nbs", "Addr": "10.0.0.15/24" } ] } } ] ```      可以通過 `docker service ps 服務名稱|服務ID` 檢視服務執行在哪些節點上。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1d008646799b4725a0e03e0a695ea9fe~tplv-k3u1fbpfcp-zoom-1.image)   在對應的任務節點上執行 `docker ps` 可以檢視該服務對應容器的相關資訊。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e0b363efa08943e2b37c453a11bcb5ca~tplv-k3u1fbpfcp-zoom-1.image)    ### 呼叫服務      接下來我們測試一下服務是否能被正常訪問,並且該叢集下任意節點的 IP 地址都要能訪問到該服務才行。   測試結果:5 臺機器均可正常訪問到該服務。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d5fc6e8278734897a5c1e26a6d9fee84~tplv-k3u1fbpfcp-zoom-1.image)    ### 彈性服務      將 service 部署到叢集以後,可以通過命令彈性擴縮容 service 中的容器數量。在 service 中執行的容器被稱為 task(任務)。   通過 `docker service scale 服務名稱|服務ID=n` 可以將 service 執行的任務擴縮容為 n 個。   通過 `docker service update --replicas n 服務名稱|服務ID` 也可以達到擴縮容的效果。   將 mynginx service 執行的任務擴充套件為 5 個: ```shell [root@manager1 ~]# docker service scale mynginx=5 mynginx scaled to 5 overall progress: 5 out of 5 tasks 1/5: running [==================================================>] 2/5: running [==================================================>] 3/5: running [==================================================>] 4/5: running [==================================================>] 5/5: running [==================================================>] verify: Service converged ```   通過 `docker service ps 服務名稱|服務ID` 檢視服務執行在哪些節點上。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/723dacc2444743f2869d2d049d874999~tplv-k3u1fbpfcp-zoom-1.image)      我們再來一波縮容的操作,命令如下: ```shell [root@manager1 ~]# docker service update --replicas 3 mynginx mynginx overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged ```   通過 `docker service ps 服務名稱|服務ID` 檢視服務執行在哪些節點上。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2e4143a1a803412eb628447807b05bd9~tplv-k3u1fbpfcp-zoom-1.image)   在 Swarm 叢集模式下真正意義實現了所謂的**彈性服務**,動態擴縮容一行命令搞定,簡單、便捷、強大。    ### 刪除服務      通過 `docker service rm 服務名稱|服務ID` 即可刪除服務。 ```shell [root@manager1 ~]# docker service rm mynginx mynginx [root@manager1 ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS ```    ## 滾動更新及回滾      以下案例將演示 Redis 版本如何滾動升級至更高版本再回滾至上一次的操作。   首先,建立 5 個 Redis 服務副本,版本為 5,詳細命令如下: ```shell # 建立 5 個副本,每次更新 2 個,更新間隔 10s,20% 任務失敗繼續執行,超出 20% 執行回滾,每次回滾 2 個 docker service create --replicas 5 --name redis \ --update-delay 10s \ --update-parallelism 2 \ --update-failure-action continue \ --rollback-monitor 20s \ --rollback-parallelism 2 \ --rollback-max-failure-ratio 0.2 \ redis:5 ``` - `--update-delay`:定義滾動更新的時間間隔; - `--update-parallelism`:定義並行更新的副本數量,預設為 1; - `--update-failure-action`:定義容器啟動失敗之後所執行的動作; - `--rollback-monitor`:定義回滾的監控時間; - `--rollback-parallelism`:定義並行回滾的副本數量; - `--rollback-max-failure-ratio`:任務失敗回滾比率,超過該比率執行回滾操作,0.2 表示 20%。      然後通過以下命令實現服務的滾動更新。 ```shell docker service update --image redis:6 redis ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/220aab1a3f494362ac18385f5fb4f467~tplv-k3u1fbpfcp-zoom-1.image)      回滾服務,只能回滾到上一次操作的狀態,並不能連續回滾到指定操作。 ```shell docker service update --rollback redis ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ba0dba7e3e204eef98603df2e5e675d4~tplv-k3u1fbpfcp-zoom-1.image)    ## 常用命令    ### docker swarm    | 命令 | 說明 | | :------------------------------ | -------------------- | | docker swarm init | 初始化叢集 | | docker swarm join-token worker | 檢視工作節點的 token | | docker swarm join-token manager | 檢視管理節點的 token | | docker swarm join | 加入叢集 |    ### docker node    | 命令 | 說明 | | ------------------------------------ | ---------------------------------- | | docker node ls | 檢視叢集所有節點 | | docker node ps | 檢視當前節點所有任務 | | docker node rm 節點名稱\|節點ID | 刪除節點(`-f`強制刪除) | | docker node inspect 節點名稱\|節點ID | 檢視節點詳情 | | docker node demote 節點名稱\|節點ID | 節點降級,由管理節點降級為工作節點 | | docker node promote 節點名稱\|節點ID | 節點升級,由工作節點升級為管理節點 | | docker node update 節點名稱\|節點ID | 更新節點 |    ### docker service    | 命令 | 說明 | | --------------------------------------- | ------------------------ | | docker service create | 建立服務 | | docker service ls | 檢視所有服務 | | docker service inspect 服務名稱\|服務ID | 檢視服務詳情 | | docker service logs 服務名稱\|服務ID | 檢視服務日誌 | | docker service rm 服務名稱\|服務ID | 刪除服務(`-f`強制刪除) | | docker service scale 服務名稱\|服務ID=n | 設定服務數量 | | docker service update 服務名稱\|服務ID | 更新服務 |    ## 參考資料    - https://docs.docker.com/engine/swarm/swarm-tutorial/ - https://docs.docker.com/engine/swarm/swarm-mode/ - https://docs.docker.com/engine/swarm/how-swarm-mode-works/pki/ - https://docs.docker.com/engine/swarm/join-nodes/ - https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/ ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/684f1820a650416fab784516f1e57c7b~tplv-k3u1fbpfcp-zoom-1.image) 本文采用 `知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議`。 大家可以通過 `分類` 檢視更多關於 `Docker` 的文章。