共计 6790 个字符,预计需要花费 17 分钟才能阅读完成。
故障表现
测试反馈生产环境报错:
172.29.120.120:9091
为 pushgateway 暴露的IP和端口。
上机排查 pushgateway 状态,此服务是裸机部署,由 systemd
管理。操作系统为 CentOS 7
。
[root@wpscloud-pth-pgw-2901 ~]# systemctl status pushgateway.service
● pushgateway.service - Prometheus pushgateway
Loaded: error (Reason: Invalid argument)
Active: active (running) since Fri 2022-12-23 18:29:16 CST; 1 years 4 months ago
Main PID: 7579 (pushgateway)
CGroup: /system.slice/pushgateway.service
└─7579 /usr/local/bin/pushgateway --web.listen-address=0.0.0.0:9091 --log.level=error
Apr 25 11:55:37 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:37 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:38 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:38 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:39 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:39 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:40 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:40 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:41 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:41 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:42 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:42 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:43 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:43 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:44 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:44 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:45 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:45 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
Apr 25 11:55:46 wpscloud-pth-pgw-2901 pushgateway[7579]: 2024/04/25 03:55:46 http: Accept error: accept tcp [::]:9091: accept4: too many open files; retrying in 1s
很明显,报错为:too many open files
,导致业务侧上报监控指标超时。
排障思路
首先排查 pushgateway 究竟打开了多少个文件:
# 查看进程PID
[root@wpscloud-pth-pgw-2901 fd]# pidof pushgateway
7579
# 查看PID打开的文件数
[root@wpscloud-pth-pgw-2901 fd]# ls /proc/7579/fd|wc -l
65535
可以看到,打开了 65535
个文件。这个值没什么可说,一眼能看出来受到了某些系统配置限制导致。
那么可以围绕以下两点展开:
- 文件描述符限制如何调大
- 为什么会打开如此多的文件
问题1:文件描述符限制
在类Unix系统中,每个进程都有一个限制,称为“文件描述符限制”,它决定了一个进程可以同时打开多少文件。
首先查看当前的环境变量:
[root@wpscloud-pth-pgw-2901 ~]# ulimit -n
1048576
[root@wpscloud-pth-pgw-2901 ~]# cat /proc/sys/fs/file-max
1048576
[root@wpscloud-pth-pgw-2901 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 509249
max locked memory (kbytes, -l) 14411059
max memory size (kbytes, -m) unlimited
open files (-n) 1048576
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 65535
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
可以看到操作系统限制的单进程最大可打开文件数为 1048576
。这与监控表现也是一致的。
再看看配置文件:
[root@wpscloud-pth-pgw-2901 ~]# cat /etc/security/limits.conf|egrep -v "^$"|egrep -v "^#"
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
* soft memlock 14411059
* hard memlock 14411059
进程打开的文件描述符由 soft nofile
和 hard nofile
进行控制。它们的值均为:1048576
。
解释如下:
- 软限制(soft limit):
- 软限制是指系统当前允许的最大文件描述符数量,但是这个值可以通过用户或者进程自己来修改,前提是不超过硬限制。
- 当达到软限制时,系统会发送警告信息,但是不会阻止进程继续分配文件描述符。
- 硬限制(hard limit):
- 硬限制是系统中设置的最大文件描述符数量,只有特权用户(例如root)可以将软限制设置为高于当前硬限制的值。
- 当达到硬限制时,系统会阻止进程继续分配文件描述符,除非提升软限制或者修改硬限制。
即软限制是进程当前允许的最大文件描述符数量,而硬限制是系统允许的最大文件描述符数量。
到这儿可以有一个初步总结,即 pushgateway 打开的文件数并未到达系统配置的上限。那现在只能达到65535个,应该是进程本身的限制。
翻查了一下 pushgateway 的官方文档,并未发现有启动参数可以控制打开的文件数。
于是 google一下,找到文章:
Prometheus Too Many Open file问题
结论为,若期望打开超过65535个文件,必须在配置文件中显式指定 LimitNOFILE=***
,且 *** ≥65535。
即便配置 LimitNOFILE=infinity
,也无法超过 65535 的上限。
修改 pushgateway 的 systemd 单元文件配置,调大上限:
[root@wpscloud-pth-pgw-2901 fd]# cat /etc/systemd/system/pushgateway.service
[Unit]
Description=Prometheus pushgateway
After=network-online.target
[Service]
Type=simple
User=prometheus
Group=prometheus
LimitNOFILE=100000
LimitMEMLOCK=65535
ExecStart=/usr/local/bin/pushgateway \
--web.listen-address=0.0.0.0:9091\
--log.level=error
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
NoNewPrivileges=true
ReadWriteDirectories=/var/lib/pushgateway
ProtectSystem=full
修改完毕重启服务:
# systemctl daemon-reload
# systemctl restart pushgateway.service
问题2:FD泄露
在Linux中,“FD”通常指“文件描述符”(File Descriptor)。文件描述符是一个非负整数,用于标识打开的文件、套接字或其他I/O资源。
在问题1中,由于我已经重启了pushgateway,再次观察打开的文件数后,发现已经降得很低:
[root@wpscloud-pth-pgw-2901 ~]# ps -ef|grep push
prometh+ 11010 1 62 14:24 ? 00:08:49 /usr/local/bin/pushgateway --web.listen-address=0.0.0.0:9091 --log.level=error
root 12106 12056 0 14:38 pts/0 00:00:00 grep --color=auto push
[root@wpscloud-pth-pgw-2901 ~]# ls /proc/11010/fd|wc -l
236
此时因为已经没有现场,没有再花费时间持续跟踪,但根据一篇博文:参考链接:www.cnblogs.com/weizaiya…
可得出结论: pushgateway 已经回收了TCP链接,但是FD却没有被释放,导致打满 65535 限制。
验证方式为:在 /proc/net/tcp
中查看对应的 inode
, 等连接释放后,再去 /proc/pid/fd/
下面看对应的文件句柄是否被回收。
- 找一条由 pushgateway 产生的TCP链接
[root@wpscloud-pth-pgw-2901 ~]# ss -plta |grep 11010
LISTEN 0 65535 :::9091 :::* users:(("pushgateway",pid=11010,fd=4))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.18.184:39032 users:(("pushgateway",pid=11010,fd=180))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.21.117:42872 users:(("pushgateway",pid=11010,fd=129))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.21.117:58386 users:(("pushgateway",pid=11010,fd=70))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.79.209:44520 users:(("pushgateway",pid=11010,fd=105))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.94.163:52390 users:(("pushgateway",pid=11010,fd=38))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.112.37:46308 users:(("pushgateway",pid=11010,fd=247))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.21.117:60518 users:(("pushgateway",pid=11010,fd=56))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.112.37:52774 users:(("pushgateway",pid=11010,fd=106))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.94.163:50958 users:(("pushgateway",pid=11010,fd=111))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.79.209:50020 users:(("pushgateway",pid=11010,fd=121))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.21.117:43214 users:(("pushgateway",pid=11010,fd=62))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.112.37:39412 users:(("pushgateway",pid=11010,fd=245))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.94.163:56800 users:(("pushgateway",pid=11010,fd=94))
ESTAB 0 0 ::ffff:172.29.120.120:9091 ::ffff:172.29.79.209:51228 users:(("pushgateway",pid=11010,fd=176))
- 以
fd=180
为例,查找对应的inode
[root@wpscloud-pth-pgw-2901 ~]# ll /proc/11010/fd/ |grep 180
lrwx------ 1 root root 64 Apr 25 14:25 180 -> socket:[217457112]
lrwx------ 1 root root 64 Apr 25 14:26 223 -> socket:[217467180]
180 为 文件句柄
;而socket:[***],例如 217457112 为 文件inode号
。
- 在 tcp 连接中过滤
inode
,发现值为空
[root@wpscloud-pth-pgw-2901 ~]# cat /proc/net/tcp |grep 217457112
[root@wpscloud-pth-pgw-2901 ~]#
- 直接查看进程打开文件描述符的详细信息。可以推测文件句柄未被清理,但是其实TCP连接已经释放了。
至于为什么 pushgateway 会产生FD泄露的问题, github 上已经有现成的 issues,不再展开讨论。
总结
若故障不紧急,当然可以保留现场慢慢调试。紧急故障需以修复为主。
本文属于专题:Prometheus 监控
- 使用 Redis Exporter 监控 Redis
- Grafana 备份、迁移与升级
- 云原生监控 Kube-Prometheus
- Prometheus 集成 Nginx 监控
- Prometheus 查询指定时间范围内的峰值或均值
- 云监控接入本地Prometheus
- 使用 MySQL Exporter 监控MySQL
- 个人微信接收夜莺告警消息
- PushGateway 报错:too many open files
- Blackbox 网络监控
- node_exporter 添加自定义指标
- Python 实现资源水位巡检
- Prometheus 替代方案:VictoriaMetrics
- 使用 node_exporter 实现路由器监控