etcd性能问题排查及解决方案

最近遇到一个客户k8s测试集群经常崩溃,最终定位是etcd磁盘IO性能不足,最终替换成ssd盘解决,记录一下排查过程。

集群是跑在客户的共享虚机上,磁盘是机械硬盘,问题现象如下:

  1. kube-system下涉及高可用的组件 kube-apiserver、kube-controller-manager、kube-scheduler 频繁重启,某些选主模式的组件、服务反复重启,频繁CrashLoopBackoff,查看其日志有"leaderelection lost",“timed out waiting for xxx”等字样

  2. kubectl 反应慢,使用 kubectl get no --v=7,两三秒内才返回结果

  3. 查看kube-apiserver日志,看到有“etcdserver: request timed out”、“etcdserver:leader changed”等字样

  4. 查看etcd日志,有较多“xxx took too long”,“lost leader”等字样,time spent达到了几百ms,甚至两三秒

从现象上看,问题很可能出现在etcd上~

etcd性能瓶颈及稳定性分析链路图

etcd性能问题排查及解决方案

图片来源:极客时间《etcd实战课》

etcd集群性能受磁盘IO、时钟同步、master之间的网络以及节点负载影响,根据经验,磁盘IO导致的可能性较大。

1、时间同步验证

使用pssh工具,或ssh 机器执行date命令,对比时钟差异是否超过1s。时钟不同步,可以使用chrony或ntp或自建时钟源,将集群所有节点连接到同一时钟源,确保时钟同步。参考:Chrony详解:代替ntp的时间同步服务

2、master节点负载、CPU、MEM、IO、NET等检察,查看系统日志是否有明显报错,比如硬件报错,OOM(out of memory)等

使用top,iostat,iftop,iotop,sar,netstat,vmstat查看系统基础指标

使用scp,ipref,dd,fio等工具测试网络及磁盘性能:

# 制作1GB文件
dd if=/dev/zero of=/tmp/test-net bs=1M count=1000

# 测试传输速度
scp /tmp/test-net root@$master2:/tmp/
scp /tmp/test-net root@$master3:/tmp/

一般来说千兆带宽得达到约125MiB/s的传输速度;大规模集群( 500节点)需要兆带宽,网络需要达到约1250MiB/s的传输速度

etcd应用层提供了节点之间网络统计的metrics指标,分别如下:

  • etcd_network_active_peer,表示peer之间活跃的连接数;

  • etcd_network_peer_round_trip_time_seconds,表示peer之间RTT延时;

  • etcd_network_peer_sent_failures_total,表示发送给peer的失败消息数;

  • etcd_network_client_grpc_sent_bytes_total,表示server发送给client的总字节数,通过这个指标我们可以监控etcd出流量;

  • etcd_network_client_grpc_received_bytes_total,表示server收到client发送的总字节数,通过这个指标可以监控etcd入流量。

可以使用监控系统监控etcd网络指标,使用相关工具查看是否出现丢包等错误。

# 4k写
fio  -direct=1 -iodepth=128 -thread -rw=write -ioengine=libaio -bs=4k -size=1G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest
# 4k读
fio  -direct=1 -iodepth=128 -thread -rw=read -ioengine=libaio -bs=4k -size=1G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest
# 4K随机写:
fio  -direct=1 -iodepth=128 -thread  -rw=randwrite -ioengine=libaio -bs=4k -size=1G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest
# 4K 随机读
fio  -direct=1 -iodepth=128 -thread -rw=randread -ioengine=libaio -bs=4k -size=1G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest
# 1M写
fio  -direct=1 -iodepth=64 -thread -rw=write -ioengine=libaio -bs=1M -size=8G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest
# 1M读
fio  -direct=1 -iodepth=64 -thread -rw=read -ioengine=libaio -bs=1M -size=8G -numjobs=1-runtime=600 -group_reporting -name=mytest -filename=/var/lib/etcd/iotest

Master配置一块独立块设备:SSD是首选,推荐 [SSD 4K IOPS>=3300] [企业级SAS硬盘rpm>=10000,最好15000][更高配置的NVMe)],参考:Linux系统下查看硬盘转速

3、kubectl descrbe node查看节点负载信息,在输出中检查 Allocated Resources 和 Conditions 部分,可以将占用高的无状态应用迁走,减轻master节点压力

最后排查发现master节点网络、节点负载、时间同步都正常,环境由于是共享虚拟机环境,机器IO性能很可能存在欺骗现象。

etcd性能不足原因定位:

1、检查 etcd 状态:

kubectl get pods -n kube-system -l component=etcd

2、查看 etcd 日志:

kubectl logs -n kube-system etcd-<node-name>

etcd性能问题排查及解决方案

etcd性能问题排查及解决方案etcd性能问题排查及解决方案

3、查看 etcd 集群状态:etcdctl endpoint status

ETCDCTL_API=3 etcdctl --endpoints=10.0.1.6:2379,10.0.1.7:2379,10.0.1.8:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key endpoint status -w table

4、查看 etcd 集群健康状态:etcdctl endpoint health

ETCDCTL_API=3 etcdctl --endpoints=10.0.1.6:2379,10.0.1.7:2379,10.0.1.8:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key endpoint health -w table

etcd性能问题排查及解决方案

5、etcd 集群性能测试:etcdctl check perf

ETCDCTL_API=3 etcdctl --endpoints=10.0.1.6:2379,10.0.1.7:2379,10.0.1.8:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key check perf

结果有FAIL

etcd性能问题排查及解决方案

6、etcd 磁盘IO指标:

1)etcd_disk_backend_commit_duration_seconds:后端提交延迟,将最近的更改保存到磁盘所需的时间(以秒为单位),一般P99在120ms内。

释义:The latency distributions of commit called by backend.

curl -s --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key  https://127.0.0.1:2379/metrics | grep backend_commit_duration_seconds

etcd性能问题排查及解决方案

上面的输出是一个类似CDF的表,表示了每一行“小于等于x秒完成的commit的数目”,最后一行代表了统计的总数。例如line7,表示完成时间<=16ms的commit有1064个,最后一行表示统计总数为9340,所以<=16ms的commit占比达到 1064/9340=11.4%。一般来说,满足要求的指标是小于25ms的超过99%,所以上面这个统计远远达不到要求。当disk_backend_commit指标的异常时候,说明事务提交过程中的B+ tree树重平衡、分裂、持久化dirty page、持久化meta page等操作耗费了大量时间。

2)etcd_disk_wal_fsync_duration_seconds:WAL日志同步延迟,将预写日志 (WAL) 中存在的 pending changes 持久保存到磁盘所需的时间(以秒为单位),一般本地SSD盘P99延时在10ms内。

释义:The latency distributions of fsync called by wal

curl -s --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key  https://127.0.0.1:2379/metrics | grep wal_fsync_duration_seconds

etcd性能问题排查及解决方案

一般来说,满足要求的指标是小于10ms的超过99%,16737/33744=50%,达不到要求。

当disk_wal_fsync指标异常的时候,一般是底层硬件出现瓶颈或异常导致。当然也有可能是CPU高负载、cgroup blkio限制导致的。

参考文献:https://etcd.io/docs/v3.5/faq/#what-does-the-etcd-warning-failed-to-send-out-heartbeat-on-time-mean

若disk_backend_commit较高、disk_wal_fsync却正常,说明瓶颈可能并非来自磁盘I/O性能,也许是B+ tree的重平衡、分裂过程中的较高时间复杂度逻辑操作导致。

3)etcd_server_leader_changes_seen_total:领导者变更次数

在etcd中,Leader节点会根据heartbeart-interval参数(默认100ms)定时向Follower节点发送心跳。如果两次发送心跳间隔超过2*heartbeart-interval,就会打印此警告日志。超过election timeout(默认1000ms),Follower节点就会发起新一轮的Leader选举。

etcd默认心跳间隔是100ms,较小的心跳间隔会导致发送频繁的消息,消耗CPU和网络资源。而较大的心跳间隔,又会导致检测到Leader故障不可用耗时过长,影响业务可用性。一般情况下,为了避免频繁Leader切换,建议你可以根据实际部署环境、业务场景,将心跳间隔时间调整到100ms到400ms左右,选举超时时间要求至少是心跳间隔的10倍。

curl -s --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key  https://127.0.0.1:2379/metrics | grep etcd_server_leader_changes_seen_total

etcd性能问题排查及解决方案

4)etcd_mvcc_db_total_size_in_bytes etcd 数据库的大小(以字节为单位),默认情况下,etcd 最多可以存储 2 GiB 的数据。该最大值是可配置的,但 etcd 建议将最大大小设置为不超过 8 GiB。如果达到最大大小,etcd 将不再接受任何写入,并且 Kubernetes 无法执行集群管理任务,例如调度新的 pod。

etcd适合读多写少的业务场景,若写请求较大,很容易出现容量瓶颈,导致高延时的读写请求产生。

etcd是一个对磁盘IO性能非常敏感的存储系统,磁盘IO性能不仅会影响Leader稳定性、写性能表现,还会影响读性能。线性读性能会随着写性能的增加而快速下降。如果业务对性能、稳定性有较大要求,建议尽量使用SSD盘。

etcd机械盘替换ssd盘:

etcd一般是随Master节点一同部署,每个Master节点会跑1个etcd实例,注意每次只对一个Master节点做替换,确认没问题后再操作下一个Master节点上的etcd

# 备份etcd数据
ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key snapshot save /root/etcd_backup/etcd-backup.db

# 验证快照命令
etcdctl snapshot status /root/etcd_backup/etcd-backup.db -w table

# 停止kubelet
systemctl stop kubelet

# 静态pod启动的etcd,先将etcd.yaml从/etc/kubernetes/manifests里挪走
mv /etc/kubernetes/manifests/etcd.yaml /tmp/

# 备份etcd数据
cp -rp /var/lib/etcd /root/

# 卸载原来的磁盘
umount /var/lib/etcd

# 假设新的ssd磁盘为/dev/vdb,格式化新的磁盘并挂载,挂载信息注意写入/etc/fstab
mkfs.ext4 -F /dev/vdb
mount /dev/vdb /var/lib/etcd

# 将备份数据还原
cp -rp etcd/* /var/lib/etcd/

# 将etcd.yaml挪回到/etc/kubernetes/manifests里
mv /tmp/etcd.yaml /etc/kubernetes/manifests/

# 启动kubelet,拉起新的etcd pod
systemctl restart kubelet

# 检查etcd是否正常启动,查看etcd集群是否正常,都正常再继续操作下一个节点
kubectl get pods -n kube-system -l component=etcd

更换ssd盘后效果:

etcd性能问题排查及解决方案etcd性能问题排查及解决方案

etcd性能问题排查及解决方案


参考:

anzhihe 安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/6317.html | ☆★★每天进步一点点,加油!★★☆ | 

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注