原文地址:the runtime configuration design
运行时重新配置是分布式系统中最难,最容易出错的部分,尤其是在基于共识(像etcd)的系统中。
阅读并学习关于etcd的运行时重新配置命令设计和如何追溯这些错误.
两阶段配置更新保证集群安全
在etcd中,每一次运行时重新配置安全的原因是由于两阶段更新。例如,添加一个成员,首先将新配置通知集群后启动新的成员。
- 阶段一 通知集群关于新的配置
添加一个成员到etcd集群中,通过API调用请求将一个新成员添加到集群中。这是将新的成员添加到集群中唯一的方法。当集群同意配置的更新后将返回API的调用。 - 阶段二 启动一个新的成员
将一个新成员加入到存在的集群中,指定正确的initial-cluster
和设置initial-cluster-state
为existing
.当成员启动后,它首先联系已存在的集群并验证当前集群配置是否和期望的initial-cluster
匹配。当一个新的成员成功启动,集群将获得期望的配置。
用户将过程分为两个阶段需要清楚了解集群成员关系的变化。实际上,这为用户提供了更大的灵活性,并使事情更容易。例如,如果试图添加一个与集群中现有的成员Id相同的新成员到集群中,操作将会立即失败由于阶段一并没有影响到运行中的集群。提供了类似的保护阻止通过错误操作添加新的成员。如果一个新的etcd成员试图在集群接受配置信息更新之前加入集群,操作将不会被集群接受。
如果没有围绕集群成员关系的显式工作流,集群将会容易受到意料之外的集群成员关系变化的影响。例如,如果etcd在一个初始化的系统如systemd中运行,etcd将会通过成员关系API在重新启动之后被移除,并试图在启动后重新加入。这个循环将会在每次通过API成员移除并将系统设置为失败后重新启动etcd时继续,这是预料之外的。
我们希望运行时重新进行配置是不常见的操作。我们决定保持为显式的由用户驱动来确保配置安全,保持集群平稳运行在显式的控制下。
永久性的丢失要求新的集群
如果一个集群永久丢失一些主要的集群成员,需要从原始的数据文件夹启动一个新的集群恢复先前的状态。
完全有可能从已存在的集群中强制删除一个失败的成员并恢复。然而,我们决定不支持此方法因为他绕过了常规的共识提交阶段,这是不安全的。如果成员移除一个没有实际失败的成员或者是同一个集群中的不同成员,etcd将会最终得到具有相同集群Id的分散集群。这是非常危险的而且很难修复。
通过正常的部署,永久性丢失的可能性非常的小。但是这是一个严重的问题值得特别注意。我们强烈建议阅读灾难恢复文档并且在将etcd部署到生产环境之前做充足的准备。
不要在运行时重新配置中使用公共的发现服务
公共发现服务应该只在启动一个集群的时候使用。将一个成员加入已存在的集群,使用运行时配置API.
发现服务被设计用来在云服务环境中启动一个在所有的成员无法提前知道Ip地址时的etcd集群。在成功启动一个集群时,所有的成员将会知道Ip地址。典型的,发现服务奖不再被需要。
看起来使用公共的发现服务进行运行时重新配置是一个便利的方法,毕竟所有的发现服务含有所有的集群配置信息。然而依赖公共发现服务将带来问题:
- 将会引进外部独立性到集群的整个生命周期,不只是启动时间。如果集群和公共发现服务之间存在网络问题,则群集将因此受到影响。
- 公共发现服务必须在集群的生命周期内反映正确的运行时配置,将需要提供安全机制避免坏的行为,而这是困难的。
- 公共发现服务需要保持数万个集群的配置,而我们的公共发现服务很难承受这种负载。
为了使发现服务支持运行时配置,最好的选择是建立一个私有的发现服务。