本文转载自微信公众号「武培轩」,作者武培轩。转载本文请联系武培轩公众号。
etcd 简介
etcd 是兼具一致性和高可用性的键值数据库,可用于服务发现以及配置中心。ETCD 采用 raft 一致性算法,基于 Go 语言实现。可以作为保存 Kubernetes 所有集群数据的后台数据库,在整个云原生中发挥极其重要的作用。
ectd 版本: v3.4 etcd 文档地址: https://etcd.io/docs/v3.4/
etcd 在 kubernetes 的架构
etcd存储着k8s所有的元数据
etcd 中存储着 k8s 的所有的元数据,至关重要,再次,我们就揭开 etcd 的最佳实践。
etcd 特点
- 扁平化二进制键值空间
- 保留事件历史记录,直到压缩为止
- 访问旧版本 keys
- 用户自定义 key 版本历史压缩
- 支持范围查询
- 带 limit 参数的分页支持
- 支持多个范围查询的一致性保证
- 通过租约替换 TTL 键
- 更高效以及低成本的 keepalive
- 为不同的 TTL key 配置配置相同逻辑的租约
- 通过多对象 Txn 替换 CAS/CAD
- 更加强大和灵活
- 支持多范围高效 watch
- RPC API 支持完整的 API 集
- 比 JSON/HTTP 更有效
- 额外的 TXN/租约支持
- HTTP API 支持 API 子集。
- 用户更容易尝试 etcd
- 用户更易于编写简单的 etcd 应用程序
etcd 运行建议
- 运行的 etcd 集群个数成员为奇数。
- etcd 是一个 leader-based 分布式系统。确保主节点定期向所有从节点发送心跳,以保持集群稳定。
- 确保资源充足。
- 集群的性能和稳定性对网络和磁盘 IO 非常敏感。任何资源匮乏都会导致心跳超时,从而导致集群的不稳定。不稳定的情况表明没有选出任何主节点。在这种情况下,集群不能对其当前状态进行任何更改,这意味着不能调度新的 pod。
- 保持稳定的 etcd 集群对 Kubernetes 集群的稳定性至关重要。因此,请在专用机器或隔离环境上运行 etcd 集群,以满足所需资源需求。
- 在生产中运行的 etcd 的最低推荐版本是 3.2.10+
- 硬件建议:https://etcd.io/docs/v3.4/op-guide/hardware/
etcd 架构实践
为了性能和高可用性,在生产中将以多节点集群的方式运行 etcd,并且定期备份。建议在生产中使用五个成员的集群。有关该内容的更多信息,请参阅https://etcd.io/docs/v3.4/faq/#what-is-failure-tolerance。
可以通过静态成员信息或动态发现的方式配置 etcd 集群。有关集群的详细信息,请参阅https://etcd.io/docs/v3.4/op-guide/clustering/。
集群规模 | 半数节点 | 容错节点 |
---|---|---|
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |
8 | 5 | 3 |
9 | 5 | 4 |
etcd 调优指南
本次调优针对于 etcd 本身的参数调优:
1.时间相关参数
在大型 etcd 集群中,由于网络的复杂性,etcd 本身的分布式共识协议将受到影响,其主要依赖于两个时间参数:
第一个参数称为 Heartbeat Interval。领导者将以此频率通知关注者它仍然是领导者。为了获得最佳实践,应围绕成员之间的往返时间设置参数。默认情况下,etcd 使用 100ms 心跳间隔。
第二个参数是 Election Timeout。此超时时间是指跟随者节点在尝试成为领导者之前要等待多长时间而不会听到心跳信号。默认情况下,etcd 使用 1000ms 选举超时。
调整这些值是一个权衡。建议心跳间隔的值应介于成员之间的平均往返时间(RTT)的最大值附近,通常约为往返时间的 0.5-1.5 倍。如果心跳间隔太短,etcd 将发送不必要的消息,从而增加 CPU 和网络资源的使用。另一方面,过高的心跳间隔会导致较高的选举超时时间。较高的选举超时时间需要更长的时间才能检测到领导者失败。测量往返时间(RTT)的最简单方法是使用 PING 实用程序。
应该根据心跳间隔和成员之间的平均往返时间来设置选举超时。选举超时时间必须至少是往返时间的 10 倍,这样才能解决网络中的差异。例如,如果成员之间的往返时间为 10 毫秒,则选举超时应至少为 100 毫秒。
选举超时上限为 50000ms(50s),仅在部署全球分布的 etcd 集群时才应使用。
一个集群中所有成员的心跳间隔和选举超时值应相同。为 etcd 成员设置不同的值可能会破坏集群的稳定性。
以上参数可以通过命令进行调整:
- # Command line arguments:
- $ etcd --heartbeat-interval=100 --election-timeout=500
- # Environment variables:
- $ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
2.快照
etcd 将所有关键更改附加到日志文件。此日志将永远增长,并且是对键所做的每次更改的完整线性历史记录。完整的历史记录适用于轻度使用的集群,但是频繁使用的集群将携带大量日志。
为了避免有大量日志,etcd 会进行定期快照。这些快照为 etcd 提供了一种通过保存系统当前状态并删除旧日志来压缩日志的方法。
使用 V2 后端创建快照可能会很昂贵,因此仅在对 etcd 进行给定数量的更改后才能创建快照。默认情况下,每 10,000 次更改后将创建快照。如果 etcd 的内存使用量和磁盘使用量过高,请尝试通过在命令行上设置以下内容来降低快照阈值:
- # Command line arguments:
- $ etcd --snapshot-count=5000
- # Environment variables:
- $ ETCD_SNAPSHOT_COUNT=5000 etcd
3.磁盘
etcd 集群对磁盘延迟非常敏感。由于 etcd 必须将建议持久保存到其日志中,因此其他进程的磁盘活动可能会导致较长的 fsync 延迟。etcd 可能会错过心跳,从而导致请求超时和临时领导者丢失。当给予较高的磁盘优先级时,etcd 服务器有时可以与这些进程一起稳定运行。
在 Linux 上,可以使用以下命令配置 etcd 的磁盘优先级 ionice:
- # best effort, highest priority
- $ sudo ionice -c2 -n0 -p `pgrep etcd`
4.网络 如果 etcd 领导者处理大量并发的客户端请求,由于网络拥塞,可能会延迟处理跟随者对等体请求。这表现为在跟随者节点上的发送缓冲区错误消息:
- dropped MsgProp to 247ae21ff9436b2d since streamMsg's sending buffer is full
- dropped MsgAppResp to 247ae21ff9436b2d since streamMsg's sending buffer is full
通过将 etcd 的对等流量优先于其客户端流量,可以解决这些错误。在 Linux 上,可以使用流量控制机制来确定对等流量的优先级:
- tc qdisc add dev eth0 root handle 1: prio bands 3
- tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1
5.内存
etcd 默认的存储大小限制为 2GB,可使用--quota-backend-bytes 标志进行配置。建议在正常环境下使用 8GB 的最大大小,如果配置的值超过该值,etcd 会在启动时发出警告。
6.请求体
etcd 被设计用于元数据的小键值对的处理。较大的请求将工作的同时,可能会增加其他请求的延迟。默认情况下,任何请求的最大大小为 1.5 MiB。这个限制可以通过--max-request-bytesetcd 服务器的标志来配置。
7.key 的历史记录压缩 ETCD 会存储多版本数据,随着写入的主键增加,历史版本将会越来越多,并且 ETCD 默认不会自动清理历史数据。数据达到 --quota-backend-bytes 设置的配额值时就无法写入数据,必须要压缩并清理历史数据才能继续写入。
- --auto-compaction-mode
- --auto-compaction-retention
所以,为了避免配额空间耗尽的问题,在创建集群时候建议默认开启历史版本清理 功能。
3.3.0 之前的版本,只能按周期 periodic 来压缩。比如设置 --auto-compaction-retention=72h,那么就会每 72 小时进行一次数据压缩。
3.3.0 之后的版本,可以通过 --auto-compaction-mode 设置压缩模式,可以选择 revision 或者 periodic 来压缩数据,默认为 periodic。
etcd 备份
所有 Kubernetes 对象都存储在 etcd 上。定期备份 etcd 集群数据对于在灾难场景(例如丢失所有主节点)下恢复 Kubernetes 集群非常重要。快照文件包含所有 Kubernetes 状态和关键信息。为了保证敏感的 Kubernetes 数据的安全,可以对快照文件进行加密。备份 etcd 集群可以通过两种方式完成: etcd 内置快照和卷快照。
1.内置快照
etcd 支持内置快照,因此备份 etcd 集群很容易。快照可以从使用 etcdctl snapshot save 命令的活动成员中获取,也可以通过从 etcd 数据目录复制 member/snap/db 文件,该 etcd 数据目录目前没有被 etcd 进程使用。获取快照通常不会影响成员的性能。
下面是一个示例,用于获取 $ENDPOINT 所提供的键空间的快照到文件 snapshotdb:
- ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshotdb
- # exit 0
- # verify the snapshot
- ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshotdb
- +----------+----------+------------+------------+
- | HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
- +----------+----------+------------+------------+
- | fe01cf57 | 10 | 7 | 2.1 MB |
- +----------+----------+------------+------------+
2.卷快照
如果 etcd 运行在支持备份的存储卷(如 Amazon Elastic Block 存储)上,则可以通过获取存储卷的快照来备份 etcd 数据。
etcd 恢复
etcd 支持从 major.minor 或其他不同 patch 版本的 etcd 进程中获取的快照进行恢复。还原操作用于恢复失败的集群的数据。
在启动还原操作之前,必须有一个快照文件。它可以是来自以前备份操作的快照文件,也可以是来自剩余数据目录的快照文件。有关从快照文件还原集群的详细信息和示例,请参阅 etcd 灾难恢复文档。
如果还原的集群的访问 URL 与前一个集群不同,则必须相应地重新配置 Kubernetes API 服务器。在本例中,使用参数 --etcd-servers=$NEW_ETCD_CLUSTER 而不是参数--etcd-servers=$OLD_ETCD_CLUSTER 重新启动 Kubernetes API 服务器。用相应的 IP 地址替换 $NEW_ETCD_CLUSTER 和 $OLD_ETCD_CLUSTER。如果在 etcd 集群前面使用负载平衡,则可能需要更新负载均衡器。
如果大多数 etcd 成员永久失败,则认为 etcd 集群失败。在这种情况下,Kubernetes 不能对其当前状态进行任何更改。虽然已调度的 pod 可能继续运行,但新的 pod 无法调度。在这种情况下,恢复 etcd 集群并可能需要重新配置 Kubernetes API 服务器以修复问题。
注意:
如果集群中正在运行任何 API 服务器,则不应尝试还原 etcd 的实例。相反,请按照以下步骤还原 etcd:
- 停止 所有 kube-apiserver 实例
- 在所有 etcd 实例中恢复状态
- 重启所有 kube-apiserver 实例
我们还建议重启所有组件(例如 kube-scheduler、kube-controller-manager、kubelet),以确保它们不会 依赖一些过时的数据。请注意,实际中还原会花费一些时间。在还原过程中,关键组件将丢失领导锁并自行重启。
总结
etcd 为 kubernetes 的存储基石,想用好 k8s,必须熟悉 etcd,我们才更有信心,以及更好的服务业务,提供更稳定的技术服务。
参考文档
https://etcd.io/docs/
https://kubernetes.io/zh/docs/tasks/administer-cluster/configure-upgrade-etcd/