管理并维护 Docker Engine 集群
当您运行 Docker Engine 集群时,管理器节点是用于管理集群和存储集群状态的关键组件。了解管理器节点的一些关键特性对于正确部署和维护集群至关重要。
请参阅 节点如何工作 以简要了解 Docker Swarm 模式以及管理节点与工作节点之间的区别。
在集群中操作管理节点
Swarm 管理节点使用 Raft 共识算法来管理集群状态。您只需了解 Raft 的一些基本概念即可管理集群。
对管理节点的数量没有限制。关于部署多少管理节点的决策,需要在性能和容错能力之间取得平衡。向Swarm集群中添加管理节点可以提高其容错性。然而,增加管理节点会降低写入性能,因为需要更多节点确认更新集群状态的提议,这会导致更多的网络往返流量。
Raft 需要大多数管理者(也称为法定人数)就向集群中提出的更新达成一致,例如节点的添加或删除。成员操作受限于与状态复制相同的约束。
保持管理者的法定人数
如果集群失去了管理节点的法定人数,集群将无法执行管理任务。如果您的集群有多个管理节点,请确保数量超过两个。 为了维持法定人数,必须保证大多数管理节点在线。建议设置奇数个管理节点,因为增加为偶数并不会让维持法定人数变得更容易。例如,无论您有 3 个还是 4 个管理节点,最多只能允许 1 个节点失效以维持法定人数。如果您有 5 个或 6 个管理节点,则最多只能允许 2 个节点失效。
即使集群失去了管理节点的法定人数,现有工作节点上的集群任务仍会继续运行。但是,无法添加、更新或删除集群节点,也无法启动、停止、移动或更新新任务或现有任务。
参见 从失去法定人数中恢复,以获取如果您确实失去了管理节点的法定人数的故障排除步骤。
配置管理器以在静态 IP 地址上进行通告
当初始化 swarm 时,您必须指定 --advertise-addr 标志以向 swarm 中的其他管理节点广播您的地址。有关更多信息,请参阅
在 swarm 模式下运行 Docker Engine。由于管理节点旨在作为基础设施的稳定组件,因此您应为广播地址使用 固定 IP 地址,以防止机器重启后 swarm 变得不稳定。
如果整个集群重启,并且每个管理节点随后都获取了一个新的 IP 地址,那么任何节点都无法联系到现有的管理节点。因此, 当节点试图使用旧的 IP 地址相互通信时,整个集群将陷入挂起状态。
动态IP地址对worker节点是可以接受的。
为容错添加管理节点
您应在 Swarm 中维护奇数个管理器节点,以支持管理器节点故障。拥有奇数个管理器可确保在网络分区期间,如果网络被划分为两个集合,法定人数(quorum)更有可能保持可用以处理请求。如果遇到超过两个网络分区,则无法保证维持法定人数。
| 集群规模 | 多数 | 容错率 |
|---|---|---|
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 6 | 4 | 2 |
| 7 | 4 | 3 |
| 8 | 5 | 3 |
| 9 | 5 | 4 |
例如,在一个有 5 个节点 的集群中,如果丢失了 3 个节点,则无法形成法定人数(quorum)。因此,在恢复其中一个不可用的管理节点或使用灾难恢复命令恢复集群之前,无法添加或删除节点。请参阅 从灾难中恢复。
虽然可以将集群缩减为单个管理节点,但无法将最后一个管理节点降级。这确保了您仍能访问集群,并且集群可以继续处理请求。将集群缩减为单个管理节点是一项不安全操作,不建议执行。如果在降级过程中最后一个节点意外离开集群,集群将不可用,直到您重启该节点或使用 --force-new-cluster 重新启动。
您使用 docker swarm 和 docker node
子系统来管理 Swarm 成员身份。有关如何添加工作节点以及将工作节点提升为管理节点的更多信息,请参阅
向 Swarm 添加节点。
分发管理节点
除了保持奇数个管理节点外,在部署管理节点时还需注意数据中心拓扑结构。为实现最佳容错能力,请将管理节点分布在至少 3 个可用区中,以应对整组机器故障或常规维护场景。如果其中任何一个可用区发生故障,Swarm 集群仍应能维持可用的管理节点法定人数,从而继续处理请求并重新平衡工作负载。
| Swarm 管理节点 | 重分区(在 3 个可用区上) |
|---|---|
| 3 | 1-1-1 |
| 5 | 2-2-1 |
| 7 | 3-2-2 |
| 9 | 3-3-3 |
运行仅管理节点
默认情况下,管理器节点也充当工作节点。这意味着调度器 可以将任务分配给管理器节点。对于小型和非关键性集群, 只要在使用 CPU 和内存资源约束来调度服务时,将任务分配给管理器的风险相对较低。
然而,由于管理节点使用 Raft 共识算法以一致的方式复制数据,它们对资源饥饿非常敏感。您应该将群集(swarm)中的管理节点与可能会阻塞群集操作(如群集心跳或领导者选举)的进程隔离开来。
为避免干扰管理节点的操作,您可以排空管理节点,使其不再作为工作节点使用:
$ docker node update --availability drain <NODE>
当您对节点执行排水操作时,调度器会将该节点上运行的所有任务重新分配给Swarm中其他可用的工作节点。同时,这将阻止调度器向该节点分配新任务。
添加工作节点以实现负载均衡
向群集添加节点 以平衡您的群集负载。只要工作节点符合服务的要求,复制的服务任务就会尽可能均匀地分布在群集中。当限制服务仅在特定类型的节点上运行时(例如具有特定CPU数量或内存量的节点),请记得不符合这些要求的工作节点将无法运行这些任务。
监控 Swarm 健康状态
您可以通过在 /nodes HTTP 端点以 JSON 格式查询 docker nodes API 来监控管理节点的健康状况。有关更多信息,请参阅
节点 API 文档。
在命令行中,运行 docker node inspect <id-node> 以查询节点。
例如,要查询节点作为管理节点的可达性:
$ docker node inspect manager1 --format "{{ .ManagerStatus.Reachability }}"
reachable
要查询节点作为接受任务的 worker 的状态:
$ docker node inspect manager1 --format "{{ .Status.State }}"
ready
从这些命令中,我们可以看到 manager1 的状态既是 reachable 作为管理器,也是 ready 作为工作节点。
unreachable 健康状态表示该特定管理节点无法从其他管理节点访问。在这种情况下,您需要采取措施恢复无法访问的管理节点:
- 重新启动守护进程,并查看管理器是否恢复为可访问状态。
- 重新启动机器。
- 如果重启或重新引导均无效,您应该添加另一个管理节点或将一个工作节点提升为管理节点。此外,您还需要使用
docker node demote <NODE>和docker node rm <id-node>从管理节点集中干净地移除失败的节点条目。
或者,您也可以从带有 docker node ls 的管理节点获取群集健康状况的概述:
$ docker node ls
ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
1mhtdwhvsgr3c26xxbnzdc3yp node05 Accepted Ready Active
516pacagkqp2xc3fk9t1dhjor node02 Accepted Ready Active Reachable
9ifojw8of78kkusuc4a6c23fx * node01 Accepted Ready Active Leader
ax11wdpwrrb6db3mfjydscgk7 node04 Accepted Ready Active
bb1nrq2cswhtbg4mrsqnlx1ck node03 Accepted Ready Active Reachable
di9wxgz8dtuh9d2hn089ecqkf node06 Accepted Ready Active
故障排除管理节点
您绝不应通过从另一个节点复制 raft 目录来重启管理节点。数据目录对每个节点 ID 是唯一的。一个节点只能使用一个节点 ID 加入集群。节点 ID 空间必须是全局唯一的。
要干净地将管理节点重新加入集群:
- 使用
docker node demote <NODE>将节点降级为工作节点。 - 使用
docker node rm <NODE>从集群中移除该节点。 - 使用
docker swarm join以全新状态将节点重新加入集群。
有关将管理节点加入群集的更多信息,请参阅 将节点加入群集。
强制移除节点
在大多数情况下,您应该在将节点从集群中移除之前先关闭它,使用的是 docker node rm 命令。如果节点变得无法访问、无响应或已受损,您可以通过传递 --force 标志来强制移除该节点而无需先关闭它。例如,如果 node9 已受损:
$ docker node rm node9
Error response from daemon: rpc error: code = 9 desc = node node9 is not down and can't be removed
$ docker node rm --force node9
Node node9 removed from swarm在强制移除管理节点之前,您必须先将其降级为工作节点。如果您降级或移除了某个管理节点,请确保始终保留奇数个管理节点。
备份 Swarm
Docker 管理节点将集群状态和管理员日志存储在
/var/lib/docker/swarm/ 目录中。这些数据包括用于加密 Raft 日志的密钥。如果没有这些密钥,您将无法恢复集群。
您可以使用任何管理器来备份群集。请按照以下操作步骤进行。
如果群集启用了自动锁定,您需要解锁密钥 才能从备份中恢复群集。如有必要,请获取解锁密钥并 将其存储在安全位置。如果您不确定,请阅读 锁定您的群集以保护其加密密钥。
在备份数据之前,请先停止管理器上的 Docker,以确保备份过程中没有数据被修改。虽然可以在管理器运行时进行备份(即“热”备份),但这并不推荐,因为恢复时的结果可能不够可预测。当管理器停机时,其他节点仍会继续生成不属于此备份范围的 Swarm 数据。
注意
请务必维护 Swarm 管理节点的法定人数(quorum)。在某个管理节点关闭期间,如果再有其他节点丢失,您的 Swarm 将更容易失去法定人数。您运行的管理节点数量需要权衡取舍。如果您经常停机以进行备份,建议运行一个包含五个管理节点的 Swarm,这样在备份运行期间即使再丢失一个管理节点,也不会影响服务的正常运行。
备份整个
/var/lib/docker/swarm目录。重启管理器。
要恢复,请参见 从备份中还原。
灾难恢复
从备份恢复
按照 备份 Swarm中所述备份 Swarm 后,使用以下步骤将数据恢复到新的 Swarm。
关闭目标主机上已恢复的 Swarm 中的 Docker。
从新swarm中移除
/var/lib/docker/swarm目录的内容。使用备份内容恢复
/var/lib/docker/swarm目录。注意
新节点使用与旧节点相同的磁盘存储加密密钥。目前无法更改磁盘存储加密密钥。
对于启用了自动锁定功能的 Swarm,解锁密钥与旧 Swarm 中的相同,并且恢复 Swarm 时需要该解锁密钥。
在新的节点上启动 Docker。如有必要,请解锁集群(swarm)。使用以下命令重新初始化集群,以确保该节点不会尝试连接到旧集群中已不存在的节点。
$ docker swarm init --force-new-cluster验证 Swarm 的状态是否符合预期。这可能包括特定于应用程序的测试,或者简单地检查输出
docker service ls,以确保所有预期的服务都存在。如果您使用自动锁定功能, 旋转解锁键。
添加管理节点和工作节点以使您的新Swarm达到运行 容量。
在新集群上恢复您之前的备份方案。
从失去法定人数中恢复
Swarm 具有故障恢复能力,可以从任意数量的临时节点故障(例如机器重启或崩溃后重启)或其他瞬态错误中恢复。但是,如果 Swarm 失去法定人数(quorum),则无法自动恢复。现有工作节点上的任务将继续运行,但无法执行管理任务,包括扩展或更新服务、将节点加入或移出 Swarm。最好的恢复方法是将缺失的管理节点重新上线。如果这不可行,请继续阅读以了解一些恢复 Swarm 的选项。
在包含 N 个管理节点的集群中,必须始终有超过半数的管理节点(即法定人数)可用。例如,在一个拥有五个管理节点的集群中,至少需要三个节点正常运行并相互通信。换句话说,该集群最多可以容忍 (N-1)/2 个永久性故障;超出此数量后,涉及集群管理的请求将无法处理。此类故障包括数据损坏或硬件故障。
如果您失去了管理节点的法定人数(quorum),您将无法管理该集群。如果已失去法定人数,而您仍试图在集群上执行任何管理操作,则会发生错误:
Error response from daemon: rpc error: code = 4 desc = context deadline exceeded从失去法定人数(quorum)中恢复的最佳方法是将故障节点重新上线。如果无法做到这一点,则从该状态恢复的唯一方法是使用
--force-new-cluster操作从管理节点执行。此操作将移除除运行该命令的管理节点之外的所有管理节点。由于现在只剩下一个管理节点,因此实现了法定人数。
继续提升节点为管理节点,直到达到所需的管理节点数量。
从节点恢复,请运行:
$ docker swarm init --force-new-cluster --advertise-addr node01:2377
当您使用 --force-new-cluster 标志运行 docker swarm init 命令时,运行该命令的 Docker Engine 将成为单节点群集的管理器节点,该群集能够管理和运行服务。管理器拥有之前关于服务和任务的所有信息,工作节点仍然是群集的一部分,服务也仍在运行。您需要添加或重新添加管理器节点,以恢复之前的任务分布,并确保拥有足够的管理器来维持高可用性并防止失去法定人数。
强制集群重新平衡
通常,您无需强制集群重新平衡其任务。当您向集群添加新节点,或者某个节点在离线一段时间后重新连接时,集群不会自动将工作负载分配给空闲节点。这是一个设计上的决定。如果集群为了平衡而周期性地在不同节点间移动任务,那么使用这些服务的客户端就会受到干扰。我们的目标是避免因追求集群范围内的平衡而中断正在运行的服务。当有新任务启动,或者运行着任务的节点变得不可用时,这些任务将被分配给负载较轻的节点。最终目标是实现平衡,同时将对终端用户的干扰降至最低。
您可以使用 --force 或 -f 标志配合 docker service update 命令
强制服务在可用的工作节点之间重新分配其任务。
这将导致服务任务重启。客户端应用程序可能会受到中断。
如果您已配置,您的服务将使用
滚动更新。
如果您使用的是较早版本,并且希望实现工作节点之间更均衡的负载分配,且不介意中断正在运行的任务,您可以通过暂时向上扩展服务来强制集群重新平衡。使用
docker service inspect --pretty <servicename>可以查看服务的配置规模。
当您使用 docker service scale时,任务数量最少的节点将被选中以接收新的工作负载。您的集群中可能存在多个负载不足的节点。您可能需要多次以适度增量向上扩展服务,才能在所有节点上实现所需的平衡。
当负载平衡达到您的满意程度时,您可以将服务缩回到原始规模。您可以使用 docker service ps 来评估服务在各节点上的当前平衡状态。