管理和维护 Docker 引擎集群

运行Docker Engine集群时,管理器节点是管理集群和存储集群状态的关键组件。了解管理器节点的一些关键功能对于正确部署和维护集群非常重要。

请参阅 节点工作方式,以简要了解Docker Swarm模式以及管理器节点和工作节点之间的区别。

操作集群中的管理器节点

Swarm管理器节点使用 Raft共识算法 来管理集群状态。您只需要了解Raft的一些基本概念即可管理集群。

管理器节点的数量没有限制。关于实现多少个管理器节点的决策是在性能和容错性之间的权衡。向集群添加管理器节点会使集群更具容错性。但是,额外的管理器节点会降低写入性能,因为更多节点必须确认更新集群状态的提案。这意味着更多的网络往返流量。

Raft要求大多数管理器(也称为仲裁)同意对集群的拟议更新,例如节点添加或删除。成员资格操作受与状态复制相同的约束。

维护管理器的仲裁

如果集群丢失了管理器的仲裁,则集群无法执行管理任务。如果您的集群有多个管理器,请始终使用两个以上的管理器。为了维护仲裁,大多数管理器必须可用。建议使用奇数个管理器,因为下一个偶数并不会使仲裁更容易保持。例如,无论您有3个还是4个管理器,您仍然只能丢失1个管理器并保持仲裁。如果您有5个或6个管理器,您仍然只能丢失两个。

即使集群丢失了管理器的仲裁,现有工作节点上的集群任务也会继续运行。但是,集群节点无法添加、更新或删除,并且无法启动、停止、移动或更新新的或现有的任务。

如果确实丢失了管理器的仲裁,请参阅 从丢失仲裁中恢复,了解故障排除步骤。

配置管理器以在静态IP地址上进行广播

初始化集群时,必须指定--advertise-addr标志以将您的地址广播到集群中的其他管理器节点。有关更多信息,请参阅 在Swarm模式下运行Docker Engine。因为管理器节点旨在成为基础设施的稳定组件,所以您应该为广播地址使用固定IP地址,以防止集群在机器重启时变得不稳定。

如果整个集群重新启动并且每个管理器节点随后都获得新的IP地址,则任何节点都无法联系现有的管理器。因此,当节点尝试使用其旧IP地址相互联系时,集群将挂起。

动态IP地址适用于工作节点。

添加管理器节点以实现容错

您应该在集群中维护奇数个管理器以支持管理器节点故障。拥有奇数个管理器可以确保在网络分区期间,如果网络被划分为两组,则仲裁更有可能保持可用以处理请求。如果您遇到两个以上的网络分区,则无法保证保持仲裁。

集群大小多数容错
110
220
321
431
532
642
743
853
954

例如,在一个包含5个节点的集群中,如果您丢失了3个节点,则您没有仲裁。因此,在恢复其中一个不可用的管理器节点或使用灾难恢复命令恢复集群之前,您无法添加或删除节点。请参阅 从灾难中恢复

虽然可以将集群缩减到单个管理器节点,但无法降级最后一个管理器节点。这确保您可以访问集群,并且集群仍然可以处理请求。缩减到单个管理器是不安全的,不建议这样做。如果最后一个节点在降级操作期间意外离开集群,则集群将不可用,直到您重新启动节点或使用--force-new-cluster重新启动。

您可以使用docker swarmdocker node子系统来管理集群成员资格。有关如何添加工作节点以及如何将工作节点提升为管理器的更多信息,请参阅 向集群添加节点

分发管理器节点

除了维护奇数个管理器节点之外,在放置管理器时还要注意数据中心拓扑。为了获得最佳容错性,请将管理器节点分布在至少3个可用区中,以支持整个机器集或常见维护场景的故障。如果您在任何这些区域中遇到故障,集群应该保持可用以处理请求和重新平衡工作负载的管理器节点仲裁。

Swarm管理器节点重新分区(在3个可用区上)
31-1-1
52-2-1
73-2-2
93-3-3

运行仅限管理器的节点

默认情况下,管理器节点也充当工作节点。这意味着调度程序可以将任务分配给管理器节点。对于小型且非关键的集群,只要您使用cpu和内存的资源约束来调度服务,将任务分配给管理器是相对低风险的。

但是,由于管理器节点使用Raft共识算法以一致的方式复制数据,因此它们对资源匮乏很敏感。您应该将集群中的管理器与可能阻塞集群操作(如集群心跳或领导者选举)的进程隔离。

为了避免干扰管理器节点的操作,您可以使管理器节点失效以使其不可用作为工作节点。

$ docker node update --availability drain <NODE>

使节点失效后,调度程序会将节点上运行的任何任务重新分配给集群中的其他可用工作节点。它还会阻止调度程序将任务分配给该节点。

添加工作节点以实现负载均衡

向 Swarm 添加节点 添加节点到集群 以平衡 Swarm 的负载。只要工作节点符合服务的相关要求,复制的服务任务就会随着时间的推移尽可能均匀地分布在整个 Swarm 中。当限制服务仅在特定类型的节点上运行时(例如,具有特定数量的 CPU 或内存量的节点),请记住,不满足这些要求的工作节点无法运行这些任务。

监控集群健康状况

您可以通过/nodes HTTP 端点以 JSON 格式查询 docker nodes API 来监控管理器节点的健康状况。节点 API 文档 提供了更多信息。

在命令行中,运行docker node inspect <id-node> 来查询节点。例如,要查询节点作为管理器的可达性

$ docker node inspect manager1 --format "{{ .ManagerStatus.Reachability }}"
reachable

要查询节点作为接受任务的工作节点的状态

$ docker node inspect manager1 --format "{{ .Status.State }}"
ready

从这些命令中,我们可以看到manager1 作为管理器处于reachable状态,作为工作节点处于ready状态。

unreachable 健康状态表示此特定管理器节点无法从其他管理器节点访问。在这种情况下,您需要采取措施来恢复不可访问的管理器。

  • 重新启动守护程序,查看管理器是否恢复可访问。
  • 重新启动机器。
  • 如果重新启动守护程序和机器均无效,则应添加另一个管理器节点或将工作节点提升为管理器节点。您还需要使用docker node demote <NODE>docker node rm <id-node> 从管理器集中干净地移除失败的节点条目。

或者,您也可以使用docker node ls从管理器节点获取 Swarm 健康状况的概述。

$ 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 一次加入 Swarm。节点 ID 空间应该是全局唯一的。

要将管理器节点干净地重新加入集群

  1. 使用docker node demote <NODE>将节点降级为工作节点。
  2. 使用docker node rm <NODE>从 Swarm 中移除节点。
  3. 使用docker swarm join将节点以全新状态重新加入 Swarm。

有关将管理器节点加入 Swarm 的更多信息,请参阅 将节点加入 Swarm

强制删除节点

在大多数情况下,您应该在使用docker node rm命令从 Swarm 中移除节点之前关闭该节点。如果节点变得不可访问、无响应或遭到破坏,您可以通过传递--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

在强制移除管理器节点之前,必须先将其降级为工作节点角色。如果降级或移除管理器,请确保始终有奇数个管理器节点。

备份集群

Docker 管理器节点将 Swarm 状态和管理器日志存储在/var/lib/docker/swarm/目录中。此数据包括用于加密 Raft 日志的密钥。如果没有这些密钥,则无法恢复 Swarm。

您可以使用任何管理器备份 Swarm。请按照以下步骤操作。

  1. 如果 Swarm 启用了自动锁定,则需要解锁密钥才能从备份中恢复 Swarm。如有必要,请检索解锁密钥并将其存储在安全位置。如果您不确定,请阅读 锁定您的 Swarm 以保护其加密密钥

  2. 在备份数据之前,请停止管理器上的 Docker,以便在备份过程中不会更改任何数据。可以在管理器运行时进行备份(“热”备份),但不推荐这样做,并且在恢复时结果的可预测性较低。在管理器关闭期间,其他节点将继续生成此备份中不包含的 Swarm 数据。

    注意

    确保维护 Swarm 管理器的仲裁。在管理器关闭期间,如果进一步丢失节点,则 Swarm 更容易丢失仲裁。您运行的管理器数量是一个权衡。如果您定期关闭管理器以进行备份,请考虑运行五个管理器的 Swarm,以便在备份运行期间可以丢失一个额外的管理器,而不会中断您的服务。

  3. 备份整个/var/lib/docker/swarm目录。

  4. 重新启动管理器。

有关恢复,请参阅 从备份恢复

从灾难中恢复

从备份恢复

按照 备份 Swarm 中所述备份 Swarm 后,请使用以下步骤将数据恢复到新的 Swarm。

  1. 关闭已恢复 Swarm 的目标主机上的 Docker。

  2. 删除新 Swarm 上/var/lib/docker/swarm目录的内容。

  3. 使用备份内容恢复/var/lib/docker/swarm目录。

    注意

    新节点使用与旧节点相同的磁盘存储加密密钥。目前无法更改磁盘存储加密密钥。

    对于启用了自动锁定的 Swarm,解锁密钥也与旧 Swarm 上的相同,并且需要解锁密钥才能恢复 Swarm。

  4. 在新节点上启动 Docker。如有必要,解锁 Swarm。使用以下命令重新初始化 Swarm,以便此节点不会尝试连接到旧 Swarm 的一部分(可能不再存在)的节点。

    $ docker swarm init --force-new-cluster
    
  5. 验证 Swarm 的状态是否符合预期。这可能包括特定于应用程序的测试,或者只是检查docker service ls的输出以确保所有预期的服务都存在。

  6. 如果您使用自动锁定,请 旋转解锁密钥

  7. 添加管理器和工作节点以将您的新 Swarm 提升到运行容量。

  8. 在新 Swarm 上恢复您之前的备份机制。

从丢失仲裁中恢复

Swarm 具有很强的容错能力,可以从任意数量的临时节点故障(机器重新启动或崩溃并重新启动)或其他瞬态错误中恢复。但是,如果 Swarm 丢失仲裁,则无法自动恢复。现有工作节点上的任务将继续运行,但管理任务将无法进行,包括扩展或更新服务以及加入或从 Swarm 中移除节点。最好的恢复方法是将丢失的管理器节点重新联机。如果无法做到这一点,请继续阅读一些恢复 Swarm 的选项。

在包含N个管理器的 Swarm 中,必须始终有仲裁(多数)管理器节点可用。例如,在具有五个管理器的 Swarm 中,至少必须有三个管理器处于运行状态并相互通信。换句话说,Swarm 最多可以容忍(N-1)/2个永久性故障,超过此数量后,涉及 Swarm 管理的请求将无法处理。这些类型的故障包括数据损坏或硬件故障。

如果您丢失了管理器的仲裁,则无法管理 Swarm。如果您丢失了仲裁并尝试对 Swarm 执行任何管理操作,则会发生错误。

Error response from daemon: rpc error: code = 4 desc = context deadline exceeded

从丢失仲裁中恢复的最佳方法是将失败的节点重新联机。如果您无法做到这一点,则从这种状态恢复的唯一方法是从管理器节点使用--force-new-cluster操作。这将移除除运行该命令的管理器之外的所有管理器。因为现在只有一个管理器,所以仲裁已实现。将节点提升为管理器,直到您拥有所需数量的管理器。

从要恢复的节点运行

$ docker swarm init --force-new-cluster --advertise-addr node01:2377

当您使用--force-new-cluster标志运行docker swarm init命令时,运行该命令的 Docker Engine 将成为单节点 Swarm 的管理器节点,该节点能够管理和运行服务。管理器拥有关于服务和任务的所有先前信息,工作节点仍然是 Swarm 的一部分,并且服务仍在运行。您需要添加或重新添加管理器节点以实现您之前的任务分配,并确保您拥有足够的管理器以维持高可用性并防止丢失仲裁。

强制集群重新平衡

通常,您无需强制 Swarm 重新平衡其任务。当您向 Swarm 添加新节点或节点在一段时间不可用后重新连接到 Swarm 时,Swarm 不会自动向空闲节点分配工作负载。这是一个设计决策。如果 Swarm 定期将任务转移到不同的节点以实现平衡,则使用这些任务的客户端将受到中断。目标是避免为了 Swarm 的平衡而中断正在运行的服务。当新的任务启动或具有正在运行的任务的节点变得不可用时,这些任务将分配给较不繁忙的节点。目标是最终实现平衡,同时最大限度地减少对最终用户的干扰。

您可以将--force-f标志与docker service update命令一起使用,以强制服务在其可用的工作节点之间重新分配其任务。这会导致服务任务重新启动。客户端应用程序可能会中断。如果您已对其进行配置,则您的服务将使用 滚动更新

如果您使用的是较旧版本,并且希望在工作节点之间实现均衡的负载,并且不介意中断正在运行的任务,您可以通过暂时向上扩展服务来强制您的 swarm 重新平衡。使用docker service inspect --pretty <servicename>查看服务的配置规模。当您使用docker service scale时,任务数量最少的节点将成为接收新工作负载的目标。您的 swarm 中可能有多个负载不足的节点。您可能需要多次以较小的增量向上扩展服务,才能在所有节点之间实现所需的平衡。

当负载达到您满意的平衡状态时,您可以将服务缩减回原始规模。您可以使用docker service ps评估服务在节点之间的当前平衡情况。

另请参见 docker service scaledocker service ps