进程监控:Zabbix 和 Nightingale 生态对比

Zabbix 监控进程和 Nightingale 监控进程的原理是一样的,但是产品体验很不相同,Zabbix 更多的是通过页面管理,Nightingale 更多的是 Prometheus 生态的玩法,靠 agent 配置驱动,采集相关进程的监控数据。

作者 巴辉特

Zabbix 监控进程和 Nightingale 监控进程的原理是一样的,但是产品体验很不相同,Zabbix 更多的是通过页面管理,Nightingale 更多的是 Prometheus 生态的玩法,靠 agent 配置驱动,采集相关进程的监控数据。本文分别演示两个产品的配置方式,帮助大家更好的理解两者的区别。

监控进程的原理

所谓的进程监控,通常是指监控进程的数量以及进程占用的 CPU、内存等资源。比如监控 Nginx 进程,平时 Nginx 进程数是 8,如果进程数不是 8 了,就不符合预期,同时,我们也希望知道 Nginx 进程占用了多少 CPU、内存等资源,甚至想知道 Nginx 进程的句柄限制等。

在 Linux 系统中,进程的信息都可以通过 /proc 文件系统获取,比如 /proc/1 是进程 1 的信息,/proc/1/status 是进程 1 的状态信息,/proc/1/cmdline 是进程 1 的启动命令等。所以,监控进程的原理就是读取 /proc 文件系统中的信息,然后计算出我们需要的监控数据。

这里我给大家看一下样例:

root@ubuntu-linux-22-04-desktop:~/works# ps aux|grep zabbix_agent
zabbix    116675  0.0  0.0  21688  4140 ?        S    Nov02   0:00 /usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf
zabbix    116678  0.0  0.0  21688  2588 ?        S    Nov02   4:00 /usr/sbin/zabbix_agentd: collector [idle 1 sec]
zabbix    116679  0.0  0.0  23340  4740 ?        S    Nov02   2:03 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection]
zabbix    116680  0.0  0.0  23344  4736 ?        S    Nov02   2:02 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection]
zabbix    116681  0.0  0.0  23340  4736 ?        S    Nov02   2:06 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection]
zabbix    116682  0.0  0.0  23340  4736 ?        S    Nov02   2:03 /usr/sbin/zabbix_agentd: listener #4 [waiting for connection]
zabbix    116683  0.0  0.0  23340  4740 ?        S    Nov02   2:04 /usr/sbin/zabbix_agentd: listener #5 [waiting for connection]
zabbix    116684  0.0  0.0  23344  4732 ?        S    Nov02   2:06 /usr/sbin/zabbix_agentd: listener #6 [waiting for connection]
zabbix    116685  0.0  0.0  23344  4732 ?        S    Nov02   2:06 /usr/sbin/zabbix_agentd: listener #7 [waiting for connection]
zabbix    116686  0.0  0.0  23344  4732 ?        S    Nov02   2:04 /usr/sbin/zabbix_agentd: listener #8 [waiting for connection]
zabbix    116687  0.0  0.0  23344  4732 ?        S    Nov02   2:05 /usr/sbin/zabbix_agentd: listener #9 [waiting for connection]
zabbix    116688  0.0  0.0  23340  4736 ?        S    Nov02   2:05 /usr/sbin/zabbix_agentd: listener #10 [waiting for connection]
zabbix    116689  0.0  0.0  22228  3808 ?        S    Nov02   3:27 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec]
root     1789894  0.0  0.0   9016  1860 pts/1    S+   11:43   0:00 grep --color=auto zabbix_agent
root@ubuntu-linux-22-04-desktop:~/works# head -n 3 /proc/116675/status
Name:	zabbix_agentd
Umask:	0002
State:	S (sleeping)
root@ubuntu-linux-22-04-desktop:~/works# cat /proc/116675/cmdline | tr '\0' ' '; echo
/usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf

上例中,我首先通过 ps aux|grep zabbix_agent 命令找到了 zabbix_agentd 进程的 PID,然后通过 /proc/116675/status 文件查看了 zabbix_agentd 进程的状态信息,通过 /proc/116675/cmdline 文件查看了 zabbix_agentd 进程的启动命令。

其中 status 文件中的 Name 字段是进程的名字,我们监控进程的时候,经常靠这个字段来做匹配,Name 字段是有长度限制的,一般是 15 个字符。cmdline 文件中是进程的启动命令,但是这个 cmdline 的内容是以 \0 分隔的,所以我用 tr '\0' ' ' 命令将 \0 替换为空格,方便大家查看。\0 是不可见不可打印的字符,如果你直接 cat /proc/116675/cmdline,会看到是一长串字符串,没有分隔。

要监控什么进程,用户得告诉监控系统,怎么告诉?本质就是告诉监控系统想要监控的进程的 Name 是啥,cmdline 是啥,即传入一些匹配条件,匹配到的进程就是用户要求监控的进程。

Zabbix 监控进程

这里我在 Zabbix 中创建了一个监控项,监控 zabbix_agentd 进程的数量。如下图所示:

Zabbix item list

首先是进入 Hosts 菜单,然后找到我要监控的机器,点击 Items 进入机器的监控项列表,然后点击 Create item 创建一个监控项。创建的时候最最核心要填写的是 Key,我这里写的 Key 是 proc.num[zabbix_agentd],这个 Key 的意思是监控 zabbix_agentd 进程的数量。这个 Key 是 Zabbix 自带的,不需要用户自己写,只需要填写好参数即可。完事点击 Test,就可以发起一个测试请求,看看监控项是否正常。

Zabbix item test

如果一切正常,就可以创建告警规则了,在 Zabbix 中称为 Trigger,如下图所示:

Zabbix Trigger

这里我故意把阈值设置为等于 13 就告警,让它立马产生告警,因为我的环境里,这个值就是 13。上面可以看到 Value 是 PROBLEM,表示这个监控项已经触发了告警。

Zabbix 告警设计小结

对于 Zabbix 内置的指标,整体还是比较丝滑的,不需要改配置文件,在页面上就可以完成。当然,Zabbix-Agent 毕竟无法采集所有数据,有些数据还是需要用户自己写脚本来采集,这个时候就需要改配置文件了。

Zabbix-Agent 采集的任何数据都有一个称为 Key 的东西作为标识,Key 对应的监控数据会因为参数不同而结果不同,比如 proc.num[zabbix_agentd]proc.num[nginx],这两个 Key 都是监控进程数量的,但是参数不同,一个是 zabbix_agentd,一个是 nginx。

姑且可以理解为:Zabbix-agent 提供了一个接口,然后远端的 Zabbix-Server 通过这个接口获取监控数据,而要获取哪些监控数据,肯定是需要通过参数传给 Zabbix-agent 的,这个参数就是 Key 以及 Key 的参数。

其实 proc.num 还有别的参数,比如 proc.num[,,run],这个参数的意思是监控所有 run 状态的进程的数量。

proc.num 实际有多个参数,其调用格式为:proc.num[<name>,<user>,<state>,<cmdline>,<zone>],各个参数的含义,可以参考 Zabbix 官方文档。

  • name - the process name (default is all processes);
  • user - the user name (default is all users);
  • state - possible values:
    • all (default),
    • disk - uninterruptible sleep,
    • run - running,
    • sleep - interruptible sleep,
    • trace - stopped,
    • zomb - zombie;
  • cmdline - filter by command line (it is a regular expression);
  • zone - the target zone: current (default), or all. This parameter is supported on Solaris only.

这种 Key 的设计,今天来看,实际是不太合理的,尤其是做聚合计算的时候,因为参数和 Key 是没有结构化区分的,比如我想计算某个服务的所有接口的平均响应时间,这个时候,我就需要写很多 Key,然后做聚合计算,这个时候,Key 的设计就显得不够灵活了。而 OpenTSDB、Prometheus 等设计的 metric_name + 多维度标签的方式,则更为方便实现这类需求。

联系我们交流

Nightingale 监控进程

夜莺监控 Nightingale 其实并不能采集监控数据,所以说用 Nightingale 来监控什么什么,其实不太合理,Nightingale 更多的是一个告警引擎,监控数据的采集是通过 Prometheus 的 Exporter 来完成的,或者通过 Telegraf、Categraf、Datadog-Agent 等各类采集器来完成的。

我这里以 Categraf 来举例,Categraf 是一个 Go 语言编写的监控数据采集器,支持很多插件,监控进程的插件叫 procstat,如下图是 procstat 的配置文件:

[[instances]]
# # executable name (ie, pgrep <search_exec_substring>)
search_exec_substring = "zabbix_agentd"

# # pattern as argument for pgrep (ie, pgrep -f <search_cmdline_substring>)
# search_cmdline_substring = "n9e server"

# # windows service name
# search_win_service = ""

# # search_exec_regexp: Use a regular expression to match the executable path
# # executable name filter to regexp (like "ps -e | grep -E <search_exec_regexp>" but using re2 regexp )
# search_exec_regexp = ""

# # search_cmdline_regexp: Use a regular expression to match the command line
# # executable name filter to regexp (like "ps -ef | grep -E <search_cmdline_regexp>" but using re2 regexp )
# search_cmdline_regexp = ""

# # [option] search process with specific user
# search_user = ""


# # mode to use when calculating CPU usage. can be one of 'solaris' or 'irix'
# mode = "irix"

# sum of threads/fd/io/cpu/mem, min of uptime/limit
gather_total = true

# will append pid as tag
gather_per_pid = true

gather_more_metrics = [
    "threads",
    "fd",
    "io",
    "uptime",
    "cpu",
    "mem",
    "limit"
]

上例中也是采集 zabbix_agentd 进程的数据,不止可以采集 zabbix_agentd 的进程数量,也可以采集其 threads 数量、fd 数量、io 情况、cpu 占用情况、内存占用情况等。要采集什么监控数据,用户就只需要配置这么一个配置文件即可,如果要采集多个进程,就拷贝 [[instances]] 配置块即可。

Zabbix 要采集什么数据基本都是需要在 WEB 上配置的,而 Prometheus 生态要采集什么数据,大都是通过配置采集器来完成的,不但数据的采集,数据的处理、转换等,也都是在采集器中完成的。

配置完成 procstat.toml 之后,执行如下命令可以查看采集到了哪些指标:

./categraf --test --inputs procstat

如果一切正常,就可以使用 systemd 之类的进程管理器启动 Categraf,让 Categraf 把采集到的数据通过 remote write 协议推给远端的 Nightingale,或者直接推给远端的时序库都是可以的。(远端地址是配置在 Categraf 的主配置文件中的)

数据采集之后,就可以在 Nightingale 中配置告警规则了。一般公司会监控很多进程,没必要为每个进程都分别配置一条告警规则,在 Prometheus 生态里,可以写这么一条 PromQL 即可对所有 Categraf 采集的进程实现进程存活监控:

procstat_lookup_count != 0

总结

本文围绕进程监控这个需求,演示了 Zabbix 和 Nightingale 两个产品的配置方式,希望能帮助大家更好的理解两者的区别。对于刚接触监控领域的朋友而言,总之觉得能监控进程存活即可,但从笔者而言,这两个产品的设计截然不同,了解他们的思路非常有意思,对于未来我们的选型也至关重要。

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云