Docker Swarm

什么是 Docker Swarm

详细的解释可以看官方文档:https://docs.docker.com/engine/swarm/

 

在这之前我们都是在一台服务器上操作Docker,在实际企业中是远远不能满足需求的,企业中所需要的高可用、弹性伸缩等都不能够在单台服务上得到应用,所以我们实践中往往都是需要以集群模式部署,防止单点故障。

Swarm就是一个Docker公司推出的用来管理docker集群的平台,它可以将多台Docker主机组成Swarm集群,在Manager管理节点上实现对集群的管理,服务部署在Swarm集群中,可以很好解决服务高可用、可伸缩的需求,对于服务器不多又需要使用集群的场景,Swarm是个不错的选择,简单且易用。

不过随着不断变化的业务发展,Swarm已逐步被淘汰,目前主流大多为Kubernetes(k8s),Kubernetes所涉及的东西要比Swarm要多得多,但学习Swarm有助于我们后期对Kubernetes的理解,所以还是有必要了解的。

 

Swarm 工作模式

Node节点工作模式

Docker从1.12版本开始就引入了swarm模式,使你能够创建一个由一个或多个Docker引擎(主机)组成的集群,我们管这个集群叫做swarm集群。

一个swarm集群由一个或多个节点组成,有两种不同类型的节点(Node):manager 管理节点、worker 工作节点。

部署服务时,manager节点和worker节点都可以部署服务。

manager 管理节点:

Manager 节点负责处理集群管理任务:

集群使用Raft实现,Manager维护整个 swarm 和在其上运行的所有服务的一致内部状态。对于测试环境,你的swarm集群可以只有一个manager节点,如果这个集群的manager节点发生故障,你worker节点的服务将继续运行,但无法管理,直到manager节点恢复。

为了利用 swarm 模式的容错特性,Docker 建议根据组织的高可用性要求实现奇数个manager节点。当您有多个manager节点时,您可以从manager节点的故障中恢复而无需停机。

  • 集群中有3个manager节点,最多允许1个manager宕机;
  • 集群中有5个manager节点,最多允许2个manager宕机;
  • 集群中有N个manager节点,最多允许(N-1)/2个manager宕机;
  • Docker 建议一个 swarm 最多使用7个manger节点。

worker 工作节点:

工作节点也是 Docker 引擎的实例,其唯一目的是执行容器。Worker 节点不参与 Raft 分布式状态,不做调度决策,也不服务于 swarm 模式的 HTTP API。

您可以创建一个由1个manger节点组成的集群,如果没有至少1个manger节点,您就不能拥有1个worker节点。默认情况下,所有manger节点也是worker节点。在单个manger节点集群中,您可以运行类似docker service create的命令,并且调度程序将所有任务放在本地引擎上。

要防止调度程序将任务放置在多节点集群中的manager节点上,请将manager节点的可用性设置为Drain。调度器优雅地停止Drain模式节点上的任务,并在一个 Active节点上调度任务。调度程序不会将新任务分配给Drain 可用的节点。

请参阅docker node update 命令行参考以了解如何更改节点可用性。

 

services 工作模式

要在swarm中部署应用程序的镜像,需要首先创建一个服务(service),创建服务时,需要指定要运行的容器镜像以及在容器中执行的命令,此外还可以定义一些其他选项,如:端口映射、网络、CPU内存限制、滚动更新策略、副本数等。

服务、任务和容器

当您将服务部署到 swarm 时,swarm 管理节点接受您的服务定义作为服务的所需状态。然后,它将集群中的节点上的服务安排为一个或多个副本任务。这些任务在 swarm 中的节点上彼此独立运行。

例如,假设您想在nginx的三个实例之间进行负载平衡。下图显示了具有三个副本的 nginx服务。侦听器的三个实例中的每一个都是 swarm 中的一个任务。

services diagram

容器是一个独立的进程。在 swarm 模式模型中,每个任务只调用一个容器。任务类似于调度程序放置容器的“槽”。一旦容器处于活动状态,调度程序就会识别出任务处于运行状态。如果容器未通过健康检查或终止,则任务终止。

 

Swarm 集群搭建

下面我们将进行Swarm集群搭建,我们将使用4台主机分别搭建并测试:1manger+3worker、3manger+1worker 的集群架构。

主机规划

主机名 IP
docker-1 192.168.92.130
docker-2 192.168.92.152
docker-3 192.168.92.153
docker-4 192.168.92.154

修改主机名:

hostnamectl set-hostname docker-1
hostnamectl set-hostname docker-2
hostnamectl set-hostname docker-3
hostnamectl set-hostname docker-4

关闭防火墙:

systemctl stop firewalld
systemctl disable firewalld

 

安装 Docker环境

分别在4台服务器上安装Docker环境,安装教程:CentOS 7 安装 Docker-CE 并配置阿里云加速器

 

集群搭建

集群搭建主要为2步:

  • 初始化集群:docker swarm init --advertise-addr IPaddress
  • 节点加入集群:docker swarm join-token manager/worker 获取加入集群成为manager/worker节点的令牌

 

Swarm命令:

[root@docker-1 ~]# docker swarm --help

Usage:  docker swarm COMMAND

Manage Swarm

Commands:
  ca          Display and rotate the root CA
  init        Initialize a swarm                        # 初始化swarm集群
  join        Join a swarm as a node and/or manager     # 加入swarm集群
  join-token  Manage join tokens                        # 获取加入集群的token
  leave       Leave the swarm                           # 从swarm集群中移除 
  unlock      Unlock swarm
  unlock-key  Manage the unlock key
  update      Update the swarm

Run 'docker swarm COMMAND --help' for more information on a command.

初始化swarm集群:

[root@docker-1 ~]# docker swarm init --help

Usage:  docker swarm init [OPTIONS]

Initialize a swarm

Options:
      --advertise-addr string                  Advertised address (format: <ip|interface>[:port])

......

 

1manger+3worker 集群搭建

这里我们选择 docker-1 为管理节点,在此主机上初始化管理节点,192.168.92.130 为当前操作主机的IP

[root@docker-1 ~]# docker swarm init --advertise-addr 192.168.92.130
Swarm initialized: current node (vjq4rfdu2jr1peg56dr13hc1o) is now a manager.

To add a worker to this swarm, run the following command:

    # 在其他主机上运行此命令加入到集群成为worker节点
    docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-25zvr62tu4af0ukq20cnx3l7f 192.168.92.130:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

这里得到了一条带令牌的命令,在其他主机上运行此命令即可加入到swarm集群中成为worker节点。

如果上面的命令忘记或遗失,可以通过下面两个命令获取:

docker swarm join-token manager  # 获取加入swarm集群成为 管理节点 的令牌
docker swarm join-token worker   # 获取加入swarm集群成为 工作节点 的令牌

 

在docker-2、docker-3、docker-4上运行此命令,将docker-2、docker-3、docker-4加入集群使之成为worker节点。

[root@docker-2 ~]# docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-25zvr62tu4af0ukq20cnx3l7f 192.168.92.130:2377
This node joined a swarm as a worker.
[root@docker-3 ~]# docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-25zvr62tu4af0ukq20cnx3l7f 192.168.92.130:2377
This node joined a swarm as a worker.
[root@docker-4 ~]# docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-25zvr62tu4af0ukq20cnx3l7f 192.168.92.130:2377
This node joined a swarm as a worker.

查看集群信息:

在docker-1上,只能在manger管理节点上查看:

[root@docker-1 ~]# docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
vjq4rfdu2jr1peg56dr13hc1o *   docker-1   Ready     Active         Leader           20.10.12
iwem4frtz0rjhfh3p9gldb7nq     docker-2   Ready     Active                          20.10.12
oj7xmee9o0pkbcsu81x9uf0nq     docker-3   Ready     Active                          20.10.12
nyzvunyg368lmgw8zy3dq09ct     docker-4   Ready     Active                          20.10.12

此时可以看到我们已经搭建起了一个 1manager+3worker的集群。

1manager+3worker 虽然也可以正常工作,但是一旦唯一个一个manager宕机后,整个集群就无法工作了。此架构可用于测试,不可用于生产。

 

3manager+1worker集群搭建

接下来我们将架构改为 3manager+1worker的架构。这种架构可以允许1台manager宕机,整个集群依然工作。

我们将 docker-2、docker-3从worker节点改为manager节点:

1. 在docker-1主节点上运行 docker swarm join-token manager 获取加入swarm集群成为 管理节点 的令牌:

[root@docker-1 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

    # 加入到swarm集群成为manager节点的令牌
    docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-09f8pehylp76xf3fvmqdsu02k 192.168.92.130:2377

2. 在docker-2、docker-3上首先运行 docker swarm leave 离开集群,再运行docker-1上获取的加入集群成为manager节点的token

# 离开集群
[root@docker-2 ~]# docker swarm leave
Node left the swarm.

# 加入集群并成为manager
[root@docker-2 ~]# docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-09f8pehylp76xf3fvmqdsu02k 192.168.92.130:2377
This node joined a swarm as a manager.
# 离开集群
[root@docker-3 ~]# docker swarm leave
Node left the swarm.

# 加入集群并成为manager
[root@docker-3 ~]# docker swarm join --token SWMTKN-1-2tq4pgnc25y38ppx4osw1afxxcsmktcfxl4582k3y0v0qt992i-09f8pehylp76xf3fvmqdsu02k 192.168.92.130:2377
This node joined a swarm as a manager.

3. 查看集群信息:

[root@docker-1 ~]# docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
vjq4rfdu2jr1peg56dr13hc1o *   docker-1   Ready     Active         Leader           20.10.12
iwem4frtz0rjhfh3p9gldb7nq     docker-2   Down      Active                          20.10.12
r1lvb783up5gx1cce7hqupqff     docker-2   Ready     Active         Reachable        20.10.12
kbbqdd5ioypjwgos3redff6mu     docker-3   Ready     Active         Reachable        20.10.12
oj7xmee9o0pkbcsu81x9uf0nq     docker-3   Down      Active                          20.10.12
nyzvunyg368lmgw8zy3dq09ct     docker-4   Ready     Active                          20.10.12

此时可以看到就是一个3manager+1worker节点的集群架构。3个manager中一个是Leader、另外两个是 Reachable,当Leader挂掉的时候,则会根据Raft一致性算法从这两个Reachable的节点中选择一个成为Leader继续管理整个集群。

4. 同时可以看到里面有显示 docker-2、docker-3 状态为Down,这是因为运行了 docker swarm leave 的结果,运行之后节点就会变成Down,但并不会真正移除出集群,只是告知集群暂时离开了,真正从集群中移除需要执行 docker node rm 移除节点,如下:

# 移除docker-2
[root@docker-1 ~]# docker node rm iwem4frtz0rjhfh3p9gldb7nq
iwem4frtz0rjhfh3p9gldb7nq

# 移除docker-3
[root@docker-1 ~]# docker node rm oj7xmee9o0pkbcsu81x9uf0nq
oj7xmee9o0pkbcsu81x9uf0nq

# 再次查看集群节点信息
[root@docker-1 ~]# docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
vjq4rfdu2jr1peg56dr13hc1o *   docker-1   Ready     Active         Leader           20.10.12
r1lvb783up5gx1cce7hqupqff     docker-2   Ready     Active         Reachable        20.10.12
kbbqdd5ioypjwgos3redff6mu     docker-3   Ready     Active         Reachable        20.10.12
nyzvunyg368lmgw8zy3dq09ct     docker-4   Ready     Active                          20.10.12

 

Raft一致性算法

接下来我们来验证一下集群Raft一致性算法下的管理节点变化过程。

1. 将docker-1关机,模拟宕机,然后在另外两个主节点上查看集群情况:

[root@docker-2 ~]# docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
vjq4rfdu2jr1peg56dr13hc1o     docker-1   Down      Active         Unreachable      20.10.12
r1lvb783up5gx1cce7hqupqff *   docker-2   Ready     Active         Leader           20.10.12
kbbqdd5ioypjwgos3redff6mu     docker-3   Ready     Active         Reachable        20.10.12
nyzvunyg368lmgw8zy3dq09ct     docker-4   Ready     Active                          20.10.12

可以看到docker变成了 Down 并且 Unreachable状态,docker-2被选择为了新的 Leader.

 

2. 接下来我们继续将docker-3关机,模拟宕机,来看看集群情况:

[root@docker-2 ~]# docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

再次查看集群状态可以看到,虽然我们将docke-3停掉,按理说集群中还有docker-2是manager节点,并且是Leader,集群应该可以正常工作才是,但结果却不是那样的。

因为我们是一个3manger的集群,那么Raft一致性算法要求我们必须确保半数以上的manager节点在线,也就是3台manager必须有2台在线,5台manager必须有3台在线,那整个集群才能够正常的工作。

 

3. 重新将 docker-1、docker-3开机,再查看集群:

启动之后,集群正常工作了。

[root@docker-2 ~]# docker node ls       
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
vjq4rfdu2jr1peg56dr13hc1o     docker-1   Ready     Active         Reachable        20.10.12
r1lvb783up5gx1cce7hqupqff *   docker-2   Ready     Active         Leader           20.10.12
kbbqdd5ioypjwgos3redff6mu     docker-3   Ready     Active         Reachable        20.10.12
nyzvunyg368lmgw8zy3dq09ct     docker-4   Ready     Active                          20.10.12

 

服务管理

创建服务

Swarm特点:弹性、扩缩容

之前操作的 docker run 、docker-compose up 启动一个一项目,都是单机的;现在使用swarm集群,通过 docker service 来管理

之前单机:一个service就是指向的一个容器,比如一个 nginx服务指向一个nginx容器;

现在集群 :一个service可能指向一个或多个容器,比如对外暴露了一个nginx服务,实际上后端有多个nginx容器构成(就像负载均衡)。

命令:

[root@docker-1 ~]# docker service --help

Usage:  docker service COMMAND

Manage services

Commands:
  create      Create a new service                                    # 创建一个服务
  inspect     Display detailed information on one or more services    # 查看服务详细信息
  logs        Fetch the logs of a service or task                     # 查看日志
  ls          List services
  ps          List the tasks of one or more services
  rm          Remove one or more services                             # 移除服务
  rollback    Revert changes to a service's configuration
  scale       Scale one or multiple replicated services               # 伸缩一个或多个副本
  update      Update a service                                        # 更新服务

Run 'docker service COMMAND --help' for more information on a command.

创建服务:

[root@docker-1 ~]# docker service create -p 8888:80 --name my-nginx nginx
pvom9t9zbdkh3uk42jj3q06np
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged

查看服务:

# 通过 docker service ls 可以看到有哪些service在集群上 
# 当前只有一个 my-nginx service,当前只有1个副本,总共1个副本
[root@docker-1 ~]# docker service ls
ID             NAME       MODE         REPLICAS   IMAGE          PORTS
pvom9t9zbdkh   my-nginx   replicated   1/1        nginx:latest   *:8888->80/tcp


# 通过 docker service ps my-nginx 可以查看执行的service部署情况 
# 当前运行在 docker-3 机器上
[root@docker-1 ~]# docker service ps my-nginx
ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE           ERROR     PORTS
rdz0t33xdvxx   my-nginx.1   nginx:latest   docker-3   Running         Running 5 minutes ago

当前my-nginx服务中,真正nginx容器运行在docker-3上,docker-1虽然是manager节点,但也能跑服务。

访问测试:

尽管真正的nginx容器运行的docker-3上,但是由于是采用集群部署模式,此时无论使用集群中的哪个主机IP访问8888端口都能够访问到nginx服务。

http://192.168.92.130:8888/
http://192.168.92.152:8888/
http://192.168.92.153:8888/
http://192.168.92.154:8888/

 

扩缩容

两个方式:

  • docker service update
  • docker service scale

     

    通过 docker service update 扩缩容

    当前my-nginx只有1个副本,现在给它扩到3个,使用 docker service update --replicas 3 my-nginx

    [root@docker-1 ~]# docker service update --replicas 3 my-nginx
    my-nginx
    overall progress: 3 out of 3 tasks 
    1/3: running   [==================================================>] 
    2/3: running   [==================================================>] 
    3/3: running   [==================================================>] 
    verify: Service converged 
    
    [root@docker-1 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE          PORTS
    pvom9t9zbdkh   my-nginx   replicated   3/3        nginx:latest   *:8888->80/tcp
    
    
    # 3个nginx副本分别在 docker-1、docker-3、docker-4机器上各自启动了一个容器
    [root@docker-1 ~]# docker service ps my-nginx      
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1   nginx:latest   docker-3   Running         Running 17 minutes ago             
    m2h63c6g4aee   my-nginx.2   nginx:latest   docker-1   Running         Running 48 seconds ago             
    v0t9kqfplu9f   my-nginx.3   nginx:latest   docker-4   Running         Running 42 seconds ago

    访问测试:

    尽管docker-2上没有部署nginx容器,但是由于是采用集群部署模式,此时无论使用集群中的哪个主机IP访问8888端口都能够访问到nginx服务,包括docker-2。

    http://192.168.92.130:8888/
    http://192.168.92.152:8888/
    http://192.168.92.153:8888/
    http://192.168.92.154:8888/

     

    扩到10个:

    [root@docker-1 ~]# docker service update --replicas 10 my-nginx
    my-nginx
    overall progress: 10 out of 10 tasks 
    1/10: running   [==================================================>] 
    2/10: running   [==================================================>] 
    3/10: running   [==================================================>] 
    4/10: running   [==================================================>] 
    5/10: running   [==================================================>] 
    6/10: running   [==================================================>] 
    7/10: running   [==================================================>] 
    8/10: running   [==================================================>] 
    9/10: running   [==================================================>] 
    10/10: running   [==================================================>] 
    verify: Service converged 
    
    
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME          IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1    nginx:latest   docker-3   Running         Running 22 minutes ago             
    m2h63c6g4aee   my-nginx.2    nginx:latest   docker-1   Running         Running 5 minutes ago              
    v0t9kqfplu9f   my-nginx.3    nginx:latest   docker-4   Running         Running 4 minutes ago              
    tcfx6gcwcmwe   my-nginx.4    nginx:latest   docker-4   Running         Running 39 seconds ago             
    pmi5gdg62wsg   my-nginx.5    nginx:latest   docker-1   Running         Running 39 seconds ago             
    jvu3wmhpv7q2   my-nginx.6    nginx:latest   docker-2   Running         Running 19 seconds ago             
    nycvkr4ffnah   my-nginx.7    nginx:latest   docker-3   Running         Running 38 seconds ago             
    fr6nmwmkel41   my-nginx.8    nginx:latest   docker-2   Running         Running 19 seconds ago             
    u78vj5easfq0   my-nginx.9    nginx:latest   docker-2   Running         Running 19 seconds ago             
    ck5p63zoqsq6   my-nginx.10   nginx:latest   docker-3   Running         Running 38 seconds ago

    减到1个:

    [root@docker-1 ~]# docker service update --replicas 1 my-nginx
    my-nginx
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 
    
    
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1   nginx:latest   docker-3   Running         Running 22 minutes ago

     

    通过 docker service scale 扩缩容

    [root@docker-1 ~]# docker service scale my-nginx=4
    my-nginx scaled to 4
    overall progress: 4 out of 4 tasks 
    1/4: running   [==================================================>] 
    2/4: running   [==================================================>] 
    3/4: running   [==================================================>] 
    4/4: running   [==================================================>] 
    verify: Service converged 
    
    
    [root@docker-1 ~]# docker service ps my-nginx 
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1   nginx:latest   docker-3   Running         Running 24 minutes ago             
    kbzanlwvfffq   my-nginx.2   nginx:latest   docker-4   Running         Running 19 seconds ago             
    y1bkw76cnsxh   my-nginx.3   nginx:latest   docker-2   Running         Running 19 seconds ago             
    jqtazzjq715c   my-nginx.4   nginx:latest   docker-1   Running         Running 19 seconds ago

    综上:使用swarm扩缩容真的是轻轻松松。

     

    故障转移

    当前在每台主机上都运行着一个nginx容器,我们停止docker-4上的nginx容器,模拟容器出现故障。

    [root@docker-4 ~]# docker ps
    CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
    99c0465704ba   nginx:latest   "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   80/tcp    my-nginx.2.kbzanlwvfffqm4eu2nr9m390u
    
    [root@docker-4 ~]# docker stop 99c0465704ba
    99c0465704ba

    再来看看service运行情况:

    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME             IMAGE          NODE       DESIRED STATE   CURRENT STATE             ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1       nginx:latest   docker-3   Running         Running 27 minutes ago              
    0l0h4vh4tw79   my-nginx.2       nginx:latest   docker-4   Running         Running 8 seconds ago               
    kbzanlwvfffq    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Complete 14 seconds ago             
    y1bkw76cnsxh   my-nginx.3       nginx:latest   docker-2   Running         Running 3 minutes ago               
    jqtazzjq715c   my-nginx.4       nginx:latest   docker-1   Running         Running 3 minutes ago

    可以看到docker-4上的nginx容器已经 Shutdown了,自动在docker-4上重建了一个新的nginx容器。

    再次停止docker-4上重建的nginx容器,再次查看service运行情况,依然是在docker-4上重建的:

    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME             IMAGE          NODE       DESIRED STATE   CURRENT STATE             ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1       nginx:latest   docker-3   Running         Running 30 minutes ago              
    5121f134n75t   my-nginx.2       nginx:latest   docker-4   Running         Running 49 seconds ago              
    0l0h4vh4tw79    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Complete 55 seconds ago             
    kbzanlwvfffq    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Complete 3 minutes ago              
    y1bkw76cnsxh   my-nginx.3       nginx:latest   docker-2   Running         Running 6 minutes ago               
    jqtazzjq715c   my-nginx.4       nginx:latest   docker-1   Running         Running 6 minutes ago

     

    是不是停止哪个机器上的容器就在哪个机器上重建呢?

    直接将docker-4主机关机,再查看:

    此时docker-4上的nginx容器,自动转移到了docker-3主机上,并不受主机的影响,会在集群中自动调度。

    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME             IMAGE          NODE       DESIRED STATE   CURRENT STATE                     ERROR     PORTS
    rdz0t33xdvxx   my-nginx.1       nginx:latest   docker-3   Running         Running 31 minutes ago                      
    rsfjw6pck39l   my-nginx.2       nginx:latest   docker-3   Running         Starting less than a second ago             
    5121f134n75t    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Running 2 minutes ago                       
    0l0h4vh4tw79    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Complete 2 minutes ago                      
    kbzanlwvfffq    \_ my-nginx.2   nginx:latest   docker-4   Shutdown        Complete 4 minutes ago                      
    y1bkw76cnsxh   my-nginx.3       nginx:latest   docker-2   Running         Running 7 minutes ago                       
    jqtazzjq715c   my-nginx.4       nginx:latest   docker-1   Running         Running 7 minutes ago

     

    删除服务

    使用 docker service rm

    [root@docker-1 ~]# docker service rm my-nginx
    my-nginx
    
    [root@docker-1 ~]# docker service ls
    ID        NAME      MODE      REPLICAS   IMAGE     PORTS

     

    镜像变更/升级

    重新新建service来测试:

    docker service create -p 8888:80 --name my-nginx nginx
    # 将镜像变更为 nginx:1.20 
    [root@docker-1 ~]# docker service update --image nginx:1.20 my-nginx
    my-nginx
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged
    # 老镜像nginx:latest停止,新镜像nginx:1.20启用
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME             IMAGE          NODE       DESIRED STATE   CURRENT STATE                 ERROR     PORTS
    z2gmcjtljhqg   my-nginx.1       nginx:1.20     docker-3   Running         Running about a minute ago              
    svh5jpysqcc3    \_ my-nginx.1   nginx:latest   docker-3   Shutdown        Shutdown about a minute ago

     

    回滚到上个版本

    # 回滚到上个版本
    [root@docker-1 ~]# docker service update --rollback my-nginx
    my-nginx
    rollback: manually requested rollback 
    overall progress: rolling back update: 1 out of 1 tasks 
    1/1: running   [>                                                  ] 
    verify: Service converged 
    
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME             IMAGE          NODE       DESIRED STATE   CURRENT STATE             ERROR     PORTS
    xak0904ma7wf   my-nginx.1       nginx:latest   docker-1   Running         Running 12 seconds ago              
    z2gmcjtljhqg    \_ my-nginx.1   nginx:1.20     docker-3   Shutdown        Shutdown 13 seconds ago             
    svh5jpysqcc3    \_ my-nginx.1   nginx:latest   docker-3   Shutdown        Shutdown 6 minutes ago

     

    删除service:

    [root@docker-1 ~]# docker service rm my-nginx
    my-nginx

     

    更多使用用法请看:

    docker service update --help

     

    数据卷挂载

    我们之前已经学习过在容器中使用volume数据卷,这里我们来看看如何在swarm集群中使用数据卷。

    volume数据卷

    创建一个新的数据卷:

    [root@docker-1 ~]# docker volume create my-volume
    my-volume
    
    
    [root@docker-1 ~]# docker volume ls
    DRIVER    VOLUME NAME
    local     my-volume
    
    
    [root@docker-1 ~]# docker volume inspect my-volume
    [
        {
            "CreatedAt": "2022-03-10T16:45:01+08:00",
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
            "Name": "my-volume",
            "Options": {},
            "Scope": "local"
        }
    ]

    创建一个service并使用数据库挂载:

    # 创建service并使用volume挂载
    # src可写为source,dst可写为target
    [root@docker-1 ~]# docker service create --replicas 3 --mount type=volume,src=my-volume,dst=/vol_test --name my-nginx nginx
    frar0fbts1f3ezwyttweoa10r
    overall progress: 3 out of 3 tasks 
    1/3: running   [==================================================>] 
    2/3: running   [==================================================>] 
    3/3: running   [==================================================>] 
    verify: Service converged 
    
    
    [root@docker-1 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE          PORTS
    frar0fbts1f3   my-nginx   replicated   3/3        nginx:latest   
    
    
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    jbz6e1w0ce7n   my-nginx.1   nginx:latest   docker-1   Running         Running 18 seconds ago             
    q4fuyxb7ctph   my-nginx.2   nginx:latest   docker-3   Running         Running 17 seconds ago             
    f3ce25vrbrpb   my-nginx.3   nginx:latest   docker-2   Running         Running 18 seconds ago

    在3个主机上部署了nginx容器,查看有没有挂载成功,我们逐个登录主机进入容器查看:

    首先看docker-1机器:

    [root@docker-1 ~]# docker exec -it 7865bec81dce /bin/bash
    root@7865bec81dce:/# ls /vol_test/
    root@7865bec81dce:/# echo "This is volume test from docker-1" > /vol_test/docker-1.txt
    root@7865bec81dce:/# ls /vol_test/
    docker-1.txt
    root@7865bec81dce:/# exit
    exit
    [root@docker-1 ~]# ls /var/lib/docker/volumes/my-volume/_data/
    docker-1.txt
    [root@docker-1 ~]# cat /var/lib/docker/volumes/my-volume/_data/docker-1.txt 
    This is volume test from docker-1

    再来看 docker-2、docker-3 发现,我们在docker-1容器里创建的文件,docker-2、docker-3的容器里并没有,说明通过此方式挂载的数据卷只能用于本地,是不能够共享的。

     

    另一种挂载方式:

    语法:
    docker service create --mount type=bind,source=/host_dir,target=/container_dir
    
    # source路径要求在部署的目标机器上真实存在,比如部署3个副本有可能分部在不同主机,那每个主机上都必须要存在此目录

    示例:

    [root@docker-1 ~]# docker service create --mount type=bind,source=/opt/web,target=/usr/share/nginx/html -p 8888:80 --name my-nginx nginx
    mumiyabkxyceeymzmkeoz637q
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 
    
    [root@docker-1 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE          PORTS
    mumiyabkxyce   my-nginx   replicated   1/1        nginx:latest   *:8888->80/tcp
    
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    jwmr1e9zn1uk   my-nginx.1   nginx:latest   docker-3   Running         Running 33 seconds ago

    部署到了docker-3.

    在docker-3机器上 /opt/web/目录下创建一个index.html 文件:

    [root@docker-3 ~]# echo "This is test from docker-3" > /opt/web/index.html
    
    [root@docker-3 ~]# ls /opt/web/
    index.html

    访问测试:

    使用任意主机IP访问8888端口:

    [root@docker-1 ~]# curl http://192.168.92.153:8888
    This is test from docker-3

    删除service:

    [root@docker-1 ~]# docker service rm my-nginx
    my-nginx

    小总结:

    通过以上对数据卷的操作案例可以看出,数据卷之间的数据是不能够在集群中共享的,对于集群部署意义并不大,如果能共享数据才是极好的,可以使用nfs解决。

     

    通过nfs在集群中共享数据:

    我们需要用一台服务器当作nfs服务器,这里我们把docker-4当作nfs服务器,在docker-4上安装nfs服务。

    yum install nfs-utils -y
    mkdir -p /data/nfs
    
    # 编辑 /etc/exports 文件,内容如下
    [root@docker-4 ~]# cat /etc/exports
    /data/nfs 192.168.92.0/24(rw,no_root_squash)
    
    # 启动nfs
    systemctl start nfs
    systemctl enable nfs

    创建服务:

    [root@docker-1 ~]#  docker service create --mount 'type=volume,source=nfsvolume,target=/usr/share/nginx/html,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/data/nfs,"volume-opt=o=addr=192.168.92.154,rw,nfsvers=4,async"'  --replicas 4 -p 8888:80 --name my-nginx nginx
    vqxjrbz91rdy9yutgnfmt2icc
    overall progress: 4 out of 4 tasks 
    1/4: running   [==================================================>] 
    2/4: running   [==================================================>] 
    3/4: running   [==================================================>] 
    4/4: running   [==================================================>] 
    verify: Service converged 
    [root@docker-1 ~]# 
    [root@docker-1 ~]# docker service ls
    ID             NAME       MODE         REPLICAS   IMAGE          PORTS
    vqxjrbz91rdy   my-nginx   replicated   4/4        nginx:latest   *:8888->80/tcp
    [root@docker-1 ~]# 
    [root@docker-1 ~]# docker service ps my-nginx
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE            ERROR     PORTS
    yuwkqgd3mlyb   my-nginx.1   nginx:latest   docker-3   Running         Running 15 seconds ago             
    h6n3t2v9c04x   my-nginx.2   nginx:latest   docker-2   Running         Running 16 seconds ago             
    igoqir801uhu   my-nginx.3   nginx:latest   docker-4   Running         Running 16 seconds ago             
    3jibweokor60   my-nginx.4   nginx:latest   docker-1   Running         Running 16 seconds ago

    查看volume:

    [root@docker-1 ~]# docker volume ls
    DRIVER    VOLUME NAME
    local     nfsvolume
    [root@docker-1 ~]# 
    [root@docker-1 ~]# docker volume inspect nfsvolume
    [
        {
            "CreatedAt": "2022-03-10T17:44:05+08:00",
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/var/lib/docker/volumes/nfsvolume/_data",
            "Name": "nfsvolume",
            "Options": {
                "device": ":/data/nfs",
                "o": "addr=192.168.92.154,rw,nfsvers=4,async",
                "type": "nfs"
            },
            "Scope": "local"
        }
    ]

    每个机器上都自动创建了 nfsvolume 数据卷。

     

    访问测试:

    在 docker-4 上向/data/nfs/目录下创建一个index.html文件

    [root@docker-4 ~]# echo "This is nfs volume test from docker-4" > /data/nfs/index.html

    访问:

    [root@docker-1 ~]# curl http://192.168.92.130:8888
    This is nfs volume test from docker-4

    成功访问到,成功。

     

    多服务Swarm集群部署

    前面我们操作的都是单个服务在swarm集群中部署,那如果要一次部署多个服务呢?

    实际上我们可以利用compose来实现,compose默认只是针对多个服务在单机上批量部署的,但我们可以利用到compose中的deploy来定义在集群中如何部署。

    关于deploy的官方文档:  https://docs.docker.com/compose/compose-file/compose-file-v3/#deploy

    deploy 部分的配置只在使用 docker stack deploy 部署到swarm集群中有效,使用 docker-compose 和 docker-compose run 时,deploy部分的配置将会忽略不会被执行。

    如下 compose.yml

    version: "3.9"
    services:
      redis:
        image: redis:alpine
        deploy:
          replicas: 6
          placement:
            max_replicas_per_node: 1
          update_config:
            parallelism: 2
            delay: 10s
          restart_policy:
            condition: on-failure

    启动部署并查看:

    # 启动部署
    [root@docker-1 ~]# docker stack deploy -c compose.yml up
    Creating network up_default
    Creating service up_redis
    
    # 看到共计6个副本,成功了4个,因为 (max 1 per node) 每一个节点最多只运行1个副本,这里我们只有4个节点,所以只有4个副本运行成功
    [root@docker-1 ~]# docker service ls
    ID             NAME       MODE         REPLICAS               IMAGE          PORTS
    p0pn2w313tob   up_redis   replicated   4/6 (max 1 per node)   redis:alpine   
    
    # 每个node上只有一个副本在运行,因为compose.yml中定义了 max_replicas_per_node: 1 每一个节点最多只运行1个副本,这里我们只有4个节点,所以看到有两个失败
    [root@docker-1 ~]# docker service ps up_redis
    ID             NAME         IMAGE          NODE       DESIRED STATE   CURRENT STATE                ERROR                              PORTS
    t9b1s57ckrqq   up_redis.1   redis:alpine   docker-2   Running         Running about a minute ago                                      
    56oplb1h7n3e   up_redis.2   redis:alpine   docker-4   Running         Running about a minute ago                                      
    layzi9ggfu4u   up_redis.3   redis:alpine   docker-3   Running         Running about a minute ago                                      
    y67mnxyppjcb   up_redis.4   redis:alpine              Running         Pending about a minute ago   "no suitable node (max replica…"   
    56ouwyy0akwi   up_redis.5   redis:alpine              Running         Pending about a minute ago   "no suitable node (max replica…"   
    sa8qso0r9m50   up_redis.6   redis:alpine   docker-1   Running         Running about a minute ago

     

     

    版权声明:
    作者:admin
    链接:https://www.chenxie.net/archives/2643.html
    来源:蜀小陈
    文章版权归作者所有,未经允许请勿转载。

    THE END
    分享
    二维码
    < <上一篇
    下一篇>>
    文章目录
    关闭
    目 录