运行时重新配置的设计

etcd 运行时重新配置命令的设计

运行时重新配置是分布式系统中最复杂且最容易出错的功能之一,尤其是在基于共识的系统如 etcd 中。

继续阅读以了解 etcd 的运行时重新配置命令的设计以及我们如何解决这些问题。

两阶段配置变更确保集群安全

在 etcd 中,出于安全考虑,每次运行时重新配置都必须经过两个阶段。例如,要添加一个成员,首先通知集群新的配置,然后启动新成员。

第一阶段 - 通知集群新的配置

要将一个成员添加到 etcd 集群中,调用 API 请求将新成员添加到集群中。这是将新成员添加到现有集群中的唯一方法。当集群同意配置变更时,API 调用返回。

第二阶段 - 启动新成员

要将新的 etcd 成员加入现有集群,指定正确的 initial-cluster 并将 initial-cluster-state 设置为 existing。当成员启动时,它会首先联系现有集群并验证当前集群配置是否与 initial-cluster 中指定的预期配置匹配。当新成员成功启动后,集群将达到预期的配置。

通过将过程分为两个独立的阶段,用户被迫明确地处理集群成员变更。这实际上给了用户更多的灵活性,并使事情更容易理解。例如,如果尝试在 etcd 集群中添加一个与现有成员 ID 相同的新成员,该操作将在第一阶段立即失败,而不会影响正在运行的集群。类似的保护措施也防止了意外添加新成员。如果新的 etcd 成员在集群接受配置变更之前尝试加入集群,它将不被集群接受。

如果没有明确的工作流程来管理集群成员,etcd 将容易受到意外的集群成员变更的影响。例如,如果 etcd 在 systemd 等初始化系统下运行,在通过成员 API 移除成员后,etcd 会被重启并在启动时尝试重新加入集群。如果设置了 systemd 在 etcd 失败后重启 etcd,这个循环会在每次通过 API 移除成员时继续,这是意料之外的情况。

我们预计运行时重新配置是一个不频繁的操作。我们决定保持其明确性和用户驱动性,以确保配置安全,并在明确控制下保持集群始终平稳运行。

永久性失去多数成员需要新建集群

如果集群永久性失去了大多数成员,则需要从旧的数据目录启动一个新的集群以恢复先前的状态。

完全可以通过强制移除现有集群中的失败成员来进行恢复。然而,我们决定不支持这种方法,因为它绕过了正常的共识提交阶段,这是不安全的。如果要移除的成员实际上并没有死亡,或者通过同一集群中的不同成员强制移除,etcd 最终可能会出现具有相同集群 ID 的分歧集群。这种情况非常危险,且难以调试和修复。

在正确的部署下,永久性失去多数成员的可能性非常低。但这是一个严重到值得特别关注的问题。我们强烈建议阅读灾难恢复文档,并在将 etcd 投入生产之前准备好应对永久性失去多数成员的情况。

不要在运行时重新配置中使用公共发现服务

公共发现服务仅应用于集群的引导启动。要将成员加入现有集群,请使用运行时重新配置 API。

发现服务旨在在云环境中引导 etcd 集群,当所有成员的 IP 地址事先未知时。成功引导集群后,所有成员的 IP 地址就已知了。从技术上讲,发现服务不再需要。

似乎使用公共发现服务是一种方便进行运行时重新配置的方法,毕竟发现服务已经包含了所有集群配置信息。然而,依赖公共发现服务会带来一些麻烦:

  1. 它在整个集群生命周期内引入了外部依赖,而不仅仅是引导阶段。如果集群与公共发现服务之间出现网络问题,集群将会受到影响。

  2. 公共发现服务必须在集群生命周期内反映正确的运行时配置。它必须提供安全机制以避免恶意行为,这非常困难。

  3. 公共发现服务必须保存数万个集群配置。我们的公共发现服务后端尚未准备好应对这种工作负载。

要有一个支持运行时重新配置的发现服务,最佳选择是构建一个私有的发现服务。


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