背景和特点
在一些无需 zabbix 主动监控,但是想统一纳入 zabbix 告警的场景下,zabbix的常用监控项明显不符合我们的需求,比如我的需求如下:
我们本身已经实现了 jvm 的内存 oom 监控,而 zabbix 的本身 jvm 监控扩展数据虽然是较多,但是配置麻烦,且没有 oom 这部分的监控告警,而我们就是想及时收到 oom 告警,并且想统一纳入 zabbix 监控告警,那么应该如何对接呢?
首先我不想全部更换为 zabbix 自带的 jvm 模板,缺点有这些:配置麻烦、无法实现需求、需要定时检测、创建自定义监控项、指定命令和返回内容,同样我也不想再通过自定义监控项然后使用脚本来定时获取,这也有前面部分的劣势,那么有什么方案呢?
方案研究
首先我想到的方法是能否使用 zabbix 自带的 api 直接发送一个告警内容,然后使得 zabbix 能够处理、通知,但查看了文档,发现 api 多是做一些管理上的内容、或者获取数据,想写入数据,甚至在没有主机、监控项的前提下写入告警通知完全没有找到可行的方案.
于是我开始寄托于常规的自定义监控项,但数据通过 zabbix_sender 来主动推送,但测试发现仍然较为麻烦,需要zabbix agent配置监控项,以及还有监控间隔时间的问题。因为实际上没有通过 zabbix agent主动发送、或者zabbix server 主动获取,间隔时间这块理论上是存在问题的,到最后不了了之
在一筹莫展之际了解到了 zabbix trapper 类型的监控项,了解到它是在 sender 上,原话是:
# 要将监控数据直接推送给Zabbix server 或 proxy,必须将监控项类型配置为trapper
https://www.zabbix.com/documentation/current/zh/manual/concepts/sender
这种似乎完全符合我们的需求,仅主动推送数据,无需 zabbix agent、zabbix server 介入
并且此监控项的另一个好处是 监控项的 key 直接在web定义就好了,无需在 agent 中设置,这样也是最简单的方案了,最后在设置好之后,我们通过 sender 来主动推送了一次数据,在此 主机 的最新数据中成功更新
工具的参数使用方法:
# -z 接 zabbix server
# -s 接 agent 配置文件中的主机名
# -k 接 定义的监控项,在web配置即可,无需agent配置文件中处理
# -o 接内容
./zabbix_sender -z 192.168.3.30 -p 10051 -s host-192.168.10.120 -k custom.jvm_oom -o 1
最后在测试数据更新无问题后,我们再制作一个触发器,当值符合后即告警推送
基于OOM告警的示例
需要考虑的是,容器环境下N多个容器需要做 OOM 告警,但是zabbix主要是对接机器的,容器肯定是比机器多,那么如何规划呢?所以我考虑的是只选择一台机器做监控项,然后告警的时候取不同容器名来区分问题,实际配置大致如下
- 容器方面,需要加入名称作为环境变量,以OOM的时候,触发脚本可以拿到容器名发送给 zabbix
- zabbix_server 使用采集器的监控项,数据类型为字符串
- 客户端使用
zabbix_sender
推送数据,故障数据格式SERVICENAME_DATE_1
,恢复数据格式SERVICENAME_DATE_0
- 接下来是触发器配置
- 触发器名称为
OOM-find {ITEM.VALUE}
这样多个可以标志不同的容器环境 - 触发器表达式为:
right(last(/Template OS Linux by OOM/monitor[OOM]),1)=1
,取最右边的值为 1,则表示有问题 - 问题事件生成模式 选择 多重,这样不同名称的容器会生成不同的问题,否则跟CPU、内存告警一样,如果一直超过90%,那么只会有第一个告警
- 触发器恢复较为复杂,理论如下:OOM告警后,恢复途径有几个,一是重启tomcat,然后在这时候自动给 zabbix 再发一个恢复(需要判断是否OOM过),二是手动上 zabbix 关闭问题,三是其他触发关闭 (与方法一类似),但明显前面两个都比较麻烦。所以考虑使用其他办法触发,于是选择在发送告警等待60秒后再给zabbix发送恢复(根本的需求是收到告警,而不关心zabbix上显示)
- 恢复配置: 时间成功迭代 选择 恢复表达式
- 恢复表达式内容:
`right(last(/Template OS Linux by OOM/monitor[OOM]),1)=0`
- 事件成功关闭 选择 所有问题如果标签值匹配
- 接下来就是恢复的第二个问题,如何恢复给定的容器,如果 con1,con2 都告警了,那么会有两条记录,想要恢复触发只关闭相关的问题,需要使用到标记
- 在 7 选择 所有问题如何标签值匹配后,需要填入一个标签值,也就是字段名,例如:name
- 然后在触发器的右边栏添加一个触发器标签,名称填入 name,值使用正则过滤出容器名,如果按照我上面的数据格式,则是
`{ITEM.VALUE}.regsub("(.*)_(.*)_(.*)",\1)`
,表示匹配三段下划线然后拿到第一段的内容 - 在配置 10 以后,测试触发、恢复数据,应该没问题了
- 标签到底是如何生效的呢? 通过观察,触发问题的时候就会根据标签拿到值,当恢复数据到达的时候,同样也会拿到值,如果两个值匹配,那么就会恢复值相同的全部问题
评论