Etcd 性能优化

etcd特点

  1. 扁平化二进制键值空间
  2. 保留事件历史记录,直到压缩为止
    • 访问旧版本keys
    • 用户自定义key版本历史压缩
  3. 支持范围查询
    • 带limit参数的分页支持
    • 支持多个范围查询的一致性保证
  4. 通过租约替换TTL键
    • 更高效以及低成本的keepalive
    • 为不同的TTL key配置配置相同逻辑的租约
  5. 通过多对象Txn替换CAS/CAD
    • 更加强大和灵活
  6. 支持多范围高效watch
  7. RPC API支持完整的API集
    • 比JSON/HTTP更有效
    • 额外的TXN/租约支持
  8. 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 性能的关键因素,包括:

  • 延迟 (latency):延迟是完成操作的时间。
  • 吞吐量 (throughput):吞吐量是在某个时间期间之内完成操作的总数量。当 etcd 接收并发客户端请求时,通常平均延迟随着总体吞吐量增加而增加。

在通常的云环境,比如 Google Compute Engine (GCE) 标准的 n-4 或者 AWS 上相当的机器类型,一个三成员 etcd 集群在轻负载下可以在低于 1 毫秒内完成一个请求,并在重负载下可以每秒完成超过 30000 个请求。

etcd 使用 Raft 一致性算法来在成员之间复制请求并达成一致。一致性性能,特别是提交延迟,受限于两个物理约束:网络 IO 延迟和磁盘 IO 延迟。完成一个 etcd 请求的最小时间是成员之间的网络往返时延 (Round Trip Time / RTT),加需要提交数据到持久化存储的 fdatasync 时间。在一个数据中心内的 RTT 可能有数百毫秒。在美国典型的 RTT 是大概 50ms, 而在大陆之间可以慢到 400ms。旋转硬盘(注:指传统机械硬盘) 的典型 fdatasync 延迟是大概 10ms。对于 SSD 硬盘, 延迟通常低于 1ms。为了提高吞吐量, etcd 将多个请求打包在一起并提交给 Raft。这个批量策略让 etcd 在重负载试获得高吞吐量。也有其他子系统影响到 etcd 的整体性能。每个序列化的 etcd 请求必须通过 etcd 的 boltdb 支持的(boltdb-backed) MVCC 存储引擎, 它通常需要 10 微秒来完成。etcd 定期递增快照它最近实施的请求,将他们和之前在磁盘上的快照合并。这个过程可能导致延迟尖峰(latency spike)。虽然在 SSD 上这通常不是问题,在 HDD 上它可能加倍可观察到的延迟。而且,进行中的压缩可以影响 etcd 的性能。幸运的是,压缩通常无足轻重,因为压缩是错开的,因此它不和常规请求竞争资源。RPC 系统,gRPC,为 etcd 提供定义良好,可扩展的 API,但是它也引入了额外的延迟,尤其是本地读取。

Etcd 的默认配置在本地网络环境(localhost)下通常能够运行的很好,因为延迟很低。然而,当跨数据中心部署 Etcd 或网络延时很高时,etcd 的心跳间隔或选举超时时间等参数需要根据实际情况进行调整。

网络并不是导致延时的唯一来源。不论是 Follower 还是 Leader,其请求和响应都受磁盘 I/O 延时的影响。每个 timeout 都代表从请求发起到成功返回响应的总时间。

时间参数

本次调优针对于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
  1. 快照
    etcd将所有关键更改附加到日志文件。此日志将永远增长,并且是对键所做的每次更改的完整线性历史记录。完整的历史记录适用于轻度使用的集群,但是频繁使用的集群将携带大量日志。
    为了避免有大量日志,etcd会进行定期快照。这些快照为etcd提供了一种通过保存系统当前状态并删除旧日志来压缩日志的方法。
    使用V2后端创建快照可能会很昂贵,因此仅在对etcd进行给定数量的更改后才能创建快照。默认情况下,每10,000次更改后将创建快照。如果etcd的内存使用量和磁盘使用量过高,请尝试通过在命令行上设置以下内容来降低快照阈值:
# Command line arguments:
$ etcd --snapshot-count=5000

# Environment variables:
$ ETCD_SNAPSHOT_COUNT=5000 etcd
  1. 磁盘
    etcd集群对磁盘延迟非常敏感。由于etcd必须将建议持久保存到其日志中,因此其他进程的磁盘活动可能会导致较长的fsync延迟。etcd可能会错过心跳,从而导致请求超时和临时领导者丢失。当给予较高的磁盘优先级时,etcd服务器有时可以与这些进程一起稳定运行。
    在Linux上,可以使用以下命令配置etcd的磁盘优先级ionice:
# best effort, highest priority
$ sudo ionice -c2 -n0 -p `pgrep etcd`
  1. 网络 如果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
  1. 内存
    etcd默认的存储大小限制为2GB,可使用–quota-backend-bytes标志进行配置。建议在正常环境下使用8GB的最大大小,如果配置的值超过该值,etcd会在启动时发出警告。
  2. 请求体
    etcd被设计用于元数据的小键值对的处理。较大的请求将工作的同时,可能会增加其他请求的延迟。默认情况下,任何请求的最大大小为1.5 MiB。这个限制可以通过–max-request-bytesetcd服务器的标志来配置。
  3. 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     |
+----------+----------+------------+------------+
  1. 卷快照
    如果 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,我们才更有信心。以及更好的服务业务。提供更稳定的技术服务。

参考文档

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值