现象:
最近新接手一个etcd集群进行维护,突然发现etcd集群连不上了,打开etcd监控看节点都是健康状态但是有大量的慢查询,而且还在持续增加。
初步怀疑是否是机器资源受限导致,把etcd集群的5个节点的cpu,mem,io等指标都拉出来了进行了对比,发现在不可访问那个时间点资源有微量上升,但是区别不大,所以可以排除是资源的问题。
然后在etcd节点上用命令检查etcd健康性发现竟然后三个节点都连不上了,然后用telnet命令去连接4012端口发现竟然也连接不上,然后用netstat命令查看4012端口发现打开一切正常,接着用tcpdump等抓包等也发现没有太大效果。
接着用命令统计了一下etcd链接数
netstat -an |grep 'ESTABLISHED' |grep -i '4012' | wc -l
发现已经有了102419个链接建立,感觉连接建立非常多,接着就怀疑应该是这个问题造成的,重启了一下etcd进程,等了没两分钟再去看发现连接数接着又飚上来了,接着去看了etcd一下日志发现一条很关键的日志:
80% of the file descriptor limit is used [used = 88863, limit = 102400]
这个是比较早期的日志,因为日志很长时间才能拉到最后,不过基于此结合连接数基本上已经可以确认是连接数太大达到上限导致的,然后看想看一下这个102400这个限制是怎么来的,经过查etcd代码发现是调用了一个系统调用获取的:
func FDLimit() (uint64, error) {
var rlimit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
return 0, err
}
return rlimit.Cur, nil
}
RLIMIT_NOFILE
这里值就变得尤为重要,这个值应该就是最大打开文件描述符限制,查看ulimit设置都是百万级别的,远远没有达到限制,此处陷入疑惑。经过一番查找思考查看etcd进程级别的限制:
cat /proc/110395/limits
果然发现有一行Max open files 102400
最后再systemd的配置文件里面终于发现一个配置LimitNOFILE=102400
原来就是这个配置捣的鬼,把这个配置改大重启一下etcd就好了。