原文地址:runtime reconfiguration
etcd带有增量运行时重新配置的支持。允许我们在集群运行的时候更新集群成员关系。
仅当大多数集群成员都在运行时,才能处理重新配置请求,强烈建议在生产环境中集群的大小应该始终大于2。从两个成员的集群中移除一个成员是不安全的。两个成员的集群中大多数成员始终是2,如果在删除过程中出现故障,集群将很难继续运行需要重新从主要成员失败中重新启动集群
为了更好的理解运行时重新配置设计,请阅读运行时重新配置设计

重新配置使用案例


本节将介绍一些重新配置集群的常见原因。 其中大多数原因仅涉及添加或删除成员的组合,群集重新配置操作下将对此进行说明。

循环或更新多机

如果由于计划的维护(硬件升级,网络停机等)而需要移动多个群集成员,建议一次修改一个成员。
移除领导者是安全的,但是在选举过程中会出现短暂的停机时间。 如果群集包含的版本为v2的数据超过50MB,则建议迁移成员的数据目录。

改变集群大小

增加群集大小可以增强容错能力并提供更好的读取性能,由于客户端可以从任何成员读取,因此增加成员数量将增加整体序列化读取吞吐量。
减小群集大小可以提高群集的写入性能,但需要权衡降低弹性。写入集群之前,会将其复制到集群的大多数成员。 减小群集大小可减少大多数操作,并且每次写入的提交速度都会更快。

替换一个失败的主机

如果计算机由于硬件故障,数据目录损坏或其他致命情况而失败,应该尽快更换它。 发生故障但尚未移除的主机会对集群产生不利影响,并降低对其他故障的容忍度。
要更换主机,请按照说明从群集中删除成员,然后在其位置添加新成员。如果群集拥有的空间超过50MB,则建议迁移仍可访问的失败成员的数据目录。

多数主机失败后重启集群

如果大多数群集丢失或所有节点的IP地址都已更改,则必须采取手动操作才能安全恢复。恢复过程中的基本步骤包括使用旧数据创建新集群,强制单个成员充当领导者,最后使用运行时配置一次将新成员添加到该新集群中。

集群重新配置操作

考虑到这些用例,可以针对每个用例进行描述。进行任何更改之前,必须有多数etcd成员可以获取。 对于对etcd的任何类型的写入,这基本上是相同的要求。
必须按顺序完成对集群的所有更改:

  • 要更新单个成员节点URL,请执行更新操作.
  • 要替换正常的单个成员,请删除旧成员,然后添加新成员.
  • 要从3名增加到5名成员,请执行两次添加操作
  • 成员数量要从5减少到3,请执行两次删除操作

这些示例都使用etcd附带的etcdctl命令行工具进行。如果不使用etcdctl工具改变成员关系,使用v2HTTP成员API或者v3gRPC成员API

更新一个成员

更新广播客户端URLs
要更新成员的发布客户端URL,只需使用已更新的客户端URL参数--advertise-client-urls或环境变量ETCD_ADVERTISE_CLIENT_URLS重新启动该成员。重新启动的成员将自行发布更新的URL。 错误更新的客户端URL不会影响etcd群集的运行状况。
更新广播节点URLs
要更新成员的广播节点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

本示例将更新a8266ecf031671f3成员ID,并将其节点URLs值更改为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成员API,或者是etcdctl member add命令添加一个新的成员到集群中。
  • 通过新的集群配置启动新的成员,新的集群配置包括被更新的成员(已存在的成员+新成员).

etcdctl添加一个新的成员到集群中通过具体的成员名字广播节点URLs:

$ 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%

新成员将作为集群的一部分运行,并立即开始同步集群的其余部分。
如果添加多个成员,最佳做法是一次配置一个成员,并在添加更多新成员之前验证它是否正确启动.如果将新成员添加到1节点群集中,则群集无法在新成员启动之前取得进展,因为它需要两个成员作为多数才能达成共识。仅在etcdctl``member add通知集群有关新成员的时间和新成员成功建立与现有成员的连接的时间之间,才发生此行为。
添加一个新的成员为领导者
从v3.4开始,etcd支持将新成员添加为领导者/非投票成员。激励和设计可以在设计文档中找到。为了使添加新成员的过程更安全,并减少添加新成员时的集群停机时间.建议将新成员作为学习者添加到集群中,直到同步完成为止。 这可以描述为三步过程:

  • 通过gRPC成员API或者etcdctl member add --learner命令将新成员添加为学习者。
  • 通过新的集群配置启动新的成员,新的集群配置包括被更新的成员(已存在的成员+新成员)和之前的步骤相同.
  • 通过gRPC成员APIetcdctl member promote命令将新添加的学习者提升为有投票权的成员。etcd服务器验证升级请求以确保其运行安全.只有在其Raft日志达到领导者的水平之后,才能将学习者提升为有投票权的成员。如果学习者成员未赶上领导者的Raft日志,则成员升级请求将失败(见提升成员错误案例部分获取更多细节).这种情况下,用户应该等待并重试。

在v3.4中,etcd服务器将群集可以拥有的学习者数量限制为一个。 主要考虑因素是限制由于领导者向学习者传播数据而导致的领导者额外工作量。
使用etcdctl member add和参数--learner添加一个新成员作为学习者到集群中.

$ 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文档翻译      etcd

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!