Docker swarm部署

本教程將介紹 Docker Engine Swarm 模式。先介紹 swarm 模式幾個關鍵的概念,而後經過動手實踐帶你體驗一下 swarm 模式。node

幾個關鍵概念

Swarm

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

建立一個 swarm

隨意選擇一個主機做爲管理節點,在上面初始化一個 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

在第二臺主機上,執行前面建立 swarmdocker 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 STATECURRENT STATE表示服務的指望狀態和當前狀態,你能夠對比它們,判斷服務是否想指望的那樣運行。這裏的RunningRunning 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 節點上啓動失敗時

相關文章
相關標籤/搜索