文章目录
最近做了很多 Etcd 运维工作,也遇到了一些场景,这里结合 《Kubernetes 生产化实践之路》 (后面称这本书为《实践》)以及网上的一些思路,思考下 Etcd 性能调优相关总结,并对相关引用材料进行整理。这些引用材料可能并没有完全读完,或者理解思考,这里作为索引,后面再对这些内容作为迭代。也就是说性能调优作为主线,相关引用材料作为分支。
减少网络时延
《实践》这本书中提到“建议 Etcd 应尽量做到同地域部署”,这个信息很重要,因为最近也在做同城双活,一般来说,同城(同城双活)的时延在 1ms 左右,应该是还能符合一个 Etcd 的时延要求的。这个我们也使用 tc 来模拟时延,在配置网卡时延在 20ms 时,Etcd 性能及功能影响不是很大。
在 Etcd 节点网络流量很大时,我们可以提高 Etcd 流量的优先级,这个也可以通过 tc 来完成,具体怎么做,可以参考《How to use ‘tc’ (traffic control) to increase / decrease an application’s network priority?》,思路是通过 iptables 来对流量进行标记,然后把不同的流量放到 tc 的不同队列里。
tc 工具很复杂,难得有资料能把事情讲清楚。不过从上面来看,通过 tc 来控制流量优先级还是有一定成本的。《实践》中还提到了一种 case: leader 的连接太多,导致 follower 发往 leader 的请求被丢弃
dropped MsgProp to 247ae21ff9436b2d since streamMsg's sending buffer is full
dropped MsgAppResp to 247ae21ff9436b2d since streamMsg's sending buffer is full
在官方文档中https://etcd.io/docs/v3.4/tuning/#network,提供了使用 tc 提高 etcd 流量优先级的方法:
# 提供优先级
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
# 取消 tc 限速配置
tc qdisc del dev eth0 root
其中,关于 tc 命令中 handle 的说明可以参考 https://tldp.org/HOWTO/Traffic-Control-HOWTO/components.html#c-handle,看上去就是一个 ID,关于 prio
模块的说明可以参考:https://linux.die.net/man/8/tc-prio
这种方式比 iptables 标记流量的方式好像简单一点。
减少磁盘 I/O 延迟
一般物理磁盘的时延为 10ms,SSD 的时延低于 1ms,所以 Etcd 一般用 ssd。而且是单盘只给 ssd 用。另外因为 K8s 的 event 量多且频繁变更,我们可以将 event 单独存储,这个需要修改 kube-apiserver 的参数:--etcd-servers-overrides
,可以参考《Etcd 安装、部署、测试》
另外,如果 Etcd 共享磁盘,那么可以使用 ionice 来提高 Etcd 磁盘优先级,命令为:
ionice -c2 -n0 -p 'pgrep etcd'
ionice 的使用,可以参考利用ionice命令设置程序的IO调度与优先级。ionice将磁盘IO调度分为三类:
- ilde:空闲磁盘调度,该调度策略是在当前系统没有其他进程需要进行磁盘 IO 时,才能进行磁盘读写。
- Best effort:是缺省的磁盘IO调度策略;(1)该调度策略可以指定优先级参数(范围是0~7,数值越小,优先级越高);
- Real time:实时调度策略,如果设置了该磁盘IO调度策略,则立即访问磁盘,不管系统中其他进程是否有IO。因此使用实时调度策略,需要注意的是,该访问策略可能会使得其他进程处于等待状态。
另外,ionice 可以配置到定时任务中,毕竟 etcd 进程有可能会重启。
ionice - sets or gets process io scheduling class and priority.
Usage:
ionice [OPTION] -p PID [PID...]
ionice [OPTION] COMMAND
Options:
-c, --class scheduling class name or number
0: none, 1: realtime, 2: best-effort, 3: idle
-n, --classdata scheduling class data
0-7 for realtime and best-effort classes
-p, --pid=PID view or modify already running process
-t, --ignore ignore failures
-V, --version output version information and exit
-h, --help display this help and exit
自动压缩历史版本
这个调整 Etcd 的参数 --auto--compaction
即可,一般默认是开启的,这个有两种压缩模式,一种是周期性的,一种是根据历史记录数,这个看下文档即可,不再赘述。
定期消除碎片
Etcd 是不会主动归还空闲的磁盘空间的,这个时候需要调用etcdctl defrag
命令来释放空间,另外在 Etcd 中,我们调用 delete 接口删除数据时,并不会从磁盘删数据,只是对对应的版本数据添加一个tombstone
标志,因此我们删除数据并不会释放空间,除非调用 defrag
命令释放磁盘空间。调用 defrag
会影响读写性能,尽量不要调用,或者在业务低峰期调用。
优化运行参数
这个主要是心跳周期(heartbeat,默认100ms)
和选举超时时间(election timeout,默认1000ms)
,尤其是在高迟延场景下,需要增加这两个参数,避免造成频繁选主,造成集群不稳定。
心跳周期一般设置为 Etcd 成员直接平均往返周期的最大值,一般是平均RTT 的 0.55~1.5 倍。选举超时一般设置为心跳周期的10倍。测量 TTL 最简单的方法是使用 ping 工具。
参考
《Kubernetes 生产化实践之路》ebay