容器编排部署工具除 Google 推出的 Kubernetes 之外,还有 Docker 发布的 Swarm 与 Mesos 推出的 Marathon。本章将从基本概念、工作原理与安装部署及管理等方面介绍 Docker 官方推出的 Docker Swarm。

目录

一、案例一 Docker Swarm 群集部署

1.1、案例概述 

1.2、案例前置知识点 

1)Docker Swarm 概述 

2)基本特性 

3)关键概念 

4)工作原理 

1.3、案例环境 

1)案例环境 

2)案例需求 

3)案例实现思路 

二、案例一实施 

2.1、配置 Docker Swarm 部署环境 

1)主机配置 

2)安装 Docker 

2.2、部署 Docker Swarm 群集 

1)创建 Docker Swarm 群集 

2)添加 worker 节点到 Swarm 集群 

3)查看 Swarm 集群中 Node 节点的详细状态信息 

三、案例二 Docker Swarm 管理 

3.1、案例概述 

3.2、案例前置知识点 

1)Docker Swarm 中的节点 

2)服务和任务 

3.3、案例环境 

1)本案例实验环境 

2)案例需求 

3)案例实现思路 

四、案例二实施 

4.1、Docker Swarm 节点管理 

1)节点状态变更管理 

2)添加标签元数据 

3)节点提权 / 降权 

4)退出 Swarm 集群 

4.2、Docker Swarm 服务管理 

1)创建服务 

2)显示服务详细信息 

3)服务的扩容与缩容 

4)删除服务 

5)滚动更新 

6)添加自定义 Overlay 网络 

7)数据卷创建与应用 


一、案例一 Docker Swarm 群集部署

Docker 自诞生以来,其容器特性以及镜像特性给 DevOps 爱好者带来诸多方便。然而在很长一段时间内,Docker 只能在单机上运行,其跨主机部署、运行与管理能力颇受外界诟病。跨主机能力薄弱,导致 Docker 容器与主机的形成高度耦合,降低了 Docker 容器的灵活性,难以实现容器的迁移、分组等功能。 

1.1、案例概述 

创鑫公司给云计算工程师提出新的要求,可将集群中所有 Docker Engine 整合进一个虚拟的资源池,通过执行命令与单一的主 Swarm 进行沟通,而不必分别和每个 Docker Engine 沟通。在灵活的调度策略下,IT 团队可以更好地管理可用的主机资源,保证应用容器的高效运行。 

1.2、案例前置知识点 

1)Docker Swarm 概述 

Docker Swarm 是 Docker 社区提供的基于 Docker 的集群管理调度工具,能够将多台主机构建成一个 Docker 集群,用户通过 API 来管理多个主机上的 Docker,并结合 Overlay 网络实现容器的调度与相互访问。 

Docker Swarm 默认对外提供两种 API。 

  1. 标准的 Docker API:包括 Docker Client、Dokku、Compose、DockerUI、Jenkins 等,它们可以通过 Swarm 工具与 Docker 集群进行通信;
  2. 集群管理 API:用于集群的管理。

2)基本特性 

Docker 集群管理和编排的特性是通过 SwarmKit 进行构建的, 其中 Swarm 模式是 Docker Engine 内置支持的一种默认实现。Docker 1.12 以及更新的版本,都支持 Swarm 模式。用户可以基于 Docker Engine 构建 Swarm 集群,然后就可以将应用服务(Application Service)部署到 Swarm 集群中。 

Docker Swarm 具有如下基本特性:

  1. 集群管理集成进 Docker Engine:使用内置的集群管理功能,可以直接通过 Docker CLI 命令来创建 Swarm 集群,并部署应用服务,而不需要其它外部软件来创建和管理 Swarm 集群。
  2. 去中心化设计:Swarm 集群中包含管理节点(Manager)和工作节点(Worker)两类,可以直接基于 Docker Engine 来部署任何类型的节点。在 Swarm 集群运行期间,可以对其作出任何改变,实现对集群的扩容和缩容等,如添加与删除节点。而做这些操作时不需要暂停或重启当前的 Swarm 集群服务。
  3. 声明式服务模型:在实现的应用栈中,Docker Engine 使用了一种声明的方式,可以定义各种所期望的服务状态。
  4. 缩放:对于每个服务,可以声明要运行的任务数。向上或向下扩展时,Swarm 集群会通过添加或删除任务来自动调整以维持所需的状态。
  5. 协调预期状态与实际状态的一致性:管理节点会不断地监控并协调集群的状态,使得 Swarm 集群的预期状态和实际状态保持一致。例如启动一个应用服务,指定服务副本为 10,则会启动 10 个 Docker 容器去运行。如果某个工作节点上面运行的 2 个 Docker 容器挂掉了,管理节点会在 Swarm 集群中其它可用的工作节点上创建 2 个服务副本, 使得实际运行的 Docker 容器数保持与预期的 10 个一致。
  6. 多主机网络:Swarm 集群支持多主机网络,可以为服务指定覆盖网络。管理节点在初始化或更新应用程序时自动为覆盖网络上的容器分配地址。
  7. 服务发现:管理节点会给 Swarm 集群中每一个服务分配一个唯一的 DNS 名称,对运行中的 Docker 容器进行负载均衡。可以通过 Swarm 内置的 DNS 服务器,查询 Swarm 集群中运行的 Docker 容器状态。
  8. 负载均衡:在 Swarm 集群中,可以指定如何在各个 Node 之间分发服务容器(Service Container),实现负载均衡。如果想要使用 Swarm 集群外部的负载均衡器,可以将服务容器的端口暴露到外部。
  9. 默认安全:Swarm 集群中的每个节点都强制执行 TLS 相互身份验证和加密,以保护自身与所有其他节点之间的通信。用户可以选择使用自签名根证书或自定义根 CA 的证书。
  10. 滚动更新:对于服务需要更新的场景,可以在多个节点上进行增量部署更新,在 Swarm 管理节点使用 Docker CLI 设置一个 delay(延迟)时间间隔,实现多个服务在多个节点上依次进行部署,这样可以非常灵活地控制。如果有一个服务更新失败,则暂停后面的更新操作,重新回滚到更新之前的版本。 

3)关键概念 

下面是 Docker Swarm 中主要的关键概念。 

  • 节点 

每个参与到 Swarm 集群中的 Docker Engine 都称之为一个节点。在单个物理计算机或云服务器上运行一个或多个节点,但是生产环境下的集群部署通常包括分布在多个物理和云机器上的 Docker 节点。集群中节点主要分为管理节点与工作节点。 

若要将应用程序部署到集群中,则需要将服务定义提交给管理节点。管理节点将被称为任务的工作单元分派给工作节点。为了维持 Swarm 集群的目标状态,管理节点还将承担编排和集群管理的功能。一旦存在多个管理节点时,会选出一个领导来进行任务编排。 

工作节点用于接收并执行来自管理节点分发的任务。默认情况下,管理节点也是工作节点,也可以把它配置成只充当管理节点的角色。工作节点将所负责任务的当前状态通知给管理节点,以便管理节点可以维护每个工作节点的期望状态。

  • 服务与任务

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

创建服务时,可以指定要使用的容器镜像以及在运行容器中执行的命令。

在复制服务模型中,Swarm 管理器根据所需状态中设置的比例在节点之间分配特定数量的副本任务。

任务是 Swarm 集群中最小的调度单位,每个任务都包含一个容器和需要在容器中执行的指令。管理器根据服务中定义的副本数量将任务分配给工作节点。一旦某个任务被分配到某个节点,就不能再移动到其他节点。它只能在分配的节点上运行或者失败。

  • 负载均衡

集群管理器使用负载均衡入口来公开对外提供的服务。集群管理器可以自动为 PublishedPort(对外发布的端口)分配服务,也可以为服务配置 PublishedPort。部署服务时可以指定任何未使用的端口为服务端口;如果部署服务时未指定端口,Swarm 管理器会为服务自动分配 30000-32767 范围内的端口。 

外部组件(例如云负载均衡器)可以访问集群中任何节点的 PublishedPort 上的服务,无论该节点当前是否正在运行该服务的任务。集群中的所有节点都将入口连接到正在运行的任务实例。

Swarm 模式有一个内部 DNS 组件,可以自动为 Swarm 中的每个服务分配一个 DNS 条目。集群管理器使用内部负载均衡来根据服务的 DNS 名称在集群内的服务之间分发请求。

4)工作原理 

在 Swarm 集群中部署镜像创建一个服务时。在一些大的应用上下文环境中需要各种服务配合工作,这样的服务通常称之为微服务。微服务可能是一个 HTTP 服务器、数据库、 或者分布式环境中运行的任何其他可执行的程序。 

在创建服务时,可以指定要使用的容器镜像以及容器中要运行的命令。服务还可以定义下面选项:

  1. 集群要对外服务的端口;
  2. 在集群中用于服务之间相连的 Overlay 网络;
  3. 滚动更新策略;
  4. 集群总运行的副本数量。 

下面从以下几个方面具体介绍服务、任务与容器的具体工作方法。

  • 服务、任务与容器 

当服务部署到集群时,Swarm 管理节点会将服务定义作为服务所需状态。然后将服务调度为一个或多个副本任务。这些任务在集群节点上彼此独立运行。 

容器是一个独立的进程。在 Swarm 集群中,每个任务都会调用一个容器。一旦容器运行,调度程序认为该任务处于运行状态。如果容器健康监测失败或者终止,那么任务也终止。

  • 任务与调度 

任务是集群内调度的原子单位。当创建或者更新服务来声明所需的服务状态时,协调器通过调度任务来实现所需的状态。

任务是单向的机制,它通过一系列状态单独进行:分配、准备、运行等操作。如果任务失败,协调器将删除任务与容器,然后根据服务指定的所需状态创建一个新的任务来代替它。 

  • 待处理的服务

配置服务时,若集群中当前没有可用的节点。在这种情况下,也可以成功配置服务,但所配置服务会处于待处理状态(挂起状态)。以下是服务可能处于待处理状态的几个示例。 

如果在集群中所有节点被暂停或耗尽时,创建了一个服务,服务则被挂起,直到节点可用。实际上,当节点恢复时,第一个可用的节点将会获得所有的任务,这在生产环境中并不是一件好事。

  1. 配置服务时可以为服务预留特定数量的内存。如果集群中没有节点满足所需的内存量, 服务则被挂起,直到有可用的节点运行其任务。如果指定了非常大的内存值(如 500G), 任务将永久挂起,除非确实有一个满足该条件的节点。 
  2. 配置服务时可以对服务施加约束,并且可能无法在给定时间履行约束,服务则被挂起。
  • 副本和全局服务 

服务部署分为两种类型:副本服务和全局服务。 

  1. 副本服务:指定要运行的相同任务的数量,每个副本都是相同的内容。
  2. 全局服务:是在每个节点上运行一个任务的服务。不需要预先指定任务数量。每当将一 个节点添加到集群中,调度器将创建一个任务,并且调度器将任务分配给新加入的节点。 全局服务最好是监控代理、反病毒扫描程序等等想要在集群中每个节点上运行的容器。 

1.3、案例环境 

1)案例环境 

主机操作系统主机名 / IP 地址主要软件
服务器CentOS 7.9manager / 192.168.23.212Docker-ce-19.03.15
服务器CentOS 7.9worker01 / 192.168.23.213Docker-ce-19.03.15
服务器CentOS 7.9worker02 / 192.168.23.214Docker-ce-19.03.15

 实验环境

案例实验环境的网络拓扑如下图所示。 

 实验网络拓扑

2)案例需求 

本案例的需求如下:

部署 Docker Swarm 集群,要求集群中包含一个管理节点(manager)和两个工作节点 (worker01、worker02)。 

3)案例实现思路 

本案例的实现思路如下: 

  • 准备 Docker Swarm 部署环境;
  • 部署 Docker Swarm 集群。 

二、案例一实施 

2.1、配置 Docker Swarm 部署环境 

在部署 Docker Swarm 之前需要先对服务器进行基础的环境配置。 

1)主机配置 

  • 设置主机名 

在三台主机上分别设置主机名。 

[root@centos7-12 ~]# hostnamectl set-hostname manager
[root@centos7-12 ~]# bash
[root@manager ~]# 

[root@centos7-13 ~]# hostnamectl set-hostname worker01
[root@centos7-13 ~]# bash    
bash
[root@worker01 ~]#

[root@centos7-14 ~]# hostnamectl set-hostname worker02
[root@centos7-14 ~]# bash
bash
[root@worker02 ~]#
  • 修改 hosts 文件 

在所有主机的 hosts 文件中添加地址解析记录,下面以 manager 主机为例进行操作。 

[root@manager ~]# vim /etc/hosts
......//省略部分内容
192.168.23.212 manager
192.168.23.213 worker01
192.168.23.214 worker02
  • 关闭防火墙 
[root@manager ~]# systemctl stop firewalld
  • 禁用 Selinux 
[root@manager ~]# getenforce
Disabled

2)安装 Docker 

在所有主机上安装并配置 Docker。下面以 manager 主机为例进行操作。 

[root@manager ~]# yum install -y yum-utils device-mapper-persistent-data lvm2  //安装一些必要的系统工具
[root@manager ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  //添加 Docker 源地址
[root@manager ~]# yum -y install docker-ce-19.03.15 docker-ce-cli-19.03.15  //安装 Docker
[root@manager ~]# mkdir /etc/docker
[root@manager ~]# vim /etc/docker/daemon.json  //配置 Docker 镜像加速
{
  "registry-mirrors": ["https://z1qbjqql.mirror.aliyuncs.com"]
}
[root@manager ~]# systemctl daemon-reload
[root@manager ~]# systemctl enable --now docker

2.2、部署 Docker Swarm 群集 

安装完 Docker 后,可以使用 docker swarm 命令创建 Docker Swarm 集群。 

1)创建 Docker Swarm 群集 

创建 Docker Swarm 集群命令格式为:

docker swarm init --advertise-addr <MANAGER-IP> 

其中:--advertise-addr 选项用于指定 Swarm 集群中管理节点(manager node)的 IP 地址,后续工作节点(worker node)加入集群时,必须能够访问管理节点的 IP 地址。在 manager 主机上,执行如下命令即可创建一个 Swarm 集群。 

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

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

    docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-7ychlv6x2srik0ef5ctlficvx 192.168.23.212:2377

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

 上述命令结果显示,Swarm 集群已创建成功,并给出其他节点如何加入集群的操作引导信息:

  • 工作节点加入集群:执行 docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-7ychlv6x2srik0ef5ctlficvx 192.168.23.212:2377 命令,将工作节点添加到 Swarm 集群中。 

注意:如果未看到提示信息,也可以通过 docker swarm join-token worker 命令重新获取该提示信息。 

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

    docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-7ychlv6x2srik0ef5ctlficvx 192.168.23.212:2377
  • 管理节点加入集群:执行 docker swarm join-token manager 命令,获取管理节点加入到 Swarm 集群的命令。当配置 Swarm 集群的 HA 时可以使用该命令设置多个管理节点 。
[root@manager ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-4pi7c3u93cilliwjpkqrhg55q 192.168.23.212:2377

2)添加 worker 节点到 Swarm 集群 

在 worker01、worker02 两个工作节点上,执行以下命令,将工作节点加入到 Swarm 集群中,具体操作如下所示。 

[root@worker01 ~]# docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-7ychlv6x2srik0ef5ctlficvx 192.168.23.212:2377
This node joined a swarm as a worker.


[root@worker02 ~]# docker swarm join --token SWMTKN-1-2nb3ebt3isp6ah2n1ejmvphadsfboxbfnj94pv5kbjuykzb7df-7ychlv6x2srik0ef5ctlficvx 192.168.23.212:2377
This node joined a swarm as a worker.

命令执行完成后,使用 docker info 命令在管理节点上查看 Swarm 集群的信息,具体操作如下所示。 

[root@manager ~]# docker info
Client:
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 19.03.15
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: active
  NodeID: x63te4qlluodigip492vngmqo
  Is Manager: true
  ClusterID: 33xsqp3i9cey537jlx33gl3sy
  Managers: 1
  Nodes: 3
  Default Address Pool: 10.0.0.0/8  
  SubnetSize: 24
  Data Path Port: 4789
  Orchestration:
   Task History Retention Limit: 5
  Raft:
   Snapshot Interval: 10000
   Number of Old Snapshots to Retain: 0
   Heartbeat Tick: 1
   Election Tick: 10
  Dispatcher:
   Heartbeat Period: 5 seconds
  CA Configuration:
   Expiry Duration: 3 months
   Force Rotate: 0
  Autolock Managers: false
  Root Rotation In Progress: false
  Node Address: 192.168.23.212
  Manager Addresses:
   192.168.23.212:2377
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
 runc version: v1.1.12-0-g51d5e94
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 3.10.0-1160.71.1.el7.x86_64
 Operating System: CentOS Linux 7 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.934GiB
 Name: manager
 ID: 2AG3:KBGL:25GS:CNC5:VMLZ:J6N3:VJFT:34J7:O65R:QMIT:DJ6H:56ON
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://z1qbjqql.mirror.aliyuncs.com/
 Live Restore Enabled: false

3)查看 Swarm 集群中 Node 节点的详细状态信息 

使用 docker node ls 命令可以查看 Swarm 集群中全部节点的详细状态信息。 

[root@manager ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
x63te4qlluodigip492vngmqo *   manager             Ready               Active              Leader              19.03.15
vno9novd2tv08g2uymi2p4ooc     worker01            Ready               Active                                  19.03.15
dajh52f1uhfyty1o8qojya595     worker02            Ready               Active                                  19.03.15

上面信息中,AVAILABILITY 表示 Swarm Scheduler 是否可以向集群中的某个节点指派任务,对应有如下三种状态: 

  • Active:集群中该节点可以被指派任务。
  • Pause:集群中该节点不可以被指派新的任务,但是其他已经存在的任务保持运行。
  • Drain:集群中该节点不可以被指派新的任务,Swarm Scheduler 停掉已经存在的任务,并将它们调度到可用的节点上。 

查看某一个 Node 的状态信息,只可以在管理节点上执行如下命令。

查看 manager 节点详细信息: docker node inspect manager。 

[root@manager ~]# docker node inspect manager
[
    {
        "ID": "x63te4qlluodigip492vngmqo",
        "Version": {
            "Index": 9
        },
        "CreatedAt": "2024-06-03T13:35:36.424879127Z",
        "UpdatedAt": "2024-06-03T13:35:36.549848678Z",
        "Spec": {
            "Labels": {},
            "Role": "manager",
            "Availability": "active"
        },
        "Description": {
            "Hostname": "manager",
            "Platform": {
                "Architecture": "x86_64",
                "OS": "linux"
            },
            "Resources": {
                "NanoCPUs": 2000000000,
                "MemoryBytes": 2076524544
            },
            "Engine": {
                "EngineVersion": "19.03.15",
                "Plugins": [
                    {
                        "Type": "Log",
                        "Name": "awslogs"
                    },
                    {
                        "Type": "Log",
                        "Name": "fluentd"
                    },
                    {
                        "Type": "Log",
                        "Name": "gcplogs"
                    },
                    {
                        "Type": "Log",
                        "Name": "gelf"
                    },
                    {
                        "Type": "Log",
                        "Name": "journald"
                    },
                    {
                        "Type": "Log",
                        "Name": "json-file"
                    },
                    {
                        "Type": "Log",
                        "Name": "local"
                    },
                    {
                        "Type": "Log",
                        "Name": "logentries"
                    },
                    {
                        "Type": "Log",
                        "Name": "splunk"
                    },
                    {
                        "Type": "Log",
                        "Name": "syslog"
                    },
                    {
                        "Type": "Network",
                        "Name": "bridge"
                    },
                    {
                        "Type": "Network",
                        "Name": "host"
                    },
                    {
                        "Type": "Network",
                        "Name": "ipvlan"
                    },
                    {
                        "Type": "Network",
                        "Name": "macvlan"
                    },
                    {
                        "Type": "Network",
                        "Name": "null"
                    },
                    {
                        "Type": "Network",
                        "Name": "overlay"
                    },
                    {
                        "Type": "Volume",
                        "Name": "local"
                    }
                ]
            },
            "TLSInfo": {
                "TrustRoot": "-----BEGIN CERTIFICATE-----\nMIIBajCCARCgAwIBAgIUQJ9GRxHIPf6PELRhHq/+XETrNQMwCgYIKoZIzj0EAwIw\nEzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMjQwNjAzMTMzMTAwWhcNNDQwNTI5MTMz\nMTAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABOrMvtu85UNSaQW97eBDVc6vmx377MAudq588S0iAwjQgfixp7jFlAg2kUm0\nGUAZpq9lD6KwgQr/idIVG9fS2KyjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB\nAf8EBTADAQH/MB0GA1UdDgQWBBSVOJnJ/wp5fj/Lz0kFMpWNkre7djAKBggqhkjO\nPQQDAgNIADBFAiEAmJVyYYkGN3FS+XDthQM7bv3knK4g0ryh5ualDXObjl8CIDvz\nQpOPUN5exYwgpeBNySboByduMn6nKBHQ3C2FsGRV\n-----END CERTIFICATE-----\n",
                "CertIssuerSubject": "MBMxETAPBgNVBAMTCHN3YXJtLWNh",
                "CertIssuerPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6sy+27zlQ1JpBb3t4ENVzq+bHfvswC52rnzxLSIDCNCB+LGnuMWUCDaRSbQZQBmmr2UPorCBCv+J0hUb19LYrA=="
            }
        },
        "Status": {
            "State": "ready",
            "Addr": "192.168.23.212"
        },
        "ManagerStatus": {
            "Leader": true,
            "Reachability": "reachable",
            "Addr": "192.168.23.212:2377"
        }
    }
]

查看 worker01 节点详细信息 

[root@manager ~]# docker node inspect worker01

查看 worker02 节点详细信息 

[root@manager ~]# docker node inspect worker02

至此,Docker Swarm 集群部署完成。 


三、案例二 Docker Swarm 管理 

3.1、案例概述 

在企业中,相对于 Docker Swarm 集群的安装部署,更重要的是 Docker Swarm 集群的管理。公司要求云计算工程师可对 Docker Swarm 进行日常管理。包括不限于节点管理、 服务管理、网络管理、数据卷管理等等,以便对应公司可能提出的各种管理需求。 

3.2、案例前置知识点 

1)Docker Swarm 中的节点 

运行 Docker 主机时可以自动初始化一个 Swarm 集群,或者加入一个已存在的 Swarm 集群,如此运行的 Docker 主机将成为 Swarm 集群中的节点(Node)。 

Swarm 集群中的节点分为管理节点和工作节点。 

  • 管理节点用于 Swarm 集群的管理,负责执行编排和集群管理工作,保持并维护 Swarm 处于期望的状态。Swarm 集群中如果有多个管理节点,就会自动协商并选举出一个 leader 执行编排任务; 
  • 工作节点是任务执行节点,管理节点将服务(Service)下发至工作节点执行。管理节点默认也作为工作节点。

管理节点与工作节点通过提权和降权命令相互转换角色,大部分 Docker Swarm 命令只能在管理节点执行,但工作节点退出集群的命令则是在工作节点上执行。 

2)服务和任务 

任务(Task)是 Swarm 集群中最小的调度单位,对应一个单一的容器。 

服务(Service)是指一组任务的集合,服务定义了任务的属性。服务包含两种工作模 式:

  • 副本服务:按照一定规则在各个工作节点上运行指定个数的任务;
  • 全局服务:每个工作节点上运行一个任务。 

服务的工作模式可以在执行 docker service create 命令创建服务时,通过 -mode 参数指定。 

在 Swarm 集群上部署服务,必须在管理节点上进行操作。下图是 Service(服务)、 Task(任务)、Container(容器)三者之间的关系。 

 服务、任务与容器之间的关系

3.3、案例环境 

1)本案例实验环境 

主机操作系统主机名 / IP 地址主要软件
服务器CentOS 7.9manager / 192.168.23.212Docker-ce-19.03.15
服务器CentOS 7.9worker01 / 192.168.23.213Docker-ce-19.03.15
服务器CentOS 7.9worker02 / 192.168.23.214Docker-ce-19.03.15

 案例实验环境

2)案例需求 

实现 Docker Swarm 日常操作管理,包括:节点管理、服务管理、网络管理、数据卷管理。 

3)案例实现思路 

  • 日常管理 Docker Swarm 节点;
  • 创建实现与管理 Docker Swarm 服务; 

四、案例二实施 

4.1、Docker Swarm 节点管理 

按照对节点的不同操作,通过命令的方式做详细说明。 

1)节点状态变更管理 

Swarm 支持设置一组管理节点,通过支持多管理节点实现 HA。这些管理节点之间的状态的一致性是非常重要的。在上一章中提到,节点的 AVAILABILITY 有三种状态:Active、 Pause、Drain。对某个节点进行变更,可以将其 AVAILABILITY 值通过 Docker CLI 修改为对应的状态。下面是常见的变更操作: 

  • 设置管理节点只具有管理功能;
  • 对服务进行停机维护,可以修改 AVAILABILITY 为 Drain 状态;
  • 暂停一个节点,使该节点就不再接收新的 Task;
  • 恢复一个不可用或者暂停的节点。 

例如,将管理节点的 AVAILABILITY 值修改为 Drain 状态,使其只具备管理功能,具体操作如下所示。 

[root@manager ~]# docker node update --availability drain manager
manager
[root@manager ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
x63te4qlluodigip492vngmqo *   manager             Ready               Drain               Leader              19.03.15
vno9novd2tv08g2uymi2p4ooc     worker01            Ready               Active                                  19.03.15
dajh52f1uhfyty1o8qojya595     worker02            Ready               Active                                  19.03.15

 如此,管理节点就不能被指派任务,也就是不能部署实际的 Docker 容器来运行服务, 而只是担任管理者的角色。

2)添加标签元数据 

在生产环境中,可能每个节点的主机配置情况不同,比如:有的适合运行 CPU 密集型应用、有的适合运行 IO 密集型应用。Swarm 支持给每个节点添加标签元数据,根据节点的标签,选择性地调度某个服务部署到期望的一组节点上。 

添加标签的命令格式如下所示。 

docker node update --label-add 值 键 

示例 1:worker01 主机在名称为 GM-IDC-01 的数据中心,为 worker01 节点添加标签 为“GM-IDC-01”,具体操作如下所示。 

[root@manager ~]# docker node update --label-add GM-IDC-01 worker01
worker01
[root@manager ~]# docker node inspect worker01 | head -12  //查看标签是否添加成功
[
    {
        "ID": "vno9novd2tv08g2uymi2p4ooc",
        "Version": {
            "Index": 22
        },
        "CreatedAt": "2024-06-03T13:40:08.966690961Z",
        "UpdatedAt": "2024-06-04T01:17:31.495806517Z",
        "Spec": {
            "Labels": {
                "GM-IDC-01": ""
            },

3)节点提权 / 降权 

前面提到,在 Swarm 集群中节点分为管理节点与工作节点两种。在实际的生产环境中根据实际需求可更改节点的角色,常见操作有: 

  • 工作节点变为管理节点:提权操作;
  • 管理节点变为工作节点:降权操作。

提权 / 降权 命令格式如下

提权:docker node promote (节点名)

降权:docker node demote (节点名)

示例 2:将 worker01 和 worker02 都升级为管理节点,具体操作如下所示。 

[root@manager ~]# docker node promote worker01 worker02
Node worker01 promoted to a manager in the swarm.
Node worker02 promoted to a manager in the swarm.
[root@manager ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
x63te4qlluodigip492vngmqo *   manager             Ready               Drain               Leader              19.03.15
vno9novd2tv08g2uymi2p4ooc     worker01            Ready               Active              Reachable           19.03.15
dajh52f1uhfyty1o8qojya595     worker02            Ready               Active              Reachable           19.03.15

示例 3:对上面已提权的 worker01 和 worker02 执行降权操作,需要执行如下命令。 

[root@manager ~]# docker node demote worker01 worker02
Manager worker01 demoted in the swarm.
Manager worker02 demoted in the swarm.
[root@manager ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
x63te4qlluodigip492vngmqo *   manager             Ready               Drain               Leader              19.03.15
vno9novd2tv08g2uymi2p4ooc     worker01            Ready               Active                                  19.03.15
dajh52f1uhfyty1o8qojya595     worker02            Ready               Active                                  19.03.15

4)退出 Swarm 集群 

如果管理节点想要退出 Swarm 集群, 在管理节点上执行 docker swarm leave 命令, 具体操作如下所示。 

[root@manager ~]# docker swarm leave

如果集群中还存在其它的工作节点,同时希望管理节点退出集群,则需要加上一个强制选项,具体操作如下所示。 

[root@manager ~]# docker swarm leave --force

同理,如果工作节点想要退出 Swarm 集群,在工作节点上执行 docker swarm leave 命令,具体操作如下所示。 

[root@worker01 ~]# docker swarm leave

即使管理节点已经退出 Swarm 集群,执行上述命令也可以使得工作节点退出集群。之后,根据需要,加入到其它新建的 Swarm 集群中。需要注意的是,管理节点退出集群后无法重新加入之前退出的集群;工作节点退出集群后通过 docker swarm join 命令并指定对应的 token 值重新加入集群。 

4.2、Docker Swarm 服务管理 

在 Swarm 模式下使用 Docker,可以实现部署运行服务、服务扩容缩容、删除服务、滚动更新等功能,下面依次进行说明。 

1)创建服务 

使用 docker service create 命令可以创建 Docker 服务。 

示例 4:从 Docker 镜像 nginx 创建一个名称为 web 的服务,指定服务副本数为 2。具 体操作如下所示。 

[root@manager ~]# docker service create --replicas 2 --name web nginx
z8w5xriykqoun7v68twy19lg4
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged 

执行如下命令可查看当前已经部署启动的全部应用服务。 

[root@manager ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
z8w5xriykqou        web                 replicated          2/2                 nginx:latest

执行如下命令可以查询指定服务的详细信息。 

[root@manager ~]# docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
3rocp0bf9th0        web.1               nginx:latest        worker01            Running             Running about a minute ago                       
m2i9blojv3n9        web.2               nginx:latest        worker02            Running             Running about a minute ago 

上面信息显示,在 worker01 和 worker02 节点上部署了 Web 应用服务,也包含了它们对应的当前状态信息。此时,可以通过执行 docker ps 命令,在工作节点上查看当前启动的 Docker 容器。 

[root@worker01 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
86f6eeb7c1e3        nginx:latest        "/docker-entrypoint.…"   2 minutes ago       Up 2 minutes        80/tcp              web.1.3rocp0bf9th0ad5wsq3eiqjty


[root@worker02 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
dcb03bddddd7        nginx:latest        "/docker-entrypoint.…"   3 minutes ago       Up 3 minutes        80/tcp              web.2.m2i9blojv3n9n31k9onull2ov

2)显示服务详细信息 

常见服务详细信息有以 JSON 格式显示、易于阅读显示两种显示方式。 

  • 以 JSON 格式显示 

可以通过下面的命令,以 JSON 格式显示方法 Web 服务的详细信息。 

[root@manager ~]# docker service inspect web
[
    {
        "ID": "z8w5xriykqoun7v68twy19lg4",
        "Version": {
            "Index": 48
        },
        "CreatedAt": "2024-06-04T03:18:44.534203044Z",
        "UpdatedAt": "2024-06-04T03:18:44.534203044Z",
        "Spec": {
            "Name": "web",
            "Labels": {},
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "nginx:latest@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31",
                    "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": 2
                }
            },
            "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"
            }
        },
        "Endpoint": {
            "Spec": {}
        }
    }
]
  • 易于阅读显示 

可以通过执行下面命令,以易于阅读方式显示 Web 服务的详细信息。 

[root@manager ~]# docker service inspect --pretty web

ID:		z8w5xriykqoun7v68twy19lg4
Name:		web
Service Mode:	Replicated
 Replicas:	2
Placement:
UpdateConfig:
 Parallelism:	1
 On failure:	pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Update order:      stop-first
RollbackConfig:
 Parallelism:	1
 On failure:	pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Rollback order:    stop-first
ContainerSpec:
 Image:		nginx:latest@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
 Init:		false
Resources:
Endpoint Mode:	vip

3)服务的扩容与缩容 

当使用服务并涉及到高可用时,可能会有服务的扩容和缩容等操作。服务扩容缩容的命令格式如下所示,通过 Task 总数确定服务是扩容还是缩容。 

 命令格式如下:

docker service scale 服务 ID=服务 Task 总数

示例 5:将前面已经部署的 2 个副本的 Web 服务,扩容到 3 个副本,具体操作如下所示。 

[root@manager ~]# docker service scale web=3
web scaled to 3
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged

通过 docker service ps web 命令查看服务扩容结果,具体操作如下所示。 

[root@manager ~]# docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
3rocp0bf9th0        web.1               nginx:latest        worker01            Running             Running 7 minutes ago                        
m2i9blojv3n9        web.2               nginx:latest        worker02            Running             Running 7 minutes ago                        
g11127uhw4g3        web.3               nginx:latest        worker01            Running             Running 49 seconds ago  

 根据上述命令结果得知,worker01 节点上有两个 Web 应用服务的副本。进行服务缩容操作时只需要设置副本数小于当前应用服务拥有的副本数即可,大于指定缩容副本数的副本会被删除。具体操作如下所示。

[root@manager ~]# docker service scale web=1
web scaled to 1
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 
[root@manager ~]# docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
3rocp0bf9th0        web.1               nginx:latest        worker01            Running             Running 9 minutes ago 

4)删除服务 

删除服务的命令格式如下所示:

docker service rm 服务名称 

示例 6:删除集群中所有 Web 应用服务。 

[root@manager ~]# docker service rm web
web
[root@manager ~]# docker service ps web
no such service: web

5)滚动更新 

在创建服务时通过 --update-delay 选项可以设置容器的更新间隔时间,每次成功部署一个服务,延迟 10 秒钟,然后再更新下一个服务。如果某个服务更新失败,Swarm 的调度器就会暂停本次服务的部署更新。具体操作如下所示。

[root@manager ~]# docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6
bsbcdza5170oeh817lby8jhb6
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged 
[root@manager ~]# docker service ps redis
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
bkhc6525r7jz        redis.1             redis:3.0.6         worker02            Running             Running 15 seconds ago                       
vxkefklid9rm        redis.2             redis:3.0.6         worker02            Running             Running 15 seconds ago                       
umtulwoc20la        redis.3             redis:3.0.6         worker01            Running             Running 21 seconds ago 

更新已经部署服务所在容器中使用的镜像版本。示例 6:将 Redis 服务对应的 Image 版本由 3.0.6 更新为 3.0.7,但是服务更新之前的 3.0.6 镜像版本的容器不会删除,只会停止。 具体操作如下所示。 

[root@manager ~]# docker service update --image redis:3.0.7 redis
redis
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged 
[root@manager ~]# docker service ps redis
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
3e32rj3fc7me        redis.1             redis:3.0.7         worker01            Running             Running 47 seconds ago                        
bkhc6525r7jz         \_ redis.1         redis:3.0.6         worker02            Shutdown            Shutdown 58 seconds ago                       
4s2h2fk0wqeh        redis.2             redis:3.0.7         worker02            Running             Running 13 seconds ago                        
vxkefklid9rm         \_ redis.2         redis:3.0.6         worker02            Shutdown            Shutdown 23 seconds ago                       
thshq4ly9ec7        redis.3             redis:3.0.7         worker01            Running             Running 35 seconds ago                        
umtulwoc20la         \_ redis.3         redis:3.0.6         worker01            Shutdown            Shutdown 36 seconds ago            

6)添加自定义 Overlay 网络 

在 Swarm 集群中使用 Overlay 网络可以连接到一个或多个服务。添加 Overlay 网络需要在管理节点上先创建一个 Overlay 网络,具体操作如下所示。 

[root@manager ~]# docker network create --driver overlay my-network
bvckhqt6tbqdyxl3oa8gntq8y

创建名为 my-network 的 Overlay 网络 my-network 之后,在创建服务时,通过 --network 选项指定使用的网络为已存在的 Overlay 网络即可,具体操作如下所示。 

[root@manager ~]# docker service create --replicas 3 --network my-network --name myweb nginx
43ezjtqcqpm7vlm6p7gn773io
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged 

如果 Swarm 集群中其他节点上的 Docker 容器也使用 my-network 网络,那么处于该 Overlay 网络中的所有容器之间都可以进行通信。 

7)数据卷创建与应用 

使用 docker volume create 命令可以创建数据卷,具体操作如下所示。 

[root@manager ~]# docker volume create product-kgc  //创建数据卷
product-kgc  
[root@manager ~]# docker volume ls  //查看创建的数据卷
DRIVER              VOLUME NAME
local               product-kgc

应用上述创建的数据卷,具体操作如下所示。 

[root@manager ~]# docker service create --mount type=volume,src=product-kgc,dst=/usr/share/nginx/html --replicas 1 --name kgc-web01 nginx
wrpuxv6p83o7lczwmhxug73jg
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 
[root@manager ~]# docker service ps kgc-web01
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
satd3xzl08tn        kgc-web01.1         nginx:latest        worker01            Running             Running 17 seconds ago  
[root@manager ~]# docker volume inspect product-kgc  //查看数据卷的详细信息
[
    {
        "CreatedAt": "2024-06-04T14:35:04+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/product-kgc/_data",
        "Name": "product-kgc",
        "Options": {},
        "Scope": "local"
    }
]

查看数据是否进行同步的命令如下。 

[root@worker01 ~]# cd /var/lib/docker/volumes/product-kgc/_data/
[root@worker01 _data]# mkdir test01 test02
[root@worker01 _data]# docker ps  //列出所有在运行的容器信息
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
47c783f985eb        nginx:latest        "/docker-entrypoint.…"   3 minutes ago       Up 3 minutes        80/tcp              kgc-web01.1.satd3xzl08tnjqo631av648km
[root@worker01 _data]# docker exec -it 47c783f985eb /bin/bash  //进入 Docker 容器
root@47c783f985eb:/# ls /usr/share/nginx/html/
50x.html  index.html  test01  test02

从上面的验证结果得出,在本地数据卷目录下创建几个文件,进入到容器后,找到对应的目录,数据依然存在。 

数据卷的挂载类型除 volume 之外,还经常使用 bind 类型。具体操作如下所示。 

[root@manager ~]# mkdir -p /var/vhost/www/aa
[root@worker01 ~]# mkdir -p /var/vhost/www/aa
[root@worker02 ~]# mkdir -p /var/vhost/www/aa

创建 2 个 kgc-web02 服务。 

[root@manager ~]# docker service create --replicas 2 --mount type=bind,src=/var/vhost/www/aa,dst=/usr/share/nginx/html/ --name kgc-web02 nginx
33mhr4g0k23zor88esyns5y9i
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged 

下面命令用于验证数据是否同步。 

[root@worker01 ~]# touch /var/vhost/www/aa/11
[root@worker01 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                      PORTS               NAMES
0291fd47da2c        nginx:latest        "/docker-entrypoint.…"   About a minute ago   Up 59 seconds               80/tcp              kgc-web02.2.pq600lfuvm6inbtfqd2ie0e0a
[root@worker01 ~]# docker exec -it 0291fd47da2c /bin/bash
root@0291fd47da2c:/# ls /usr/share/nginx/html/
11
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐