本教程將介紹 Docker Engine Swarm 模式。先介紹 swarm 模式幾個關鍵的概念,而後經過動手實踐帶你體驗一下 swarm 模式。node
Docker Engline 中集成的集羣管理和編排功能都是基於 SwarmKit 實現。參與到集羣中的 Docker Engine 會進入 swarm 模式。好比初始化一個 swarm 或加入已有的 swarm。linux
一個 swarm 就是個一個 Docker Engine 集羣,你能夠在上面部署服務。Docker Engine CLI 提供了用於 swarm 管理的命令,好比添加或移除一個節點。一樣還提供了用於部署服務到 swarm 和管理服務編排的命令。redis
當 Docker Engine 運行在 swarm 模式時,你管理容器。當 Docker Engine 運行在 swarm 模式時,你編排服務。docker
每一個參與到 swarm 中的 Docker Engine 都稱之爲一個節點。json
將服務的定義提交到管理節點便可將應用部署到 swarm。而後管理節點將叫做任務的工做單元分發到工做節點。bash
爲了維持 swarm 的目標狀態,管理節點還將承當編排和集羣管理的功能。通常有多個管理節點,它們之間會選出一個領導來進行編排任務。網絡
工做節點接收並執行來自管理節點分發的任務。默認狀況下,管理節點也是工做節點,你能夠把它配置成只當管理節點。代理通知管理節點已分配任務的當前狀態,以便管理節點維護所需的狀態。負載均衡
服務定義了須要在工做節點上執行的任務。它是 swarm 系統的中心結構,也是用戶和 swarm 交互的主要根源。tcp
服務包括要使用的容器鏡像,以及在容器中執行的指令。ide
對於複製服務,管理節點根據服務的規模和目標狀態將必定數量的任務副本分發到各節點上。
對於全局服務,每一個節點上都將分發一個任務副本。
任務包含一個容器和須要在容器中執行的指令。它是 swarm 原子調度單位。管理節點根據服務規模中定義的副本數量將任務分配給工做節點。一旦某個任務被分配到某個節點,就不能再移動到其餘節點。它只能在分配的節點上運行或者失敗。
swarm 管理節點使用 入口負載均衡 的方式暴露你想要讓外部訪問的服務。Swarm 管理節點能夠自動將一個服務分配到某個 發佈端口,或者你能夠爲服務指定一個發佈端口。你能夠指定任意未使用的端口。若是你沒指定端口,swarm 管理節點將爲服務指定一個 30000-32757 之間的端口。
外部組件,好比雲負載均衡器,能夠經過集羣中的任意節點訪問發佈端口上的服務,無論當前節點上是否有服務對應的任務在運行,swarm 中的全部節點都會將進入鏈接路由到正在運行任務的實例上。
Swarm 模式有一個內置的 DNS 組件,它會自動給 swarm 中的每一個服務分配一個 DNS 條目。Swarm 管理器使用internal load balancing 基於服務對應的 DNS 名稱在服務之間分發請求。
本教程將指導你完成如下任務:
在 Docker Engline swarm 模式下初始化一個集羣
添加節點到 swarm
部署服務到 swarm
在一切就緒後管理 swarm
在開始本教程以前,你須要準備一下幾樣東西:
三臺經過網絡鏈接的主機
每臺主機安裝 Docker Engine 1.12 或更新版本
充當管理節點的主機 IP
主機之間開放下面提到的端口
主機之間的如下端口必須是開放。某些環境下,這些端口默認是容許的:
TCP 端口 2377 用於集羣管理通訊(管理節點)
TCP 和 UDP 端口 7946 用於節點間通訊(全部節點)
TCP 和 UDP 端口 4789 用於 overlay 網絡流量(全部節點)
若是你的這些端口沒有打開,能夠用iptables
命令打開它們:
iptables -A INPUT -p tcp --dport 2377 -j ACCEPT iptables -A INPUT -p tcp --dport 7946 -j ACCEPT iptables -A INPUT -p udp --dport 7946 -j ACCEPT iptables -A INPUT -p tcp --dport 4789 -j ACCEPT iptables -A INPUT -p udp --dport 4789 -j ACCEPT
192.168.33.160 swarm_manager
192.168.33.161 node1
192.168.33.162 node2
隨意選擇一個主機做爲管理節點,在上面初始化一個 swarm:
[root@swarm_manager ~]# docker swarm init --advertise-addr 192.168.33.160 Swarm initialized: current node (7ik7wqhe5wcag8k5tp816c7ck) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-0p0p5f96e1w4xblhw2eeookrv46spwf4yx7qmve2srxe9wec5g-ellbnyt4cwwvvdkssaj0cbtus \ 192.168.33.160:2377
--advertise-addr
標誌配置了管理節點的 IP 地址。若是你的機器只有一個 IP 地址,能夠省略--adbertise-addr
選項,docker 會自動選擇正確的 IP。上輸出信息說明了怎樣加入新的工做節點。也說明了執行docker swarm join-token manager
能夠查詢怎樣加入新的管理節點。
docker info
命令查看swarm
的當前狀態[root@swarm_manager ~]# docker info ... Swarm: active NodeID: 7ik7wqhe5wcag8k5tp816c7ck Is Manager: true ClusterID: 2scd04fv8c9mua1jiaq6n0370 Managers: 1 Nodes: 1 ... 執行 docker node ls 命令查看節點信息 [root@swarm_manager ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 9e21bk67ey1abzje69lmpvbe1 * swarm_manager Ready Active Leader
節點 id 後面的*
表示你當前鏈接到了該節點。
swarm
在第二臺主機上,執行前面建立 swarm
時 docker swarm init
輸出信息中命令建立工做節點並加入到 swarm
[root@node1 ~]# docker swarm join \ --token SWMTKN-1-0p0p5f96e1w4xblhw2eeookrv46spwf4yx7qmve2srxe9wec5g-ellbnyt4cwwvvdkssaj0cbtus \ 192.168.33.160:2377 This node joined a swarm as a worker.
輸出信息表示當前節點已經是 swarm
中的一個工做節點了。若是你忘記了該命令,能夠在管理節點上執行 docker swarm join-token worker
查詢怎麼加入。
[root@swarm_manager ~]# docker swarm join-token worker To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-3wi7tszkolocsbc7vopv1tfx2r2h1owtqegwevdqqdk3fj195u-ejpeq0afjvfmujlvzboux9zjs \ 192.168.33.160:2377
到第三臺主機上,繼續講第三臺主機加入到 swarm
中
[root@node1 ~]# docker swarm join \ --token SWMTKN-1-0p0p5f96e1w4xblhw2eeookrv46spwf4yx7qmve2srxe9wec5g-ellbnyt4cwwvvdkssaj0cbtus \ 192.168.59.128:2377 This node joined a swarm as a worker.
在管理節點上
[root@swarm_manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
622ih8ji5t428lazjx233pvks node2 Ready Active
9e21bk67ey1abzje69lmpvbe1 * swarm_manager Ready Active Leader
f3wzagmtgsn8qyqzidxtw98d3 node1 Ready Active
輸出信息第二行 id 後面的*
表示當前鏈接到了該節點。HOSTNAME
欄輸出節點的 hostname。MANAGER
用於指示 swarm
中的管理節點,該欄值爲 Leader
表示爲管理節點,空值表示爲工做節點。
swarm
在管理節點上建立一個服務,每隔三秒輸出一個 「hello world」:
[root@swarm_manager ~]# docker service create --replicas 1 --name helloworld busybox:1.25.1-musl /bin/sh -c "while true; do echo hello world; sleep 3; done" 04a3iqg8zlhba84kpi2tatssf
docker service create
命令建立服務。
--name
標誌將服務命名爲helloworld
。
--replicas
標誌指定了指望狀態爲 1 個運行示例。
參數 busybox:1.25.1-musl /bin/sh -c "while true; do echo hello world; sleep 3; done
將服務定義爲使用鏡像busybox:1.25.1-musl
建立容器,並在裏面執行 /bin/sh -c "while true; do echo hello world; sleep 3; done
。
仍是在管理節點上
[root@swarm_manager ~]# docker service ls ID NAME REPLICAS IMAGE COMMAND c3hvgwhyim4n helloworld 1/1 busybox:1.25.1-musl /bin/sh -c while true; do echo hello world; sleep 3; done
在管理節點上。
[root@swarm_manager ~]# docker service inspect --pretty helloworld ID: c3hvgwhyim4nllg1qqix7kli6 Name: helloworld Mode: Replicated Replicas: 1 Placement: UpdateConfig: Parallelism: 1 On failure: pause ContainerSpec: Image: busybox:1.25.1-musl Args: /bin/sh -c while true; do echo hello world; sleep 3; done Resources:
參數--pretty
表示以可讀性良好的格式輸出。若是想輸出詳細的 json 格式信息,去掉--pretty
參數便可。
仍是在管理節點上:
[root@swarm_manager ~]# docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 556c2lpvr4489yrclo52cjlo5 helloworld.1 busybox:1.25.1-musl node2 Running Running 3 minutes ago
輸出信息代表,helloworld
服務的一個實例在 node2 節點上執行。這是由於,默認狀況下管理節點是工做節點。
DESIRED STATE
和CURRENT STATE
表示服務的指望狀態和當前狀態,你能夠對比它們,判斷服務是否想指望的那樣運行。這裏的Running
和Running 3 minutes ago
說明服務運行正常。
docker ps
命令查看相關容器的詳細信息[root@node2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 964ddb3220b6 busybox:1.25.1-musl "/bin/sh -c 'while tr" 5 minutes ago Up 5 minutes helloworld.1.556c2lpvr4489yrclo52cjlo5
在管理節點上
[root@node2 ~]# docker service scale helloworld=5 helloworld scaled to 5 咱們將服務的數量伸縮到5。
在管理節點上:
[root@swarm_manager ~]# docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 556c2lpvr4489yrclo52cjlo5 helloworld.1 busybox:1.25.1-musl node2 Running Running 10 minutes ago e2tw7i9bkjb32jrr3sdztskwe helloworld.2 busybox:1.25.1-musl swarm_manager Running Running 24 seconds ago d5plppbjvtr1rany4tzb88czc helloworld.3 busybox:1.25.1-musl node2 Running Running 28 seconds ago a0hs8ik837jl7mlgeaowws1i3 helloworld.4 busybox:1.25.1-musl node1 Running Running 18 seconds ago bo27jnf7n59hqzl9m9jnpwbks helloworld.5 busybox:1.25.1-musl swarm_manager Running Running 24 seconds ago
首先是管理節點:
[root@swarm_manager ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 46aa83031ad7 busybox:1.25.1-musl "/bin/sh -c 'while tr" About a minute ago Up About a minute helloworld.2.e2tw7i9bkjb32jrr3sdztskwe e1cb3bd1bfb0 busybox:1.25.1-musl "/bin/sh -c 'while tr" About a minute ago Up About a minute helloworld.5.bo27jnf7n59hqzl9m9jnpwbks
再是工做節點1
[root@node1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1c200722ace5 busybox:1.25.1-musl "/bin/sh -c 'while tr" About a minute ago Up About a minute helloworld.4.a0hs8ik837jl7mlgeaowws1i3
再是工做節點2
[root@node2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2dba702ccd68 busybox:1.25.1-musl "/bin/sh -c 'while tr" About a minute ago Up About a minute helloworld.3.d5plppbjvtr1rany4tzb88czc 964ddb3220b6 busybox:1.25.1-musl "/bin/sh -c 'while tr" 11 minutes ago Up 11 minutes helloworld.1.556c2lpvr4489yrclo52cjlo5
能夠看到:管理節點上運行了兩個任務,工做節點1運行了兩個任務,工做節點2運行了1個任務。
swarm
上運行的服務在管理節點上
[root@swarm_manager ~]# docker service rm helloworld
helloworld
在管理節點上
[root@swarm_manager ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
[root@swarm_manager ~]#
看不到任何服務了。
在這部分,咱們將部署一個基於 Rddis 3.07 鏡像的服務。而後使用滾動更新將服務更新到使用 Redis 3.2.5 鏡像。
swarm
中部署 Redis 3.0.7,並配置 10 秒更新延遲[root@swarm_manager ~]# docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.7-alpine 6vw26iief1y2nxmi6a01tzco6
咱們在部署服務指定滾動更新策略。--update-delay
表示更新服務對應的任務或一組任務之間的時間間隔。時間間隔用數字和時間單位表示,m 表示分,h 表示時,因此 10m30s 表示 10 分 30 秒的延時。
默認狀況下,調度器一次更新一個任務。你可使用 --update-parallelism
標誌配置調度器每次同時更新的最大任務數量。
默認狀況下,若是更新某個任務返回了RUNNING
狀態,調度器會轉去更新另外一個任務,直到全部任務都更新完成。若是在更新某個任務的任意時刻返回了FAILED
,調度器暫停更新。咱們能夠在執行 docker service create
命令和 docker service update
命令時使用 --update-failure-action
標誌來覆蓋這種默認行爲。
redis
服務[root@swarm_manager ~]# docker service inspect --pretty redis ID: 6vw26iief1y2nxmi6a01tzco6 Name: redis Mode: Replicated Replicas: 3 Placement: UpdateConfig: Parallelism: 1 Delay: 10s On failure: pause ContainerSpec: Image: redis:3.0.7-alpine Resources:
redis
服務使用的容器鏡像swarm
管理節點會根據UpdateConfig
策略來更新節點
[root@swarm_manager ~]# docker service update --image redis:3.2.5-alpine redis redis
調度器根據下面默認的策略來應用滾動更新:
中止第一個任務。
爲中止的任務應用更新。
爲更新的任務啓動容器。
若是更新任務時返回RUNNING
,等待一個指定的延時後中止下一個任務。
若是,在更新的任意時刻,某個任務返回FAILED
,暫停更新。
[root@swarm_manager ~]# docker service update --image redis:3.2.5-alpine redis redis [root@swarm_manager ~]# docker service inspect --pretty redis ID: 6vw26iief1y2nxmi6a01tzco6 Name: redis Mode: Replicated Replicas: 3 Update status: State: updating Started: 46 seconds ago Message: update in progress Placement: UpdateConfig: Parallelism: 1 Delay: 10s On failure: pause ContainerSpec: Image: redis:3.2.5-alpine Resources:
能夠看到 redis 服務的鏡像已經變成了redis:3.2.5-alpine
。不過狀態還在更新中。過一會再查看:
[root@swarm_manager ~]# docker service inspect --pretty redis ID: 6vw26iief1y2nxmi6a01tzco6 Name: redis Mode: Replicated Replicas: 3 Update status: State: completed Started: 2 minutes ago Completed: about a minute ago Message: update completed Placement: UpdateConfig: Parallelism: 1 Delay: 10s On failure: pause ContainerSpec: Image: redis:3.2.5-alpine Resources:
能夠看到更新完成。
[root@swarm_manager ~]# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR e69zhhxz66jmlm0h15gj89s2x redis.1 redis:3.2.5-alpine swarm_manager Running Running 2 minutes ago 63h5wy36474k01vmr5jppbbxs \_ redis.1 redis:3.0.7-alpine node1 Shutdown Shutdown 2 minutes ago 1h9e8m9v3rx3hgx5x2bn71kim redis.2 redis:3.2.5-alpine node2 Running Running 3 minutes ago 39jitd0mzztl0mpy6k6rppkx5 \_ redis.2 redis:3.0.7-alpine swarm_manager Shutdown Shutdown 3 minutes ago 8pwrkq6558fwp8oiiu0uq484h redis.3 redis:3.2.5-alpine node1 Running Running about a minute ago 6usd4p2mj7p597ilgs490ou7a \_ redis.3 redis:3.0.7-alpine node2 Shutdown Shutdown 2 minutes ago
能夠看到有三個鏡像爲redis:3.0.7-alpine
的任務狀態爲Shutdown
,三個鏡像爲redis:3.2.5-alpine
的任務狀態爲Running
。說明滾動更新已完成。
再看看容器信息
[root@swarm_manager ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f7c5ebb8678b redis:3.2.5-alpine "docker-entrypoint.sh" 4 minutes ago Up 4 minutes 6379/tcp redis.1.e69zhhxz66jmlm0h15gj89s2x 524aadad84b8 redis:3.0.7-alpine "docker-entrypoint.sh" 7 minutes ago Exited (0) 5 minutes ago redis.2.39jitd0mzztl0mpy6k6rppkx5
能夠看出更新後,swarm
並無刪除舊的容器。
在前面的步驟中,全部的節點都處於運行狀態且可用性爲ACTIVE
。swarm 管理器能夠將任務分配給任何可用性爲 ACTIVE
的節點,因此到目前爲止,全部節點均可以接收任務。
有時候,好比到了計劃的維護時間,你須要將節點的可用性設爲DRAIN
。可用性爲DRAIN
的節點不會從 swarm 接收任何新任務。同時,管理器將中止運行在該節點上的任務,並在另外可用性爲 ACTIVE
的節點上啓動相應的任務副本。
[root@swarm_manager ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 622ih8ji5t428lazjx233pvks node2 Ready Active 9e21bk67ey1abzje69lmpvbe1 * swarm_manager Ready Active Leader f3wzagmtgsn8qyqzidxtw98d3 node1 Ready Active
將分配了任務的工做節點node2
下線:
[root@swarm_manager ~]# docker node update --availability drain node2 node2
[root@swarm_manager ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 622ih8ji5t428lazjx233pvks node2 Ready Drain 9e21bk67ey1abzje69lmpvbe1 * swarm_manager Ready Active Leader f3wzagmtgsn8qyqzidxtw98d3 node1 Ready Active [root@swarm_manager ~]# docker node inspect --pretty node2 ID: 622ih8ji5t428lazjx233pvks Hostname: node2 Joined at: 2017-10-25 06:45:04.369968305 +0000 utc Status: State: Ready Availability: Drain Platform: Operating System: linux Architecture: x86_64 Resources: CPUs: 1 Memory: 985.6 MiB Plugins: Network: bridge, host, null, overlay Volume: local Engine Version: 1.12.6
能夠看到該節點的狀態爲Ready
,但可用性爲Drain
。
[root@swarm_manager ~]# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR e69zhhxz66jmlm0h15gj89s2x redis.1 redis:3.2.5-alpine swarm_manager Running Running 8 minutes ago 63h5wy36474k01vmr5jppbbxs \_ redis.1 redis:3.0.7-alpine node1 Shutdown Shutdown 9 minutes ago 6q046y1camb43b146kj2jaxe4 redis.2 redis:3.2.5-alpine node1 Running Running about a minute ago 1h9e8m9v3rx3hgx5x2bn71kim \_ redis.2 redis:3.2.5-alpine node2 Shutdown Shutdown about a minute ago 39jitd0mzztl0mpy6k6rppkx5 \_ redis.2 redis:3.0.7-alpine swarm_manager Shutdown Shutdown 9 minutes ago 8pwrkq6558fwp8oiiu0uq484h redis.3 redis:3.2.5-alpine node1 Running Running 8 minutes ago 6usd4p2mj7p597ilgs490ou7a \_ redis.3 redis:3.0.7-alpine node2 Shutdown Shutdown 8 minutes ago
[root@swarm_manager ~]# docker node update --availability active node2 node2
[root@swarm_manager ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 622ih8ji5t428lazjx233pvks node2 Ready Active 9e21bk67ey1abzje69lmpvbe1 * swarm_manager Ready Active Leader f3wzagmtgsn8qyqzidxtw98d3 node1 Ready Active
說明如今該節點又能夠從新接收任務了。
再看看 node2
節點上是否被分配了任務:
[root@swarm_manager ~]# docker service ps -f desired-state=running redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR e69zhhxz66jmlm0h15gj89s2x redis.1 redis:3.2.5-alpine swarm_manager Running Running 10 minutes ago 6q046y1camb43b146kj2jaxe4 redis.2 redis:3.2.5-alpine node1 Running Running 2 minutes ago 8pwrkq6558fwp8oiiu0uq484h redis.3 redis:3.2.5-alpine node1 Running Running 9 minutes ago
desired-state
表示只列出處於活動狀態的任務。說明 node2雖然可用,但沒被分配任務。
一個可用性爲Active
的節點在如下狀況下能夠接收到新任務:
當一個服務在伸縮規模時
滾動更新時
當你把其餘某個節點的可用性設爲 Drain
時
當某個任務在另外某個 Active
節點上啓動失敗時