研究一下Zabbix 3.4的服务主动发现功能

我所在组一直以来对不同服务的监控方针是:针对不同的服务(比如nginx,tomcat,mysql等等)创建不同的template,然后将这个template应用于对应的服务器上,在每一个template里添加具体的item和trigger。今天尝试一下全新的自动发现Low-level discovery(LLD)。

LLD对返回的内容有一个json格式,这个json格式必须要被zabbix-server识别。所以我们需要准备一个脚本,脚本的结果就是生成这个json。本文zabbix-serverzabbix-agent的版本都是3.4.15

服务器内部操作

首先在被监控服务器里,创建一个脚本/etc/zabbix/script/discovery_services.sh,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
proarray=($(find /var/run/ -name "*.pid"|egrep -v '(rpc|php_daemon|haldaemon|irqbalance|console-kit-daemon)' |awk -F'/' '{print $NF}'|awk -F'.' '{print $1}')) # 排除不监控的服务

length=${#proarray[@]} #${#var}是用来取长度
printf "{\n"
printf '\t'"\"data\":["
printf "\t"
printf '\n\t\t{'
printf "\"{#PRO_NAME}\":\"iptables\"}" #必须要添加的iptables
printf ","
for ((i=0;i<$length;i++))
do
printf '\n\t\t{'
printf "\"{#PRO_NAME}\":\"${proarray[$i]}\"}" #for循环取每一项
if [ $i -lt $[$length-1] ];then
printf ','
fi
done
printf "\n\t]\n"
printf "}\n"

这里我们设定将所有的进程文件的pid统一放到/var/run下,这样能取到所有进程的文件。脚本里的{PRO_NAME}这个就是自动发现规则中的宏变量,另外这个脚本返回的是符合zabbix-server的json格式。如图:
akb48

同时在加上一个判断进程是否运行的脚本/etc/zabbix/script/program_status.sh,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
procjetName="${1:-NULL}"
LOCK_PATH="/var/lock/subsys"
RUN_PATH="/var/run"
ret_ok=1
ret_critical=3
ret_unknown=4

if [[ ${procjetName} == "NULL" ]] ; then
echo ${ret_unknown}
fi

if [ -f "${LOCK_PATH}/${procjetName}" ] || [ -f "${RUN_PATH}/${procjetName}.pid" ] || [ -f "${RUN_PATH}/${procjetName}/${procjetName}.pid" ] ; then
echo ${ret_ok}
else
echo ${ret_critical}
fi

这个脚本的结果就是:服务若存在就返回1,否则返回3。如图:
akb48

然后在zabbix_agentd.conf里添加两个items,如下:

1
2
UserParameter=services.scan,/bin/bash /etc/zabbix/script/discovery_services.sh
UserParameter=services.status[*],/bin/bash /etc/zabbix/script/program_status.sh $1

服务端操作到此结束。

WEB端操作

添加自动发现规则与添加item很相似,先configuationtemplatescreate template:
akb48

akb48

在新生成的“服务进程自动发现”的template里添加Discovery rules,设定Key是Services.scan如下:
akb48

上面那个Services.scan到时候要写到zabbix-agent.conf里的,切记保持一模一样。然后在点击Filters标签页,如下:
akb48

此处的{PRO_NAME}就是我们的脚本返回的变量,保存之。然后创建一个item prototypes,如图:
akb48

此处需要注意的$1键值是我们之前定义的,也即是服务名,保存之。

然后创建一个trigger prototype,如图:
akb48

图中的解释器是:

1
({auto Service discovery:services.status[{#PRO_NAME}].last()}<>1) and ({auto Service discovery:services.status[{#PRO_NAME}].last(,1h)}=1)

这句话的意思是“最后状态不是1同时一小时前的状态是1”的服务出现了问题会发生报警,这主要是因为当启动一些临时进程,比如yum,当yum完毕了之后,进程就不存在了,那么如果只是通过判断进程数的话,就会报yum is down

至此web端配置结束。

错误解决

如果web界面出现了Value should be a JSON object.的错误,如图:
akb48

跑到zabbix-server去zabbix-get一下发现有错误:
akb48

将mdadm这个文件夹改成755即可。回到web页面查看一下latest data:
akb48

参考资料

https://www.zabbix.com/documentation/3.4/zh/manual/discovery/low_level_discovery
https://www.xiaomastack.com/2015/07/04/zabbix-auto-tcp-port/
https://www.cnblogs.com/fengbohello/p/5954895.html (Linux Shell 截取字符串)
http://caosiyang.github.io/2017/03/06/zabbix-get-value-error/

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------