夜莺-Nightingale
夜莺V6
项目介绍 架构介绍
快速开始
黄埔营
安装部署
升级
采集器
使用手册
API
数据库表结构
FAQ
开源生态
Prometheus
版权声明
第1章:天降奇兵
第2章:探索PromQL
第3章:Prometheus告警处理
第4章:Exporter详解
第5章:数据与可视化
第6章:集群与高可用
第7章:Prometheus服务发现
第8章:监控Kubernetes
第9章:Prometheus Operator
参考资料

Telegraf调研笔记6:PING监控、进程监控

本篇介绍两个采集插件,ping和procstat。ping监控就是用于远程探测的,procstat主要有两个功能,一个是采集进程个数,比如nginx这种多进程模型,会采集总的进程数量,同时对每个单一进程,会采集进程相关的cpu、内存使用情况以及一些资源限制信息等。

ping

ping插件的默认配置如下:

# # Ping given url(s) and return statistics
# [[inputs.ping]]
#   ## Hosts to send ping packets to.
#   urls = ["example.org"]
#
#   ## Method used for sending pings, can be either "exec" or "native".  When set
#   ## to "exec" the systems ping command will be executed.  When set to "native"
#   ## the plugin will send pings directly.
#   ##
#   ## While the default is "exec" for backwards compatibility, new deployments
#   ## are encouraged to use the "native" method for improved compatibility and
#   ## performance.
#   # method = "exec"
#
#   ## Number of ping packets to send per interval.  Corresponds to the "-c"
#   ## option of the ping command.
#   # count = 1
#
#   ## Time to wait between sending ping packets in seconds.  Operates like the
#   ## "-i" option of the ping command.
#   # ping_interval = 1.0
#
#   ## If set, the time to wait for a ping response in seconds.  Operates like
#   ## the "-W" option of the ping command.
#   # timeout = 1.0
#
#   ## If set, the total ping deadline, in seconds.  Operates like the -w option
#   ## of the ping command.
#   # deadline = 10
#
#   ## Interface or source address to send ping from.  Operates like the -I or -S
#   ## option of the ping command.
#   # interface = ""
#
#   ## Percentiles to calculate. This only works with the native method.
#   # percentiles = [50, 95, 99]
#
#   ## Specify the ping executable binary.
#   # binary = "ping"
#
#   ## Arguments for ping command. When arguments is not empty, the command from
#   ## the binary option will be used and other options (ping_interval, timeout,
#   ## etc) will be ignored.
#   # arguments = ["-c", "3"]
#
#   ## Use only IPv6 addresses when resolving a hostname.
#   # ipv6 = false

urls这个字段,可以写很多ip,Telegraf就会对这些ip发起ping探测,待会咱们写一个能连通的ip,一个不能连通的ip,测试下,method有两种取值,一个是exec,就是调用本机的ping命令,一个是native,用Telegraf这个进程直接发icmp包,建议用native,deadline表示整体超时时间,10s有点太长了,内网ping探测,2s足够了,所以,我们最终使用下面的配置测试:

[[inputs.ping]]
urls = ["10.255.0.34", "10.255.0.35"]
method = "native"
deadline = 2

[root@10-255-0-34 telegraf-tmp]# ./usr/bin/telegraf --config etc/telegraf/telegraf.conf --test --input-filter ping
2021-11-10T02:40:39Z I! Starting Telegraf 1.20.2
> ping,host=10-255-0-34,url=10.255.0.34 average_response_ms=0.398049,maximum_response_ms=0.398049,minimum_response_ms=0.398049,packets_received=1i,packets_transmitted=1i,percent_packet_loss=0,result_code=0i,standard_deviation_ms=0,ttl=64i 1636512039000000000
> ping,host=10-255-0-34,url=10.255.0.35 packets_received=0i,packets_transmitted=1i,percent_packet_loss=100,result_code=1i 1636512041000000000

标签部分,除了host之外,只有url标签,所以标签肯定是稳态的,还不错,field部分,有个result_code,如果是0表示正常,非0表示异常,可以拿这个字段做告警策略。

如果ping监控需要探测的目标比较多,会占用很多网络连接的句柄,需要调大ulimit限制,建议把Telegraf用systemd托管,在systemd里可以调整这个配置:

[Service]
LimitNOFILE=8192

上面就是把打开的文件句柄限制为8192了,默认一般是1024,查看某个进程的限制,可以通过这个命令获取:

[root@10-255-0-34 telegraf-tmp]# cat /proc/15451/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             63359                63359                processes
Max open files            65535                65535                files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       63359                63359                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

很多朋友会反馈是,我明明调整了系统的ulimit配置,为啥进程还是报了文件句柄打开过多的错误呢?通常就是忘记调整systemd的配置了,最终进程的限制,查看/proc/pid/limits是最准的,做了一些调整之后,一定要来查看一下这个文件,判断是否调整成功了。

如果method是native,Telegraf这个进程本身就会直接发送icmp包,在大多数系统上,需要进程具备CAP_NET_RAW的能力,可以在systemd的配置中增加如下内容:

[Service]
CapabilityBoundingSet=CAP_NET_RAW
AmbientCapabilities=CAP_NET_RAW

procstat

procstat用于进程监控,主要是监控cpu、mem的用量,以及监控一些系统资源的限制,我的系统里跑了两个进程,一个是ibex server,一个是ibex agentd,二进制是一个,都是ibex,只是通过传入不同的参数,启动了不同的逻辑,如下:

[root@10-255-0-34 telegraf-tmp]# ps aux|grep ibex
root      1845  0.0  0.0 112724   992 pts/0    S+   11:32   0:00 grep --color=auto ibex
root      9799  0.0  0.0 1232732 11704 ?       Sl   11月04   4:10 ./ibex agentd
mysql    12447  0.4  0.8 2026732 144000 ?      Sl   11月04  38:05 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
root     15028  0.3  0.0 1232988 15660 ?       Sl   11月07  14:37 ./ibex server

巧了,mysqld的二进制所在的路径是/usr/libexec/mysqld,这个路径中包含了ibex这个字符串,所以上例的命令也查到了mysqld,埋个伏笔。

procstat的配置,一上来就是一堆的过滤器,用过滤器来过滤进程的pid列表,如下:

# [[inputs.procstat]]
#   ## PID file to monitor process
#   pid_file = "/var/run/nginx.pid"
#   ## executable name (ie, pgrep <exe>)
#   # exe = "nginx"
#   ## pattern as argument for pgrep (ie, pgrep -f <pattern>)
#   # pattern = "nginx"
#   ## user as argument for pgrep (ie, pgrep -u <user>)
#   # user = "nginx"
#   ## Systemd unit name, supports globs when include_systemd_children is set to true
#   # systemd_unit = "nginx.service"
#   # include_systemd_children = false
#   ## CGroup name or path, supports globs
#   # cgroup = "systemd/system.slice/nginx.service"
#
#   ## Windows service name
#   # win_service = ""

注意,这些过滤器,不是与的关系,每次咱们只能选择其中一个过滤器使用,来个最简单的配置:

[[inputs.procstat]]
exe = "ibex"

exe是在通过进程名字做过滤,静态编译的语言,通常进程名就是二进制的名字,Java、Python、Perl之类的进程名字就是java、python、perl了,不具备区分度。ibex这个程序是go写的,所以这里就用exe来过滤即可。测试一下输出:

[root@10-255-0-34 telegraf-tmp]# ./usr/bin/telegraf --config etc/telegraf/telegraf.conf --test --input-filter procstat
2021-11-10T03:43:02Z I! Starting Telegraf 1.20.2
> procstat,exe=ibex,host=10-255-0-34,process_name=ibex,user=root child_major_faults=0i ... 1636515783000000000
> procstat,exe=ibex,host=10-255-0-34,pid_finder=pgrep,process_name=ibex,result=success,user=root child_major_faults=0i ... 1636515783000000000
> procstat_lookup,exe=ibex,host=10-255-0-34,pid_finder=pgrep,process_name=ibex,result=success,user=root pid_count=2i,result_code=0i,running=2i 1636515783000000000

为了看着清爽,上面例子的输出故意截断了一些内容。procstat这个measurement是进程资源相关的,procstat_lookup这个measurement是进程数量相关的。

首先,procstat_lookup中的result这个tag,要干掉,因为会造成指标标签不稳定,result_code这个field要拿来做告警,大于0就表示采集失败。

running这个field可以拿来做告警规则,如果为0表示进程挂了,但是一般进程的存活性,建议使用net_response做端口探测,不要用procstat做进程存活性判断,除非,某个进程不监听任何端口。

下面我们把pid_finder设置为native,相当于不去调用外部的pgrep工具,效率应该会高一点,测试下:

[[inputs.procstat]]
exe = "ibex"
pid_finder = "native"
tagexclude = ["result"]

[root@10-255-0-34 telegraf-tmp]# ./usr/bin/telegraf --config etc/telegraf/telegraf.conf --test --input-filter procstat
2021-11-10T04:04:16Z I! Starting Telegraf 1.20.2
> procstat,exe=ibex,host=10-255-0-34,process_name=ibex,user=root child_major_faults=0i,child_minor_faults=0i ... 1636517057000000000
> procstat,exe=ibex,host=10-255-0-34,process_name=mysqld,user=mysql child_major_faults=0i ... 1636517057000000000
> procstat,exe=ibex,host=10-255-0-34,pid_finder=native,process_name=ibex,result=success,user=root child_major_faults=0i ... 1636517057000000000
> procstat_lookup,exe=ibex,host=10-255-0-34,pid_finder=native,process_name=ibex,user=root pid_count=3i,result_code=0i,running=3i 1636517170000000000

采集的进程列表多了一个mysqld,尴尬,这个pid_finder不太靠谱呢…另外tags部分,ibex的两个进程采集的也不一致:

procstat,exe=ibex,host=10-255-0-34,process_name=ibex,user=root
procstat,exe=ibex,host=10-255-0-34,pid_finder=native,process_name=ibex,user=root

这个就有点恶心了,估计是个bug…


果然,当前我测试的版本是1.20.2,升级了一下版本,到1.20.3,tag就变成稳定的了,新的输出如下:

procstat,exe=ibex,host=10-255-0-34,process_name=ibex,user=root
procstat,exe=ibex,host=10-255-0-34,process_name=ibex,user=root

实际还是有问题,两个进程,tag是相同的,从时序数据上看,无法区分开,我们把pid_tag的配置打开:

[[inputs.procstat]]
exe = "ibex"
pid_finder = "pgrep"
pid_tag = true
tagexclude = ["result"]

输出的新内容为:

procstat,exe=ibex,host=10-255-0-34,pid=9799,process_name=ibex,user=root
procstat,exe=ibex,host=10-255-0-34,pid=15028,process_name=ibex,user=root

pid这个tag就可以区分开不同的时序数据了,不过,如果进程生命周期比较短,进程的pid就会频繁发生变化,这种情况对时序库的索引是非常不好的行为。

所以,这里建议如下: 1,如果这些filter的规则只能匹配到一个pid,那太棒了,设置pid_tag=false 2,如果这些filter的规则匹配到多个pid,那就需要把pid_tag设置为true,同时要求进程的生命周期不能太短,如果进程的生命周期太短,就不建议配置procstat做进程监控了

ok,我们修改一下filter配置,把exe去掉,用pattern来匹配:

[[inputs.procstat]]
pattern = "ibex server"
pid_finder = "pgrep"
tagexclude = ["result"]

[[inputs.procstat]]
pattern = "ibex agentd"
pid_finder = "pgrep"
tagexclude = ["result"]

输出内容如下:

[root@10-255-0-34 telegraf-1.20.3]# ./usr/bin/telegraf --config etc/telegraf/telegraf.conf --test --input-filter procstat
2021-11-10T06:38:29Z I! Starting Telegraf 1.20.3
> procstat,host=10-255-0-34,pattern=ibex\ server,process_name=ibex,user=root child_major_faults=0i ... 1636526310000000000
> procstat_lookup,host=10-255-0-34,pattern=ibex\ server,pid_finder=pgrep pid_count=1i,result_code=0i,running=1i 1636526310000000000
> procstat,host=10-255-0-34,pattern=ibex\ agentd,process_name=ibex,user=root child_major_faults=0i ... 1636526310000000000
> procstat_lookup,host=10-255-0-34,pattern=ibex\ agentd,pid_finder=pgrep pid_count=1i,result_code=0i,running=1i 1636526310000000000

嗯,这就舒服多了,有个pattern的标签可以标识出具体是哪个进程,也就无需pid的tag来做区分了。

OK,基本就介绍这么多,我也是一边测试一边记录,算是一个调研笔记。另外大家注意一下rlimit_num_fds_soft这个field,这个字段建议配置告警,因为可能会有很多机器忘记调整ulimit配置了,或者调整的不对,导致有些进程的真实fd限制仍然是1024,有了这个监控指标,我们就可以方便的知道哪些进程有问题了。

开源版
Flashcat
Flashduty