現象:
最近新接手一個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就好了。