这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。
宣布 etcd 3.4
etcd 3.4 专注于稳定性、性能和易用性,具有预投票和非投票成员等功能,并改进了存储后端和客户端负载均衡器。
有关更改的完整列表,请参阅 CHANGELOG。
更好的存储后端
etcd v3.4 包括针对大规模 Kubernetes 工作负载的许多性能改进。
特别是,即使没有写入(例如 “read-only range request ... took too long to execute”
),etcd 在大量并发读取事务时也会遇到性能问题。以前,即使没有待写入操作,存储后端提交操作也会阻塞传入的读取事务。现在,提交 不会阻塞读取,从而提高了长期运行的读取事务的性能。
我们进一步使 后端读取事务完全并发。以前,正在进行的长期读取事务会阻止写入和即将到来的读取。通过此更改,在存在长期读取的情况下,写入吞吐量提高了 70%,P99 写入延迟降低了 90%。我们还使用此更改在 GCE 上运行了 Kubernetes 5000 节点可扩展性测试,并观察到类似的改进。例如,在测试的开始阶段,有很多长期运行的“LIST pods”时,“POST clusterrolebindings”的 P99 延迟 降低了 97.4%。
租约存储也进行了更多改进。我们通过更高效地存储租约对象来增强 租约过期/撤销性能,并通过当前的租约授予/撤销操作使 租约查找操作非阻塞。etcd v3.4 引入了 租约检查点 作为一项实验性功能,以通过共识持久化剩余的生存时间值。这确保了短生存时间的租约对象在领导者选举后不会自动续订。这也防止了当生存时间值相对较大时(例如,在 Kubernetes 用例中,1 小时的 TTL 永远不会过期)租约对象堆积。
改进的 Raft 投票过程
etcd 服务器实现了用于数据复制的 Raft 共识算法。Raft 是一种基于领导者的协议。数据从领导者复制到跟随者;跟随者将提议转发给领导者,领导者决定提交什么或不提交什么。一旦集群法定人数同意,领导者就会持久化并复制一个条目。集群成员选出一个领导者,所有其他成员都成为跟随者。当选的领导者定期向其跟随者发送心跳信号以保持其领导地位,并期望每个跟随者的响应以跟踪其进度。
在其最简单的形式中,当 Raft 领导者收到具有更高任期的消息时,会降级为跟随者,而无需进行任何进一步的集群范围内的运行状况检查。此行为可能会影响整个集群的可用性。
例如,一个不稳定的(或重新加入的)成员进进出出,并开始竞选。此成员最终具有更高的任期,忽略所有具有较低任期的传入消息,并发送具有更高任期的消息。当领导者收到此具有更高任期的消息时,它会恢复为跟随者。
当存在网络分区时,这种情况会更具破坏性。每当分区节点重新获得其连接时,它可能会触发领导者重新选举。为了解决此问题,etcd Raft 引入了一个新的节点状态预候选者,具有 预投票功能。预候选者首先询问其他服务器它是否足够新以获得投票。只有当它能从大多数人那里获得投票时,它才会增加其任期并开始选举。这个额外的阶段通常可以提高领导者选举的鲁棒性。并帮助领导者保持稳定,只要它与它的对等点的法定人数保持连接。
类似地,当重新启动的节点没有及时收到领导者心跳信号时(例如,由于网络速度慢),也会影响 etcd 的可用性,这会触发领导者选举。以前,etcd 会在服务器启动时快速转发选举节拍,只留下一个节拍进行领导者选举。例如,当选举超时为 1 秒时,跟随者仅等待 100 毫秒进行领导者联系,然后开始选举。通过不必等待选举超时来加速初始服务器启动(例如,在 100 毫秒而不是 1 秒内触发选举)。提前选举节拍也适用于具有更大选举超时的跨数据中心部署。但是,在许多情况下,可用性比初始领导者选举的速度更为关键。为了确保重新加入节点具有更好的可用性,etcd 现在 调整了选举节拍,使其剩余的节拍多于一个,从而使领导者有更多时间来防止破坏性重启。
Raft 非投票成员,学习者
成员资格重新配置的挑战在于,它通常会导致法定人数大小的变化,这很容易导致集群不可用。即使它不改变法定人数,成员资格变更的集群也更有可能遇到其他潜在问题。为了提高重新配置的可靠性和信心,在 etcd 3.4 版本中引入了一个新角色 - 学习者。
一个新的 etcd 成员加入集群时没有初始数据,请求来自领导者的所有历史更新,直到它赶上领导者的日志。这意味着领导者的网络更有可能过载,阻止或丢弃领导者向跟随者发送的心跳信号。在这种情况下,跟随者可能会遇到选举超时并开始新的领导者选举。也就是说,拥有新成员的集群更容易受到领导者选举的影响。领导者选举和随后向新成员的更新传播都容易导致集群不可用时期(请参见图 1)。
最糟糕的情况是配置错误的成员资格添加。etcd 中的成员资格重新配置是一个两步过程:带有对等 URL 的 etcdctl member add
和启动一个新的 etcd 来加入集群。也就是说,无论对等 URL 值是否无效,都将应用 member add
命令。如果第一步是应用无效的 URL 并更改法定人数的大小,则直到新节点连接之前,集群可能已经失去了法定人数。由于具有无效 URL 的节点永远不会在线并且没有领导者,因此不可能恢复成员资格更改(请参见图 2)。
当存在分区节点时,这种情况会变得更加复杂(有关更多信息,请参见 设计文档)。
为了解决这种故障模式,etcd 引入了一个 新节点状态“学习者”,该状态作为非投票成员加入集群,直到它赶上领导者的日志。这意味着学习者仍然会收到来自领导者的所有更新,但它不计入法定人数,领导者使用法定人数来评估对等点的活跃度。学习者仅充当备用节点,直到被提升。对法定人数的这种宽松要求在成员资格重新配置和操作安全期间提供了更好的可用性(请参见图 3)。
我们将进一步提高学习者的鲁棒性,并探索自动提升机制,以实现更轻松、更可靠的操作。请阅读我们的 学习者设计文档 和 运行时配置文档,以获取用户指南。
新的客户端负载均衡器
etcd 旨在容忍各种系统和网络故障。通过设计,即使一个节点发生故障,集群也会“看起来”正常工作,方法是提供多个服务器的一个逻辑集群视图。但是,这不能保证客户端的活跃性。因此,etcd 客户端实现了一组不同的复杂协议,以保证其在故障条件下的正确性和高可用性。
从历史上看,etcd 客户端负载均衡器严重依赖旧的 gRPC 接口:每个 gRPC 依赖项升级都会破坏客户端行为。大部分开发和调试工作都致力于修复这些客户端行为更改。因此,它的实现变得过于复杂,对服务器连接性做出了错误的假设。主要目标是 简化 etcd v3.4 客户端中的负载均衡器故障转移逻辑;每当客户端与当前端点断开连接时,简单地循环到下一个端点,而不是维护可能过时的不健康端点列表。它不假定端点状态。因此,不再需要更复杂的状态跟踪。
此外,新客户端现在创建自己的凭据捆绑包以 修复针对安全端点的负载均衡器故障转移。这解决了 长达一年的错误,其中 kube-apiserver 在第一个 etcd 服务器不可用时会失去与 etcd 集群的连接。
有关更多信息,请参阅 客户端负载均衡器设计文档。