一直以来我采用supervisord来进行第三方服务的管理,百试不爽。所谓的第三方服务,我这里把不能通过yum或apt进行安装的,统统归拢为第三方;当然使用systemd来进行管理也很不错,不过在服务exit的时候需要自己写脚本来进行重启和重试操作。不例外的,Prometheus我还是采用了supervisord来进行启动管理,但是过完年后上班发现,我的prometheus无法收集targets的监控数据了,8百多个监控接口的数据丢了三天;排查后发现是由于supervisor引起的。于是整理出来,大家分享一下我的排查路线。 1、发现Prometheus监控的Targets状态全部变为Down,查看页面详细报错信息和服务日志: 监控挂掉 服务日志
从页面和日志中发现基本被"file closed"的报错信息所淹没:“err="WAL log samples: log series: write data/wal/002911: file already closed"。 2、本着优先恢复业务的运维原则,尝试重启其中一台Prometheus服务,发现重启后服务日志依旧报错,信息如下: level=error ts=2018-02-26T02:26:38.80774862Z caller=db.go:265 component=tsdb msg="compaction failed" err="compact [/data/prometheus/prometheus/data/01C6S070KRF0V2202ZKPB4BTG4 /data/prometheus/prometheus/data/01C6TY0J7RAQAA34JJQVQZ3D46 /data/prometheus/prometheus/data/01C6WVSZB66DBAXBSYPMZGJ29W]: open /data/prometheus/prometheus/data/01C6TY0J7RAQAA34JJQVQZ3D46/tombstones: too many open files 看到日志关键字段:“too many open files”! 3、根据重启前和重启后的日志关键字眼,初步判定跟文件描述符有关,Linux系统对单进程可最大打开文件数默认限制为1024,我这里监控了800多个节点,每个节点暴露上百个监控数据,平均没分钟抓取一次,需要定期的进行数据落盘操作,可能是系统的文件描述符过低导致的。 4、检查系统文件描述符情况: ①检查inodes使用情况: 系统inode使用情况正常。 ②查看系统的限制情况:

# ulimit -n
81920

系统级别的打开文件数限制已经调整至81920,正常。 ③既然系统层面没有限制已经放开,那么会不会是Prometheus进程的限制呢,验证:

# pidof prometheus
17626
# cat /proc/17624/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 63472 63472 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 63472 63472 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

查看进程的限制max open files的Soft和Hard分别为1024和4096,这就很奇怪了,系统明明已经放开了open file限制,为什么Prometheus进程还被限制在1024呢? 思考之后想到Prometheus本来也有自己的监控接口,查下本身的监控数据,其中“process_max_fds”监控条目跟最大文件数相关,然后看到如下数据:

# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1024
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 1022

当前已经open了1022个,最大限制1024,再次验证了是进程的可用文件数限制过低导致。 ④那么问题来了?是什么原因导致的进程open file受限呢。答案可能只有一个:supervisor!因为我的Prometheus是用supervisor启动的。先验证一下,弃用守护进程,手动启动Prometheus服务看下,文件数限制是否放开;再次启动后,查看监控情况:

可见手动重启后限制已经放开。由此确定是supervisor引起的被守护进程文件数限制。

⑤定位到supervisor后,查看supervisor的启动参数,有没有类似文件描述符的限制字眼,在配置文件/etc/supervisord.conf中搜索关键字file、nf、fds等字眼: 发现在supervisord的配置区域内有"mindfs"的配置,解释如下:“avail startup file descriptors;default 1024”。顺便查了下官方文档里的解释:

The minimum number of file descriptors that must be available before supervisord will start successfully. A call to setrlimit will be made to attempt to raise the soft and hard limits of the supervisord process to satisfy minfds. The hard limit may only be raised if supervisord is run as root. supervisord uses file descriptors liberally, and will enter a failure mode when one cannot be obtained from the OS, so it’s useful to be able to specify a minimum value to ensure it doesn’t run out of them during execution. These limits will be inherited by the managed subprocesses. This option is particularly useful on Solaris, which has a low per-process fd limit by default.

文档中指出,如果用root用户启动的supervisord,可以尝试增大此值。

⑥修复:增大supervisord的mindfs值至65535,之后再次用supervisor启动Prometheus。启动后监控恢复,能够正常抓取数据。再次查看进程的打开文件数限制,已调整至65535: # cat /proc/17626/limits 总结:真正实践中问题的排查,可能没有文章中整理的那么简单,6步定位问题并恢复故障。实际可能会走许多弯路,在问题过后的整理归纳可以让梳理思路、积累经验,为下一次更快、更准确的定位问题埋下希望的种子。