Docker swarm部署

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker swarm部署相关的知识,希望对你有一定的参考价值。

本教程将介绍 Docker Engine Swarm 模式。先介绍 swarm 模式几个关键的概念,然后通过动手实践带你体验一下 swarm 模式。

几个关键概念

Swarm

Docker Engline 中集成的集群管理和编排功能都是基于 SwarmKit 实现。参与到集群中的 Docker Engine 会进入 swarm 模式。比如初始化一个 swarm 或加入已有的 swarm。

一个 swarm 就是个一个 Docker Engine 集群,你可以在上面部署服务。Docker Engine CLI 提供了用于 swarm 管理的命令,比如添加或移除一个节点。同样还提供了用于部署服务到 swarm 和管理服务编排的命令。

当 Docker Engine 运行在 swarm 模式时,你管理容器。当 Docker Engine 运行在 swarm 模式时,你编排服务。

节点

每个参与到 swarm 中的 Docker Engine 都称之为一个节点。

将服务的定义提交到管理节点即可将应用部署到 swarm。然后管理节点将叫作任务的工作单元分发到工作节点。

为了维持 swarm 的目标状态,管理节点还将承当编排和集群管理的功能。一般有多个管理节点,它们之间会选出一个领导来进行编排任务。

工作节点接收并执行来自管理节点分发的任务。默认情况下,管理节点也是工作节点,你可以把它配置成只当管理节点。代理通知管理节点已分配任务的当前状态,以便管理节点维护所需的状态。

服务和任务

服务定义了需要在工作节点上执行的任务。它是 swarm 系统的中心结构,也是用户和 swarm 交互的主要根源。

服务包括要使用的容器镜像,以及在容器中执行的指令。

对于复制服务,管理节点根据服务的规模和目标状态将一定数量的任务副本分发到各节点上。

对于全局服务,每个节点上都将分发一个任务副本。

任务包含一个容器和需要在容器中执行的指令。它是 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:

[[email protected]_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的当前状态

[[email protected]_manager ~]# docker info
...
Swarm: active
 NodeID: 7ik7wqhe5wcag8k5tp816c7ck
 Is Manager: true
 ClusterID: 2scd04fv8c9mua1jiaq6n0370
 Managers: 1
 Nodes: 1
 ...
 
 执行 docker node ls 命令查看节点信息
 
[[email protected]_manager ~]# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS     
9e21bk67ey1abzje69lmpvbe1 *  swarm_manager  Ready   Active        Leader

节点 id 后面的*表示你当前连接到了该节点。

添加节点到 swarm

添加两个工作节点到swarm

在第二台主机上,执行前面创建 swarmdocker swarm init 输出信息中命令创建工作节点并加入到 swarm

[[email protected] ~]# 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 查询怎么加入。

[[email protected]_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

[[email protected] ~]# docker swarm join \     
       --token SWMTKN-1-0p0p5f96e1w4xblhw2eeookrv46spwf4yx7qmve2srxe9wec5g-ellbnyt4cwwvvdkssaj0cbtus      192.168.59.128:2377
     This node joined a swarm as a worker.

查看所有节点的状态

在管理节点上

[[email protected]_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”:

[[email protected]_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

查看服务列表

还是在管理节点上

[[email protected]_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

查看服务的详细信息

查看服务的详细信息

在管理节点上。

[[email protected]_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参数即可。



查看哪个节点在运行该服务

还是在管理节点上:

[[email protected]_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命令查看相关容器的详细信息

[[email protected] ~]# 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

伸缩服务

伸缩服务的任务数量

在管理节点上

[[email protected] ~]# docker service scale helloworld=5
helloworld scaled to 5
我们将服务的数量伸缩到5。

查看服务列表

在管理节点上:

[[email protected]_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

在各节点上查看服务

首先是管理节点:

[[email protected]_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

[[email protected] ~]# 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

[[email protected] ~]# 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 上运行的服务

删除

在管理节点上

[[email protected]_manager ~]# docker service rm helloworld
helloworld

确认

在管理节点上

[[email protected]_manager ~]# docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND
[[email protected]_manager ~]#

看不到任何服务了。


滚动更新

在这部分,我们将部署一个基于 Rddis 3.07 镜像的服务。然后使用滚动更新将服务更新到使用 Redis 3.2.5 镜像。

swarm中部署 Redis 3.0.7,并配置 10 秒更新延迟

[[email protected]_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服务

[[email protected]_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策略来更新节点

[[email protected]_manager ~]# docker service update --image redis:3.2.5-alpine redis 
redis

调度器根据下面默认的策略来应用滚动更新:

  • 停止第一个任务。

  • 为停止的任务应用更新。

  • 为更新的任务启动容器。

  • 如果更新任务时返回RUNNING,等待一个指定的延时后停止下一个任务。

  • 如果,在更新的任意时刻,某个任务返回FAILED,暂停更新。

查看新镜像的状态

[[email protected]_manager ~]# docker service update --image redis:3.2.5-alpine redis 
redis
[[email protected]_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。不过状态还在更新中。过一会再查看:

[[email protected]_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:

可以看到更新完成。

查看滚动更新后服务的状态

[[email protected]_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。说明滚动更新已完成。

再看看容器信息

[[email protected]_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 的节点上启动相应的任务副本。

确认所有节点都是活跃可用的

[[email protected]_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 下线:

[[email protected]_manager ~]# docker node update --availability drain node2
node2

查看被下线节点的详细信息

[[email protected]_manager ~]# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
622ih8ji5t428lazjx233pvks    node2          Ready   Drain         
9e21bk67ey1abzje69lmpvbe1 *  swarm_manager  Ready   Active        Leader
f3wzagmtgsn8qyqzidxtw98d3    node1          Ready   Active        
[[email protected]_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

再次查看任务的分配情况

[[email protected]_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

再次将被下线的节点重置为活动状态

[[email protected]_manager ~]# docker node update --availability active node2
node2

确认该节点的新状态

[[email protected]_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 节点上是否被分配了任务:

[[email protected]_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 节点上启动失败时




以上是关于Docker swarm部署的主要内容,如果未能解决你的问题,请参考以下文章

Docker集群管理工具-Swarm部署记录

如何使用未部署在 swarm 中的 docker 容器从 docker swarm 访问服务?

Docker swarm部署

从零开始轻松部署Docker Swarm集群

docker swarm集群部署

docker swarm集群及其UI部署