二、在 Swarm 模式下使用 Docker
Docker 引擎是一个用于运行 Docker 容器的容器化平台。多个 Docker 容器在同一个底层操作系统内核上独立运行,每个容器都有自己的网络和文件系统。每个 Docker 容器都是应用所需的软件和依赖项的封装,不会产生打包整个操作系统的开销,这可能需要几个 GB。Docker 应用从 Docker 容器中的 Docker 映像运行,每个 Docker 映像特定于特定的应用或软件。Docker 映像是从 Docker 文件构建的,Docker 文件定义了用于下载和安装软件、设置环境变量和运行命令的指令集。
问题
虽然 Docker Engine 1.12 之前的版本(没有本机 Swarm 模式) 是为在轻量级容器中运行应用而设计的,但它缺少一些功能,以下是主要功能。
- 无分布式计算 - 不提供分布式计算,因为 Docker 引擎安装并运行在单个节点或操作系统实例上。
- No fault tolerance - As shown in the diagram in Figure 2-1 , if the single node on which a Docker Engine is running fails, the Docker applications running on the Docker Engine fail as well.

图 2-1。
Single node Docker cluster
解决方案
从 Docker 引擎版本 1.12 开始,Docker 容器编排以群组模式内置于 Docker 引擎中,并且是 Docker 引擎的原生功能。使用群模式,分布在多个机器(OS 实例) 上的节点群(或集群) 可以以主/工/模式运行。默认情况下,Docker 引擎中不启用 Docker 群组模式,必须使用 docker 命令进行初始化。接下来,作为对 Docker Swarm 模式的介绍,我们介绍一些术语。
DockerSwarm 模式
Docker Swarm 是一个由覆盖网络连接的 Docker 主机集群,用于服务发现。Docker 群包括一个或多个管理节点和一个或多个工作节点,如图 2-2 所示。在 Swarm 模式中,Docker 服务是 Docker 容器化的单元。从管理节点创建的服务的 Docker 容器在集群中部署或调度,并且 Swarm 包括用于扩展服务的内置负载均衡。服务的预期状态在管理器上声明,然后管理器调度任务在节点上运行。但是,worker 节点本身仍然提取映像并启动容器。

图 2-2。
Docker Swarm mode cluster
节点
Docker 主机(Docker 引擎) 的一个实例称为节点。提供了两种类型的节点角色:管理者节点和工作者节点。
服务
服务是分布在整个群体中的一组任务(也称为副本或复制任务) 的抽象。例如,一个服务可以运行 Nginx 服务器的三个副本。默认调度在第 7 章中讨论,它使用 分散 调度策略,根据计算的节点等级将任务分散到集群的节点上。服务由一个或多个彼此独立运行的任务组成,这意味着停止一个任务或启动一个新任务不会影响其他任务的运行。运行在三个节点上的 Nginx 服务可以包含三个复制任务。每个任务为服务运行一个 Docker 容器。一个节点可以为一项服务运行多个任务。任务是调度的原子单位的抽象,是调度程序运行 Docker 容器的 槽 。
服务的期望状态
服务的 期望状态 指的是创建服务时在服务定义中定义的服务状态。例如,服务定义可以将服务定义为由 Nginx 服务器的三个副本组成。
管理节点和 Raft 共识
当第一次创建群时,当前节点成为第一个管理节点。默认情况下,所有管理器节点也是工作节点。管理节点执行集群协调并管理群,包括服务任务的初始调度和服务的期望状态和实际状态之间的后续协调(如果有的话)。例如,对于由 Nginx 服务器的三个副本组成的服务定义,管理节点将创建三个任务,并在群中的群工作节点上调度这些任务。随后,如果运行任务的节点失败,群管理器将在仍在群中的工作节点上启动新的替换任务。当服务被创建时,群管理器接受服务定义,并在一个或多个工作者节点上将服务调度为服务任务。群组管理器节点还通过添加/移除服务任务来管理服务的扩展。群组管理器为每个服务分配一个唯一的 DNS 名称,并通过服务复制任务启动 Docker 容器。管理器节点监视集群状态。默认情况下,Swarm manager 也是一个 worker 节点,这将在下一节讨论。
提到 管理节点 实际上是群管理器的简化,因为群可以由一个或多个管理节点组成。每个管理节点保存完整的集群状态数据,包括哪个服务副本任务在哪个节点上运行以及节点角色,并参与 Raft 一致性的群管理。Raft 共识仅仅是一种算法,用于以分布式方式在一个组内创建决策/协议(共识)。Swarm 使用它来做出决定,如领导者选举、集群成员资格、服务更改等。在群模式中,Raft 共识是管理节点之间对于全局集群状态参数的协定,例如关于存储在数据库中的数据值的状态。群体管理者使用 Raft 共享数据。Raft 一致性协议是一种在集群中所有可达管理节点之间实现分布式一致性的协议。Raft 一致性算法有几种实现方式,其在 Swarm 模式下的实现方式具有分布式系统中常见的特性,如下所示:
- 容错值的一致性
- 集群成员管理
- 使用互斥的领袖选举
只有一个管理器节点(称为领导者) 执行所有的集群协调和管理。只有领导节点执行服务任务的服务调度、缩放和重启。其他管理器节点用于群管理器的容错,这意味着如果领导者节点失败,其他管理器节点中的一个将被选为新的领导者并接管集群管理。领导者的选举是由来自大多数管理节点的共识来执行的。
工作节点
工作节点实际上运行服务副本任务和相关的 Docker 容器。作为管理者节点和工作者节点的节点角色之间的区别不是在服务部署时处理的,而是在运行时处理的,因为节点角色可以被提升/降级。升级/降级节点将在后面的章节中讨论。工作者节点不影响管理者 Raft 共识。工作节点只是增加了群集运行服务副本任务的能力。工作者节点本身对 raft 中保存的投票和状态没有贡献,但是它们是工作者节点的事实保存在 raft 中。由于运行一个服务任务需要资源(CPU 和内存),而一个节点有一定的固定可分配资源,所以群的容量受到群中工作节点数量的限制。
法定人数
法定人数是指大多数群管理器节点或管理器之间的一致。如果一个群体失去了法定人数,它就不能执行任何管理或编排功能。已经计划的服务任务不受影响,并继续运行。没有安排新的服务任务,也没有执行其他需要一致同意的管理决策,例如添加或删除节点。所有群管理器都被认为是决定容错的多数共识。对于领导者选举,只有可到达的管理器节点被包括在 Raft 共识中。任何群体更新,如节点的添加或删除或新领导者的选举,都需要法定人数。筏共识和法定人数是一样的。为了实现高可用性,建议在生产中使用三到五个群组管理器。一般情况下,建议使用奇数数量的群管理器。容错性指的是群管理器节点的故障容限,或者在不使群不可用的情况下可能发生故障的群管理器的数量。数学上, 多数 是指超过一半,但是对于群模式 Raft 共识算法,Raft 容许(N-1)/2 次失败,并且 Raft 共识的多数由(N/2)+1 确定。n 指的是群的大小或群中管理节点的数量。
Swarm Size = Majority + Fault Tolerance
作为一个例子,群大小为 1 和 2 的每一个都有一个容错值 0,因为如果任何一个群管理器失败,就不能为群大小达成 Raft 共识。更多的管理器节点提高了容错能力。对于奇数 N,群大小 N 和 N+1 的容错是相同的。
举个例子,一个有三个管理者的蜂群,容错度为 1,如图 2-3 所示。容错和 Raft 一致性不适用于工作节点,因为群容量仅基于工作节点。即使三个工作者节点中的两个发生故障,一个工作者节点,即使管理器节点是仅管理器节点,也将保持群可用,尽管群容量减少,并且可以将一些运行任务转换到非运行状态。

图 2-3。
Fault tolerance for a Swarm
本节涵盖以下主题:
- 设置环境
- 初始化 Docker 群组模式
- 将节点加入群集群
- 测试群集群集
- 将工作节点提升为管理器
- 将管理员节点降级为工作节点
- 使工作节点离开集群
- 使工作节点重新加入集群
- 使管理节点离开集群
- 重新初始化蜂群
- 修改节点可用性
- 删除节点
设置环境
本章向您展示了如何创建一个由一个管理节点和两个工作节点组成的三节点集群。使用 CoreOS Stable AMI 创建三个 Amazon EC2 实例,如图 2-4 中的 EC2 控制台所示。为 EC2 实例配置安全组时,启用 EC2 实例之间的所有流量。获取为群组管理器启动的 EC2 实例的 IP 地址。

图 2-4。
EC2 instances
初始化 Docker 群组模式
Docker Swarm 模式默认不启用,需要启用。使用公共 IP 地址为 Swarm manager 启动了到 EC2 实例的 SSH 登录。
ssh -i "coreos.pem" core@34.204.168.217
Docker Swarm 模式从 Docker 版本 1.12 开始提供。使用 docker --version 命令验证 Docker 版本至少为 1.12。
[root@localhost ∼]# ssh -i "coreos.pem" core@34.204.168.217 Container Linux by CoreOS stable (1409.7.0) core@ip-172-30-5-70 ∼ $ docker --version Docker version 1.12.6, build a82d35e
要初始化 Swarm,使用 docker swarm init options 命令。该命令支持的一些选项在表 2-1 中列出。
表 2-1。
Command Swarm init Options
| [计]选项 | 描述 | 缺省值 | | --- | --- | --- | | `--advertise-addr` | 格式为`[:port]`的广告地址。所通告的地址是其他节点可以访问群的 IP 地址。如果没有指定 IP 地址,Docker 确定系统是否有单个 IP 地址,如果有,则使用 IP 地址和端口 2337。如果系统有多个 IP 地址,必须为管理器间通信和覆盖网络指定`--advertise-addr`。 | | | `--availability` | 节点的可用性。应该是`active` / `pause` / `drain`中的一个。 | `active` | | `--force-new-cluster` | 是否从当前状态强制创建新的群集。我们将在本章中讨论为什么可能需要强制创建和使用该选项。 | `false` | | `--listen-addr` | 格式为`[:port]`的监听地址。 | `0.0.0.0:2377` |
除了没有提供默认值的 --advertise-addr ,所有选项都使用默认值。使用私有地址作为广告地址,可以从 EC2 控制台获得,如图 2-5 所示。如果 AWS 上的 EC2 实例位于不同的区域,则应该使用外部公共 IP 地址来访问 manager 节点,该地址也可以从 EC2 控制台获得。

图 2-5。
Private IP
运行以下命令来初始化 Docker Swarm 模式。
docker swarm init --advertise-addr 172.30.5.70
如下面清单中的输出所示,Swarm 被初始化,当前节点是一个管理节点。添加工作节点的命令也包含在输出中。还输出获得添加管理器节点的命令的命令。复制 docker swarm join 命令,将一个工作者节点添加到群中。
core@ip-172-30-5-70 ∼ $ docker swarm init --advertise-addr 172.30.5.70
Swarm initialized: current node (bgzqx2cfsf05qdradxytmdcp3) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-3o3zi1rxgkzy5gq5itr580yp9pbagxnkelinzh42ovrb7znt6f-dmgeg3veppor942vsavma3s47 \
172.30.5.70:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
运行 docker info 命令来获取关于 Docker 引擎的系统范围的信息。该命令输出正在运行、暂停或停止的 Docker 容器的总数。列出了部分输出。
core@ip-172-30-5-70 ∼ $ docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 1.12.6 Storage Driver: overlay Backing Filesystem: extfs Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: null host bridge overlay Swarm: active NodeID: bgzqx2cfsf05qdradxytmdcp3 Is Manager: true ClusterID: 056zm05kk6em6u7vlki8pbhc9 Managers: 1 Nodes: 1 CPUs: 1 Total Memory: 994.6 MiB Name: ip-172-30-5-70.ec2.internal Docker Root Dir: /var/lib/docker
存储驱动程序是覆盖的,后备文件系统是 extfs 。测井驱动程序是 json-file ,这在关于测井的第 11 章节中有所涉及。这个蜂群被显示为 active 。还列出了关于节点的信息,例如 NodeID、节点是否是管理器、群中管理器的数量以及群中节点的数量。
还列出了节点的资源容量(CPU 和内存)。第 7 章讨论了更多关于资源使用的内容。节点名是初始化群组的 EC2 实例的私有 DNS。
使用以下命令列出群中的节点:
docker node ls
列出了单个节点,包括节点 ID,这是节点的唯一参数。如果一个节点没有离开集群并重新加入,主机名也是唯一的。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS bgzqx2cfsf05qdradxytmdcp3 * ip-172-30-5-70.ec2.internal Ready Active Leader
节点 ID 后面的 * 表示这是当前节点。群中的节点也有一个 STATUS 、 AVAILABILITY 和 MANAGER STATUS 列。 STATUS 可以是表 2-2 中列出的值之一。
表 2-2。
Node Status
| 状态 | 描述 | | --- | --- | | `Ready` | 随时可以使用 | | `Down` | 不准备使用 | | `Unknown` | 不知道 |
AVAILABILITY 可以是表 2-3 中列出的值之一。
表 2-3。
AVAILABILITY Column
| 有效 | 描述 | | --- | --- | | `Active` | 调度器可以向节点分配任务。 | | `Pause` | Scheduler 不会向节点分配新任务,但现有任务会继续运行。 | | `Drain` | Scheduler 不会向节点分配新任务,现有任务会关闭。替换任务在其他节点上启动。 |
MANAGER STATUS 可以是表 2-4 中列出的值之一。如果 MANAGER STATUS 列没有值,则表示一个 worker 节点。
表 2-4。
Manager Status
| 经理状态 | 描述 | | --- | --- | | `Reachable` | 该节点加入 Raft 共识仲裁,并且如果领导者变得不可用,该节点有资格成为领导者节点。 | | `Unreachable` | 该节点是一个可到达的管理器节点,但已经变得不可到达,并且无法与群中的其他管理器节点通信。通过执行以下操作之一,可以使无法访问的管理器节点变得可以访问,但不能保证可以恢复:-重新启动计算机-重新启动守护程序如果前面的操作都无法恢复无法访问的管理器节点,则应该执行以下操作。降级并删除故障节点。`docker node demote and docker node rm `用`docker swarm join`添加另一个管理节点。或者用`docker node promote`将一个工作者节点提升为管理者节点 | | `Leader` | 执行所有群管理和协调的主管理器节点。 |
将节点加入群
额外的节点,管理者或工作者,可以根据需要被添加或加入到群中。默认情况下,管理器节点也是工作者节点,但反之亦然。添加管理节点的原因与添加工作节点的原因不同。添加管理节点以使群更加容错,添加工作者节点以增加群的容量。添加管理器和工作器节点的命令也不同。当初始化群时,输出添加工作者节点的命令。使用以下命令也可以找到添加工作节点的命令。
docker swarm join-token worker
使用以下命令可以找到添加管理器节点的命令。
docker swarm join-token manager
添加工作者节点的原因是在一些节点上调度的服务任务没有运行,并且处于 Allocated 状态。添加管理器节点的原因是另一个管理器节点变得不可访问。
要加入的节点(管理器或工作器) 必须至少安装 Docker 引擎版本 1.12。接下来,添加两个工作节点。获取为工作节点启动的 EC2 实例的公共 IP 地址。工作者实例的 SSH 登录。
ssh -i "coreos.pem" core@34.204.199.
运行具有以下语法的 docker swarm join 命令,将该节点作为工作者节点加入群。
docker swarm join [OPTIONS] HOST:PORT
表 2-5 中列出了 docker swarm join 命令支持的选项。
表 2-5。
Options for docker swarm join Command
| [计]选项 | 描述 | 缺省值 | | --- | --- | --- | | `--advertise-addr` | 格式为`[:port]`的广告地址。 | | | `--availability` | 节点的可用性。`active` / `pause` / `drain`之一。 | `active` | | `--listen-addr` | 格式为`[:port]`的监听地址。 | `0.0.0.0:2377` | | `--token` | 进入蜂群的令牌。 | |
在 Swarm 模式初始化期间运行 docker swarm join 命令输出,将 worker 实例加入 Swarm。正如输出消息所示, 节点作为一个工人加入了群体。
[root@localhost ∼]# ssh -i "coreos.pem" core@34.204.199.45 Container Linux by CoreOS stable (1409.7.0) core@ip-172-30-5-31 ∼ $ docker swarm join \ > --token SWMTKN-1-3o3zi1rxgkzy5gq5itr580yp9pbagxnkelinzh42ovrb7znt6f-dmgeg3veppor942vsavma3s47 \ > 172.30.5.70:2377 This node joined a swarm as a worker.
类似地,SSH 登录到另一个 worker 实例。
ssh -i "coreos.pem" core@34.231.70.10
运行相同的 docker swarm join 命令,第二个节点作为工作者节点加入群。
[root@localhost ∼]# ssh -i "coreos.pem" core@34.231.70.10 Container Linux by CoreOS stable (1409.7.0) core@ip-172-30-5-108 ∼ $ docker swarm join \ > --token SWMTKN-1-3o3zi1rxgkzy5gq5itr580yp9pbagxnkelinzh42ovrb7znt6f-dmgeg3veppor942vsavma3s47 \ > 172.30.5.70:2377 This node joined a swarm as a worker.
当运行 docker swarm join 命令将一个工作者节点加入群时,发生以下事件序列。
- 启用节点上 Docker 引擎的群组模式。
- 对 TLS 证书的请求被发送给管理者。
- 该节点以机器主机名命名。
- 当前节点在管理器监听地址加入群。基于该令牌,该节点作为工作者节点或管理者节点加入。
- 将当前节点设置为
Active可用性。 - 入口覆盖网络扩展到当前节点。
当节点使用管理器令牌加入群时,该节点作为管理器节点加入。新的管理器节点应该是 Reachable ,并且只有第一个管理器节点是领导者。仅当初始引导者节点失败或被降级时,才会发生不同管理器节点的引导者选举。
工作者节点在另一方面不同于管理者节点。工作节点不能用于查看或修改群集状态。只有管理节点可用于查看集群状态,如群中的节点。只有管理器节点可用于修改集群状态,如删除节点。如果在工作节点上运行 docker node ls 命令,将生成以下错误消息。
core@ip-172-30-5-31 ∼ $ docker node ls Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
测试蜂群
接下来,您向 Swarm 部署一个简单的 Hello World 服务来测试集群。使用下面的命令从 manager 节点列出 Swarm 中的节点。
docker node ls
应该会列出这三个节点。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 9n5qmj4pp91f0n3s0n2jwjdv8 ip-172-30-5-108.ec2.internal Ready Active bgzqx2cfsf05qdradxytmdcp3 * ip-172-30-5-70.ec2.internal Ready Active Leader bqq4bryuobylu0glm4p19tko4 ip-172-30-5-31.ec2.internal Ready Active
如何判断一个节点是管理节点还是工作节点?从 经理状态 列。如果管理者状态为空,则该节点为工作者节点,如果管理者状态具有值,则该节点为管理者节点,该值为表 2-4 中讨论的值之一。列出了两个工作节点和一个管理节点。
我们已经讨论过工作节点不能用于查看或修改集群状态。接下来,使用 docker service create 命令创建一个 Docker 服务,该命令只有在启用了 Swarm 模式时才可用。使用 Docker image alpine ,这是一个 Linux 发行版,创建两个副本并从服务容器 ping docker.com 域。
docker service create --replicas 2 --name helloworld alpine ping docker.com
如果前面的命令运行没有错误,Docker Swarm 安装得很好。该命令返回服务 ID。
core@ip-172-30-5-70 ∼ $ docker service create --replicas 2 --name helloworld alpine ping docker.com bkwskfzqa173dp55j54erg5cg
可以使用以下命令列出服务。
docker service ls
服务 helloworld 被列出,副本的数量被列为 2/2,这意味着两个副本存在并且满足两个副本的期望状态。 REPLICAS 列输出被命令为 实际/期望 。Docker 映像是 alpine ,运行服务的命令是 ping docker.com 。
core@ip-172-30-5-70 ∼ $ docker service ls ID NAME REPLICAS IMAGE COMMAND bkwskfzqa173 helloworld 2/2 alpine ping docker.com
docker service inspect 命令用于查找关于服务的更多信息。
docker service inspect helloworld
列出了关于 helloworld 服务的详细信息 - 包括容器规格、资源、重启策略、位置、模式、更新配置和更新状态。
core@ip-172-30-5-70 ∼ $ docker service inspect helloworld
[
{
"ID": "bkwskfzqa173dp55j54erg5cg",
"Version": {
"Index": 22
},
"CreatedAt": "2017-07-22T19:11:50.345823466Z",
"UpdatedAt": "2017-07-22T19:11:50.345823466Z",
"Spec": {
"Name": "helloworld",
"TaskTemplate": {
"ContainerSpec": {
"Image": "alpine",
"Args": [
"ping",
"docker.com"
]
},
"Resources": {
"Limits": {},
"Reservations": {}
},
"RestartPolicy": {
"Condition": "any",
"MaxAttempts": 0
},
"Placement": {}
},
"Mode": {
"Replicated": {
"Replicas": 2
}
},
"UpdateConfig": {
"Parallelism": 1,
"FailureAction": "pause"
},
"EndpointSpec": {
"Mode": "vip"
}
},
"Endpoint": {
"Spec": {}
},
"UpdateStatus": {
"StartedAt": "0001-01-01T00:00:00Z",
"CompletedAt": "0001-01-01T00:00:00Z"
}
}
]
可以使用以下命令语法列出副本和放置副本的节点。
docker service ps <SERVICE
<SERVICE> 占位符或者是服务名(比如 helloworld ) 或者是实际的服务 ID(比如本例中的 bkwskfzqa173 )。对于 helloworld 服务,命令变成:
docker service ps helloworld
前面的命令还列出了运行复制副本的节点。为服务启动的 Docker 容器与之前的命令一样,即 docker ps 命令。
core@ip-172-30-5-70 ∼ $ docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 2x8gqd2qbylpkug1kg0pxi1c2 helloworld.1 alpine ip-172-30-5-70.ec2.internal Running Running 34 seconds ago 6twq1v0lr2gflnb6ae19hrpx9 helloworld.2 alpine ip-172-30-5-108.ec2.internal Running Running 34 seconds ago core@ip-172-30-5-70 ∼ $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES acbdaccad6ea alpine:latest "ping docker.com" 47 seconds ago Up 46 seconds helloworld.1.2x8gqd2qbylpkug1kg0pxi1c2
docker ps 命令不是群模式命令,但是可以在工作者节点上运行,以找到在工作者节点上运行的服务容器。 docker ps 命令给出了在一个节点上运行的所有容器,即使它们不是服务容器。
core@ip-172-30-5-108 ∼ $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 74ea31054fb4 alpine:latest "ping docker.com" About a minute ago Up About a minute helloworld.2.6twq1v0lr2gflnb6ae19hrpx9
docker service ps helloworld 命令只列出了两个调度副本的节点,一个是管理节点,另一个是工作节点。另一个 worker 节点上的 docker ps 命令没有列出任何 Docker 容器。
core@ip-172-30-5-31 ∼ $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker node inspect <node> 命令用于获取节点的详细信息,例如节点角色、可用性、主机名、资源容量、插件和状态。
core@ip-172-30-5-70 ∼ $ docker node inspect ip-172-30-5-70.ec2.internal
[
{
"ID": "bgzqx2cfsf05qdradxytmdcp3",
"Version": {
"Index": 10
},
"CreatedAt": "2017-07-22T19:09:45.647701768Z",
"UpdatedAt": "2017-07-22T19:09:45.68030039Z",
"Spec": {
"Role": "manager",
"Availability": "active"
},
"Description": {
"Hostname": "ip-172-30-5-70.ec2.internal",
"Platform": {
"Architecture": "x86_64",
"OS": "linux"
},
"Resources": {
"NanoCPUs": 1000000000,
"MemoryBytes": 1042935808
},
"Engine": {
"EngineVersion": "1.12.6",
"Plugins": [
{
"Type": "Network",
"Name": "bridge"
},
{
"Type": "Network",
"Name": "host"
},
{
"Type": "Network",
"Name": "null"
},
{
"Type": "Network",
"Name": "overlay"
},
{
"Type": "Volume",
"Name": "local"
}
]
}
},
"Status": {
"State": "ready"
},
"ManagerStatus": {
"Leader": true,
"Reachability": "reachable",
"Addr": "172.30.5.70:2377"
}
}
]
可以使用 docker service rm <service> 命令删除服务。随后, docker service inspect <service> 命令不应该列出任何副本,运行中的 docker ps 将不再显示运行中的 Docker 容器。
core@ip-172-30-5-70 ∼ $ docker service rm helloworld helloworld core@ip-172-30-5-70 ∼ $ docker service inspect helloworld [] Error: no such service: helloworld
第 4 章讨论了更多关于服务的内容。
将工作节点提升为管理器
如前所述,默认情况下,管理器节点也是工作者节点,但是工作者节点只是工作者节点。但是工作者节点可以被提升为管理者节点。将一个或多个工作节点提升为管理节点的 Docker 命令具有以下语法。
docker node promote NODE [NODE...]
该命令必须从 leader 节点运行。举个例子,提升节点 ip-172-30-5-108.ec2.internal 。如输出所示,该节点被提升为管理器节点。随后列出群中的节点,被提升的节点应该具有管理者状态 Reachable 。
工作者节点应该优选地使用节点 ID 来升级;其原因将在后面讨论。使用节点 ID 提升另一个工作节点。随后,两个工作节点在管理器状态列中被列为 Reachable 。
core@ip-172-30-5-70 ∼ $ docker node promote ip-172-30-5-108.ec2.internal Node ip-172-30-5-108.ec2.internal promoted to a manager in the swarm. core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 9n5qmj4pp91f0n3s0n2jwjdv8 ip-172-30-5-108.ec2.internal Ready Active Reachable bgzqx2cfsf05qdradxytmdcp3 * ip-172-30-5-70.ec2.internal Ready Active Leader bqq4bryuobylu0glm4p19tko4 ip-172-30-5-31.ec2.internal Ready Active
将管理员节点降级为工作节点
可以使用以下 Docker 命令将管理节点降级为工作节点。
docker node demote NODE [NODE...]
包括领导者节点在内的任何管理者节点都可能被降级。例如,降级管理器节点 ip-172-30-5-108.ec2.internal 。
core@ip-172-30-5-70 ∼ $ docker node demote ip-172-30-5-108.ec2.internal Manager ip-172-30-5-108.ec2.internal demoted in the swarm.
一旦降级,只能从管理器节点运行的命令(如 docker node ls ) 将无法在该节点上运行。 docker node ls 命令将降级的节点列为工作节点;没有为工人节点列出 MANAGER STATUS 。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 9n5qmj4pp91f0n3s0n2jwjdv8 ip-172-30-5-108.ec2.internal Ready Active bgzqx2cfsf05qdradxytmdcp3 * ip-172-30-5-70.ec2.internal Ready Active Leader bqq4bryuobylu0glm4p19tko4 ip-172-30-5-31.ec2.internal Ready Active
节点应该优选地被升级/降级,或者在使用节点 ID 指向该节点的任何命令中被引用,该节点 ID 对于节点是唯一的。原因是,降级的节点如果升级回来,可能会添加不同的节点 ID,并且 docker node ls 命令可能会为同一个主机名列出两个节点 ID。如果主机名用于引用一个节点,可能会导致 node is ambiguous 错误消息。
使一个工作者节点离开群体
之前,您将一个节点作为工作者节点加入到群中。工作者节点也可以离开群。例如,使用下面的命令让一个工作节点离开,该命令必须从您想要从集群中删除的节点上运行。
docker swarm leave
如消息输出所示,节点已经离开了群。
core@ip-172-30-5-31 ∼ $ docker swarm leave Node left the swarm.
类似地,让另一个工作者节点离开群体。
core@ip-172-30-5-108 ∼ $ docker swarm leave Node left the swarm.
在一个工作者节点离开群之后,该节点本身并没有被移除,而是继续被列在具有 Down 状态的 docker node ls 命令中。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 9n5qmj4pp91f0n3s0n2jwjdv8 ip-172-30-5-108.ec2.internal Down Active bgzqx2cfsf05qdradxytmdcp3 * ip-172-30-5-70.ec2.internal Ready Active Leader bqq4bryuobylu0glm4p19tko4 ip-172-30-5-31.ec2.internal Down Active
使管理节点离开群体
虽然使工作者节点离开群更容易,但是当管理者节点必须离开群时就不同了。使工作者节点离开群只会降低群中可调度的服务任务方面的群容量。但是让一个管理节点离开群会使群变得不可用。如果容错不允许管理节点失败或从群中移除,则使工作节点离开群的相同的 docker swarm leave 命令不能用于使管理节点离开群。如果一个群只有一个管理节点,那么 docker swarm leave 命令会生成下面的错误消息。
core@ip-172-30-5-70 ∼ $ docker swarm leave Error response from daemon: You are attempting to leave the swarm on a node that is participating as a manager. Removing the last manager erases all current state of the swarm. Use `--force` to ignore this message.
将 --force 选项添加到管理节点上的 docker swarm leave 命令,以使管理节点离开群。
core@ip-172-30-5-70 ∼ $ docker swarm leave --force Node left the swarm.
如果唯一的管理节点被移除,那么群体将不复存在。如果要使用群组模式,必须再次初始化群组。
core@ip-172-30-5-70 ∼ $ docker swarm init --advertise-addr 172.30.5.70
Swarm initialized: current node (cnyc2w3n8q8zuxjujcd2s729k) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-4lxmisvlszjgck4ly0swsxubejfx0phlne1xegho2fiq99amqf-11mpscd8gs6bsayzren8fa2ki \
172.30.5.70:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
创建一个只有管理节点的新群,该群最初只有一个节点。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS cnyc2w3n8q8zuxjujcd2s729k * ip-172-30-5-70.ec2.internal Ready Active Leader
如果一个群有两个管理节点,让其中一个管理节点离开群会有不同的效果。如前所述,对于两个管理器,容错能力为 0。要创建一个有两个管理节点的群,从一个有一个管理节点和两个工作节点的群开始。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 4z03hudbo3fz17q94leo24pvh ip-172-30-5-108.ec2.internal Ready Active cnyc2w3n8q8zuxjujcd2s729k * ip-172-30-5-70.ec2.internal Ready Active Leader efsxwt43iskasa6poh2stkjeb ip-172-30-5-31.ec2.internal Ready Active
将其中一个工作节点提升为管理节点。
core@ip-172-30-5-70 ∼ $ docker node promote ip-172-30-5-108.ec2.internal Node ip-172-30-5-108.ec2.internal promoted to a manager in the swarm.
该群将有两个管理节点。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 4z03hudbo3fz17q94leo24pvh ip-172-30-5-108.ec2.internal Ready Active Reachable cnyc2w3n8q8zuxjujcd2s729k * ip-172-30-5-70.ec2.internal Ready Active Leader efsxwt43iskasa6poh2stkjeb ip-172-30-5-31.ec2.internal Ready Active
从不是领导者节点的管理器节点运行 docker swarm leave 命令。将生成以下消息。
core@ip-172-30-5-108 ∼ $ docker swarm leave
守护程序的错误响应如下:
You are attempting to leave the swarm on a node that is participating as a manager.
删除此节点会使两个管理器中只剩下一个。没有 Raft quorum,你的虫群将无法接近。恢复失去共识的蜂群的唯一方法是用 --force-new-cluster 重新初始化它。使用 --force 抑制此消息。
要使管理器节点离开,必须在命令中添加 --force 选项。
core@ip-172-30-5-108 ∼ $ docker swarm leave --force Node left the swarm.
当两个管理者中的一个离开群体时,Raft 的法定人数就会丢失,群体变得不可访问。如前所述,必须使用 --force-new-cluster 选项重新初始化蜂群。
重新初始化群集
无法使用用于初始化群组的命令来重新初始化失去仲裁的群组。如果同一个命令在一个失去仲裁的群上运行,会有一条消息指出该节点已经在该群中,必须首先离开该群:
core@ip-172-30-5-70 ∼ $ docker swarm init --advertise-addr 172.30.5.70
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
To reinitialize the Swarm the --force-new-cluster option must be added to the docker swarm init command. core@ip-172-30-5-70 ∼ $ docker swarm init --advertise-addr 172.30.5.70 --force-new-cluster
Swarm initialized: current node (cnyc2w3n8q8zuxjujcd2s729k) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-4lxmisvlszjgck4ly0swsxubejfx0phlne1xegho2fiq99amqf-11mpscd8gs6bsayzren8fa2ki \
172.30.5.70:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
群被重新初始化,并输出添加工作者节点的 docker swarm join 命令。
修改节点可用性
可以使用带有 --availability 选项的 D 命令修改节点的可用性。可以设置表 2-6 中的 --availability 选项之一。
表 2-6。
Availability Options
| 可用性选项 | 描述 | | --- | --- | | `active` | 将暂停或耗尽的节点恢复为活动状态。 | | `pause` | 暂停节点,使其无法接收新任务。 | | `drain` | 对于工作节点,该节点会停机,无法调度新任务。管理节点也变得不可用于调度新任务,但是继续执行群管理。 |
例如,您可以如下所示清空一个工作节点。
core@ip-172-30-5-70 ∼ $ docker node update --availability drain ip-172-30-5-108.ec2.internal ip-172-30-5-108.ec2.internal
工作节点已耗尽。耗尽节点上的所有服务任务都将关闭,并在其他可用节点上启动。 docker node ls 命令的输出列出了状态设置为 Drain 的节点。
core@ip-172-30-5-70 ∼ $ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
bhuzgyqvb83dx0zvms54o0a58 ip-172-30-5-108.ec2.internal Ready Drain
cnyc2w3n8q8zuxjujcd2s729k * ip-172-30-5-70.ec2.internal Ready Active Leader
efsxwt43iskasa6poh2stkjeb ip-172-30-5-31.ec2.internal Ready Active
The node detail (partial output is listed) for the drained worker node lists the node availability as "drain".core@ip-172-30-5-70 ∼ $ docker node inspect ip-172-30-5-108.ec2.internal
[
{
"ID": "bhuzgyqvb83dx0zvms54o0a58",
"Version": {
"Index": 49
},
"CreatedAt": "2017-07-22T19:30:31.544403951Z",
"UpdatedAt": "2017-07-22T19:33:37.45659544Z",
"Spec": {
"Role": "worker",
"Availability": "drain"
},
"Description": {
"Hostname": "ip-172-30-5-108.ec2.internal",
耗尽节点上的所有服务任务都将关闭,并在其他可用节点上启动。带有 docker node ls 的节点可用性被列为 Drain 。
在 --availability 设置为 Active 的情况下,可以使用 docker node update 命令再次激活被清空的节点。
core@ip-172-30-5-70 ∼ $ docker node update --availability active ip-172-30-5-108.ec2.internal ip-172-30-5-108.ec2.internal
被清空的节点变为活动状态,并以设置为 Active 的状态列出。
core@ip-172-30-5-70 ∼ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS bhuzgyqvb83dx0zvms54o0a58 ip-172-30-5-108.ec2.internal Ready Active cnyc2w3n8q8zuxjujcd2s729k * ip-172-30-5-70.ec2.internal Ready Active Leader efsxwt43iskasa6poh2stkjeb ip-172-30-5-31.ec2.internal Ready Active
删除节点
可以使用从任何管理节点运行的 docker node rm 命令从群中删除一个或多个节点。
docker node rm [OPTIONS] NODE [NODE...]
docker swarm leave 和 docker node rm 的区别在于 docker node rm 只能从管理节点运行。降级的节点只能用 docker node rm 命令从集群中移除。不使用 --force 选项删除管理器节点的顺序如下。
- 降级 manager 节点,使其成为 worker 节点。
- 清空工作节点。
- 让工作者节点离开群体。
- 移除节点。
摘要
本章讨论了在群组模式下使用 Docker。首先,用 docker swarm init 命令初始化 Swarm 模式,使当前节点成为 Swarm 中的管理节点。随后,您使用 docker swarm join 命令将工作节点加入到集群中。本章还讨论了将工作者节点提升为管理者节点/将管理者节点降级为工作者节点、使工作者节点离开群组然后重新加入群组、使管理者节点离开群组、重新初始化群组以及修改节点可用性和删除节点。下一章介绍 Docker for AWS,这是 Docker Swarm 模式的托管服务。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论