项目问题:文件描述符限制

1. 背景:

项目需要搭建ElasticSearch、Logstash、Filebeat、Kibana、Prometheus等工具进行微服务系统的性能监控,此外我们额外构建了一个后台,从ElasticSearch中读取保存的监控数据,绘制到前端页面中。整套微服务系统和检测工具都部署在minikube单机集群中,而前后端系统开发过程中使用另一台主机,后端要想访问单机集群中的ES数据库,需要对ES数据库暴露的接口进行端口转发:

1
kubectl port-forward svc/elasticsearch-master -n observe --address 10.10.1.202 9200:9200

2. 问题:

后端在获取ES数据时,当连接次数过多后,会出现如下错误:

1
E0225 15:22:30.454203   26392 portforward.go:353] error creating forwarding stream for port 9090 -> 9090: Timeout occured

并且kubectl的端口转发不会退出,在后端角度就是连数据库时会不断地中断连接。

3. 问题根因:

通过查找相关资料:https://github.com/kubernetes/kubernetes/issues/74551#issuecomment-881761717

有人提供了一种受到大家认可的思路:进程可以打开的文件描述符数量限制了kubectl在端口转发时创建新的TCP连接

临时修改进程的文件描述符数量限制(number of file descriptor, nofile)

1
ulimit -n 1048576

也可以将修改写入配置文件中进行持久化: sudo vim /etc/security/limits.conf。添加下面这行:

1
* soft nofile 1048576

也可以将ulimit -n 1048576写入/etc/profile中,然后source /etc/profile使其立即生效

通过调大nofile,确实能够延缓该问题。但是最终仍然还会出现该错误,似乎kubectl进行端口转发时不会及时释放老的连接。因此最终只能通过编写bash脚本和使用crontab来每天重启一次kubectl的port-forward。

1
2
3
4
5
6
7
8
9
#!/bin/bash

pid=$(ps -aux|grep -w 'kubectl port-forward svc/elasticsearch-master -n observe --address 10.10.1.202 9200:9200'|grep -v 'grep'|awk '{print $2}');
if [ -n "$pid" ] ; then
echo "Found process:" $pid
kill -9 $pid
fi

kubectl port-forward svc/elasticsearch-master -n observe --address 10.10.1.202 9200:9200

使用crontab时还有个小细节,kubectl并不是/bin目录下的可执行文件,其路径是通过环境变量进行添加的,如果直接编写crontab文件该bash脚本不能完全正常执行,需要这样:

1
2
3
4
5
6
7
SHELL=/bin/bash
PATH=/usr/local/bin/:/sbin:/bin:/usr/sbin:/usr/bin
LANG=en_US.UTF-8
5 */4 * * * bash /home/fanqiliang/scripts/kubectl.sh
5 */4 * * * bash /home/fanqiliang/scripts/kubectl_prometheus.sh
5 */4 * * * bash /home/fanqiliang/scripts/kubectl_kibana.sh
5 */4 * * * bash /home/fanqiliang/scripts/kubectl_chaosmesh.sh

项目问题:文件描述符限制
https://www.torch-fan.site/2023/04/17/项目问题-文件描述符限制/
作者
Torch-Fan
发布于
2023年4月17日
更新于
2023年4月21日
许可协议