管理和维护Docker引擎群

当你运行一群Docker引擎时,管理节点是管理群集和存储群集状态的关键组件。理解管理节点的一些关键特性对于正确部署和维护群集非常重要。

请参考 节点如何工作 以简要了解Docker Swarm模式以及管理节点和工作节点之间的区别。

在群集中操作管理节点

Swarm管理器节点使用 Raft共识算法来管理 swarm状态。你只需要理解Raft的一些基本概念 就可以管理一个swarm。

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

Raft 需要大多数管理者(也称为法定人数)同意对 swarm 的提议更新,例如节点的添加或移除。成员资格操作受到与状态复制相同的约束。

维持管理者的法定人数

如果群体失去了管理者的法定人数,群体将无法执行管理任务。如果你的群体有多个管理者,始终应保持超过两个。为了维持法定人数,大多数管理者必须可用。建议使用奇数个管理者,因为下一个偶数并不会使法定人数更容易保持。例如,无论你有3个还是4个管理者,你仍然只能失去1个管理者并维持法定人数。如果你有5个或6个管理者,你仍然只能失去两个。

即使一个群集失去了管理者的法定人数,现有工作节点上的群集任务仍会继续运行。然而,无法添加、更新或移除群集节点,也无法启动、停止、移动或更新新的或现有的任务。

请参阅 从失去法定人数中恢复 以获取 如果您确实失去了管理员的法定人数时的故障排除步骤。

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

在启动一个swarm时,你必须指定--advertise-addr标志来向swarm中的其他管理节点广播你的地址。更多信息,请参阅在swarm模式下运行Docker引擎。因为管理节点是基础设施的稳定组成部分,你应该为广播地址使用一个固定IP地址,以防止在机器重启时swarm变得不稳定。

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

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

添加管理节点以实现容错

您应该在群集中保持奇数个管理器以支持管理器节点故障。拥有奇数个管理器可以确保在网络分区期间,如果网络被分成两组,仲裁仍然有更高的机会保持可用以处理请求。如果您遇到超过两个网络分区,则无法保证保持仲裁。

Swarm SizeMajorityFault Tolerance
110
220
321
431
532
642
743
853
954

例如,在一个有5个节点的集群中,如果你失去了3个节点,你就没有达到法定人数。因此,在你恢复一个不可用的管理节点或使用灾难恢复命令恢复集群之前,你无法添加或删除节点。请参阅 从灾难中恢复

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

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

分发管理节点

除了保持奇数个管理节点外,在放置管理节点时还需注意数据中心拓扑。为了获得最佳的容错能力,应将管理节点分布在至少3个可用区中,以支持整个机器集或常见维护场景的故障。如果这些区域中的任何一个发生故障,群集应保持足够的管理节点来处理请求并重新平衡工作负载。

Swarm manager nodesRepartition (on 3 Availability zones)
31-1-1
52-2-1
73-2-2
93-3-3

运行仅管理节点

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

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

为了避免干扰管理节点的操作,您可以排空管理节点,使其无法作为工作节点使用:

$ docker node update --availability drain <NODE>

当你排空一个节点时,调度器会将该节点上运行的任何任务重新分配到群集中的其他可用工作节点。它还会阻止调度器将任务分配给该节点。

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

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

监控集群健康

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

从命令行运行 docker node inspect 来查询节点。 例如,查询节点作为管理器的可达性:

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

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

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

从这些命令中,我们可以看到manager1既作为管理者的状态是reachable,也作为工作者的状态是ready

一个unreachable健康状态意味着这个特定的管理节点无法从其他管理节点访问。在这种情况下,您需要采取措施来恢复无法访问的管理节点:

  • 重新启动守护进程,查看管理器是否恢复为可访问状态。
  • 重启机器。
  • 如果重启和重新启动都不起作用,您应该添加另一个管理节点或将一个工作节点提升为管理节点。您还需要使用docker node demote docker node rm 从管理集中干净地移除失败的节点条目。

或者,你也可以从管理节点使用 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空间应该是全局唯一的。

要干净地重新加入一个管理节点到集群:

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

有关将管理节点加入swarm的更多信息,请参阅 将节点加入集群

强制移除节点

在大多数情况下,你应该在从群集中移除节点之前使用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

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

备份集群

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

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

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

  2. 在备份数据之前,请在管理器上停止Docker,以确保在备份期间没有数据被更改。虽然可以在管理器运行时进行备份(“热”备份),但不建议这样做,因为在恢复时结果不太可预测。当管理器关闭时,其他节点会继续生成不属于此备份的群集数据。

    注意

    确保维持swarm管理员的法定人数。在管理员关闭期间,如果进一步丢失节点,您的swarm更容易失去法定人数。您运行的管理员数量是一个权衡。如果您经常关闭管理员进行备份,考虑运行一个五管理员swarm,这样在备份运行时,您可以再失去一个管理员,而不会中断您的服务。

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

  4. 重新启动管理器。

要恢复,请参阅 从备份恢复

从灾难中恢复

从备份恢复

在按照备份群集中描述的方法备份群集后,使用以下步骤将数据恢复到新的群集。

  1. 在目标主机上关闭Docker以恢复swarm。

  2. 移除新集群中/var/lib/docker/swarm目录的内容。

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

    注意

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

    在启用了自动锁定的群集情况下,解锁密钥也与旧群集相同,并且需要解锁密钥来恢复群集。

  4. 在新节点上启动Docker。如有必要,解锁swarm。使用以下命令重新初始化swarm,以便此节点不会尝试连接到旧swarm中的节点,这些节点可能已不存在。

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

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

  7. 添加管理节点和工作节点,以使您的新群集达到运行容量。

  8. 在新的群集上恢复您之前的备份方案。

从失去法定人数中恢复

Swarm 对故障具有弹性,并且可以从任何数量的临时节点故障(机器重启或崩溃后重启)或其他瞬时错误中恢复。然而,如果失去了法定人数,Swarm 无法自动恢复。现有工作节点上的任务会继续运行,但管理任务将无法进行,包括扩展或更新服务以及加入或移除 Swarm 中的节点。恢复的最佳方法是使缺失的管理节点重新上线。如果这不可能,请继续阅读以了解一些恢复 Swarm 的选项。

在由N个管理器组成的群体中,必须始终有大多数(即法定人数)的管理器节点可用。例如,在一个由五个管理器组成的群体中,至少需要有三个管理器正常运行并相互通信。换句话说,群体可以容忍最多(N-1)/2个永久性故障,超过这个数量,涉及群体管理的请求将无法处理。这些类型的故障包括数据损坏或硬件故障。

如果您失去了管理员的法定人数,您将无法管理集群。如果您失去了法定人数并尝试在集群上执行任何管理操作,将会发生错误:

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引擎将成为单节点群集的经理节点,该群集能够管理和运行服务。经理节点保留了所有关于服务和任务的先前信息,工作节点仍然是群集的一部分,服务仍在运行。你需要添加或重新添加经理节点以实现先前的任务分配,并确保你有足够的经理节点来维持高可用性并防止失去法定人数。

强制群集重新平衡

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

你可以使用--force-f标志与docker service update命令一起, 强制服务在可用的工作节点之间重新分配其任务。 这会导致服务任务重新启动。客户端应用程序可能会受到影响。 如果你已经配置了,你的服务会使用 滚动更新

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

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

另请参阅 docker service scaledocker service ps