运行时重新配置

etcd 增量式运行时重新配置支持

etcd 支持增量运行时重新配置,允许用户在运行时更新集群的成员。

只有当大多数集群成员正常运行时,才能处理重新配置请求。强烈建议在生产环境中始终将集群大小设置为大于两个。从两成员集群中移除一个成员是不安全的。两成员集群的大多数也是两个。如果在移除过程中发生故障,集群可能无法继续运行,并需要从多数故障中重启

为了更好地理解运行时重新配置的设计,请阅读运行时重新配置文档

重新配置用例

本节将介绍重新配置集群的一些常见原因。这些原因大多涉及添加或移除成员的组合,将在下面的集群重新配置操作部分进行解释。

循环或升级多台机器

如果由于计划维护(硬件升级、网络中断等)需要移动多个集群成员,建议一次修改一个成员。

移除领导者是安全的,但在选举过程中会有短暂的停机时间。如果集群包含超过 50MB 的 v2 数据,建议迁移成员的数据目录

更改集群大小

增加集群大小可以提高容错能力并提供更好的读取性能。由于客户端可以从任何成员读取数据,因此增加成员数量会增加整体序列化读取吞吐量。

减少集群大小可以提高集群的写入性能,但会降低弹性。写入集群的数据在被认为已提交之前会被复制到集群的大多数成员。减少集群大小会降低大多数成员的数量,从而使每次写入更快地被提交。

替换故障机器

如果机器因硬件故障、数据目录损坏或其他致命情况而失败,应尽快更换。已经失败但尚未移除的机器会对法定人数产生不利影响,并降低对额外故障的容忍度。

要替换机器,请按照从集群中移除成员的说明操作,然后在其位置添加新成员。如果集群包含超过 50MB 的数据,并且仍然可以访问,则建议迁移故障成员的数据目录

从多数故障中重启集群

如果集群的大多数成员丢失或所有节点的 IP 地址都已更改,则需要手动操作以安全恢复。恢复过程的基本步骤包括使用旧数据创建新集群,强制单个成员作为领导者,并最终使用运行时配置逐个向新集群添加新成员

从少数故障中恢复集群

如果某个特定成员丢失,则相当于替换一个故障的机器。步骤在替换故障机器中提到。

集群重新配置操作

考虑到这些用例,可以分别描述涉及的操作。

在进行任何更改之前,必须有大多数(法定人数)etcd 成员可用。这实际上是针对 etcd 的任何写操作的基本要求。

对集群的所有更改必须按顺序进行:

  • 要更新单个成员的 peerURLs,请执行更新操作
  • 要替换一个健康的单个成员,请先移除旧成员,然后添加新成员
  • 要从 3 个成员增加到 5 个成员,请执行两次添加操作
  • 要从 5 个成员减少到 3 个成员,请执行两次移除操作

所有这些示例都使用随 etcd 提供的 etcdctl 命令行工具。要在不使用 etcdctl 的情况下更改成员资格,请使用 v2 HTTP 成员 APIv3 gRPC 成员 API

更新成员

更新通告客户端 URL

要更新成员的通告客户端 URL,只需使用更新后的客户端 URL 标志 (--advertise-client-urls) 或环境变量 (ETCD_ADVERTISE_CLIENT_URLS) 重新启动该成员即可。重新启动的成员将自行发布更新后的 URL。错误更新的客户端 URL 不会影响 etcd 集群的健康状态。

更新通告对等 URL

要更新成员的通告对等 URL,首先通过成员命令显式更新它,然后重新启动该成员。由于更新对等 URL 会更改集群范围的配置并可能影响 etcd 集群的健康状态,因此需要额外的操作。

要更新通告对等 URL,首先找到目标成员的 ID。要使用 etcdctl 列出所有成员:

$ etcdctl member list
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792
924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793
a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791

此示例将 update a8266ecf031671f3 成员 ID 并将其 peerURLs 值更改为 http://10.0.1.10:2380

$ etcdctl member update a8266ecf031671f3 --peer-urls=http://10.0.1.10:2380
Updated member with ID a8266ecf031671f3 in cluster

移除成员

假设要移除的成员 ID 是 a8266ecf031671f3。使用 remove 命令执行移除:

$ etcdctl member remove a8266ecf031671f3
Removed member a8266ecf031671f3 from cluster

此时目标成员将停止运行,并在日志中打印出移除信息:

etcd: this member has been permanently removed from the cluster. Exiting.

移除领导者是安全的,但在选举新的领导者期间,集群将处于非活动状态。这段时间通常是选举超时加上投票过程的时间。

添加新成员

添加成员是一个两步过程:

  • 通过 HTTP 成员 APIgRPC 成员 APIetcdctl member add 命令将新成员添加到集群中。
  • 使用新的集群配置启动新成员,包括更新后的成员列表(现有成员 + 新成员)。

etcdctl 通过指定成员的 名称通告对等 URL 将新成员添加到集群中:

$ etcdctl member add infra3 --peer-urls=http://10.0.1.13:2380
added member 9bf1b35fc7761a23 to cluster

ETCD_NAME="infra3"
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_STATE=existing

etcdctl 已通知集群关于新成员的信息,并打印出成功启动所需的所有环境变量。现在使用相关标志启动新的 etcd 进程:

$ export ETCD_NAME="infra3"
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
$ export ETCD_INITIAL_CLUSTER_STATE=existing
$ etcd --listen-client-urls http://10.0.1.13:2379 --advertise-client-urls http://10.0.1.13:2379 --listen-peer-urls http://10.0.1.13:2380 --initial-advertise-peer-urls http://10.0.1.13:2380 --data-dir %data_dir%

新成员将成为集群的一部分,并立即开始追赶集群中的其他成员。

如果要添加多个成员,最佳实践是每次只配置一个成员,并在添加更多新成员之前验证其是否正确启动。如果向单节点集群中添加新成员,在新成员启动之前,集群无法取得进展,因为它需要两个成员作为多数来达成共识。这种行为仅发生在etcdctl member add通知集群新成员和新成员成功连接到现有成员之间的时间段内。

将新成员作为学习者添加

从 v3.4 开始,etcd 支持将新成员作为学习者/非投票成员添加。动机和设计可以在设计文档中找到。为了使添加新成员的过程更安全,并减少添加新成员时的集群停机时间,建议将新成员作为学习者添加到集群中,直到它赶上为止。这可以描述为一个三步过程:

  • 通过gRPC 成员 APIetcdctl member add --learner命令将新成员作为学习者添加。

  • 使用新的集群配置(包括更新后的成员列表(现有成员+新成员))启动新成员。此步骤与之前完全相同。

  • 通过gRPC 成员 APIetcdctl member promote命令将新添加的学习者提升为投票成员。etcd 服务器会验证提升请求以确保其操作安全。只有当其 Raft 日志追上领导者的日志后,学习者才能被提升为投票成员。如果学习者成员尚未追上领导者的 Raft 日志,则成员提升请求将失败(有关详细信息,请参阅提升成员时的错误情况部分)。在这种情况下,用户应等待并稍后重试。

在 v3.4 中,etcd 服务器限制了集群可以拥有的学习者数量为一个。主要考虑因素是限制由于从领导者传播数据到学习者而给领导者带来的额外工作负载。

使用带有--learner标志的etcdctl member add命令将新成员作为学习者添加到集群中。

$ etcdctl member add infra3 --peer-urls=http://10.0.1.13:2380 --learner
Member 9bf1b35fc7761a23 added to cluster a7ef944b95711739

ETCD_NAME="infra3"
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_STATE=existing

在为新添加的学习者成员启动新的 etcd 进程后,使用etcdctl member promote命令将学习者提升为投票成员。

$ etcdctl member promote 9bf1b35fc7761a23
Member 9e29bbaa45d74461 promoted in cluster a7ef944b95711739

添加成员时的错误情况

在以下情况下,新主机未包含在枚举节点列表中。如果是新集群,则必须将该节点添加到初始集群成员列表中。

$ etcd --name infra3 \
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
  --initial-cluster-state existing
etcdserver: assign ids error: the member count is unequal
exit 1

在这种情况下,提供一个不同于用于加入集群的地址(10.0.1.13:2380)的新地址(10.0.1.14:2380):

$ etcd --name infra4 \
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra4=http://10.0.1.14:2380 \
  --initial-cluster-state existing
etcdserver: assign ids error: unmatched member while checking PeerURLs
exit 1

如果 etcd 使用已移除成员的数据目录启动,并且连接到集群中的任何活动成员,etcd 将自动退出:

$ etcd
etcd: this member has been permanently removed from the cluster. Exiting.
exit 1

添加学习者成员时的错误情况

如果集群已经有一个学习者(v3.4),则不能将学习者添加到集群中。

$ etcdctl member add infra4 --peer-urls=http://10.0.1.14:2380 --learner
Error: etcdserver: too many learner members in cluster

提升学习者成员时的错误情况

只有当学习者与领导者同步时,才能将其提升为投票成员。

$ etcdctl member promote 9bf1b35fc7761a23
Error: etcdserver: can only promote a learner member which is in sync with leader

提升非学习者的成员将失败。

$ etcdctl member promote 9bf1b35fc7761a23
Error: etcdserver: can only promote a learner member

提升不存在于集群中的成员将失败。

$ etcdctl member promote 12345abcde
Error: etcdserver: member not found

严格重新配置检查模式 (-strict-reconfig-check)

如上所述,添加新成员的最佳实践是一次配置一个成员,并在添加更多新成员之前验证其是否正确启动。这种逐步的方法非常重要,因为如果新添加的成员配置不正确(例如对等 URL 不正确),集群可能会失去法定人数。由于新添加的成员即使无法从其他现有成员访问也会被计入法定人数中,因此可能会发生法定人数丢失的情况。此外,如果存在连接问题或操作问题,也可能导致法定人数丢失。

为了避免这个问题,etcd 提供了一个选项 -strict-reconfig-check。如果将此选项传递给 etcd,则当启动的成员数量少于重新配置后的集群的法定人数时,etcd 将拒绝重新配置请求。

默认情况下,该选项是启用的。


最后更新于 2025 年 6 月 3 日:递归地将 v3.6 的内容复制到 v3.7(a90b2a6)