自动发现(LLD)提供了一种在计算机上为不同实体自动创建监控项,触发器和图形的方法。
例如,Zabbix可以在你的机器上自动开始监控文件系统或网络接口,而无需为每个文件系统或网络接口手动创建监控项;还可以配置Zabbix根据定期执行发现后的得到实际结果,来移除不需要的监控。
除了 Linux 系统自带的发现字段外,还支持通过 snmp OID 来进行自动发现
用户可以自己定义发现类型,只要脚本的返回值是遵循特定的 JSON 格式。
配置自动发现过程的一般如下:
首先,用户在“配置”→“模板”→“发现”列中创建一个发现规则。发现规则包括(1)发现必要实体(例如,文件系统或网络接口)的项 和(2)应该根据该项的值创建的监控项,触发器和图形的原型。
下面表达的 zabbix 内置关键字
可以理解为 zabbix 底层的一个函数/接口,用户可以通过调用这个函数/接口(或调用时为其传参)来获得指定格式的值;如果需要自定义发现规则, zabbix 内置关键字
可以是用户自己编写的脚本/函数/接口。
SNMP OID 自动发现
以一个通过 SNMP 发现接口入方向流量的例子作为解析,首先创建一个模板:
然后找到刚才创建的模板,进行编辑:
进入模板后,创建一个自动发现规则:
填入如下内容:
上图中:
-
Key
字段:net.if.discovery
是为了标识自动发现规则的名字,一般使用.
分隔的字符来方便理解这个规则的作用(当然你也可以写你觉得顺口好记的名字或者分隔符,如_
、-
等) -
SNMP OID
字段:discovery
为 zabbix 内置关键字,可以理解为一个函数,将后面[ ]
的值作为参数传入,参数的格式是由discovery
预先规定好的(如果是自己定义的函数,可以按照自己的喜好来写)。
其中{#IFDESCR}
为变量名称,1.3.6.1.2.1.2.2.1.2
为获取这个变量值的 SNMP OID 值,执行类似 snmpwalk 的操作,获取设备的信息。
这个步骤用来获取自动发现规则中的键值:
discovery[{#IFDESCR},1.3.6.1.2.1.2.2.1.2,{#IFTYPE},1.3.6.1.2.1.2.2.1.3]
的行为约等于:
{#IFDESCR} = snmpwalk -v 2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.2
{#IFTYPE} = snmpwalk -v 2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.3
因为 snmpwalk 遍历出来的值很多,假设 snmpwalk 出来的结果为:
$ snmpwalk -v 2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.2
1.3.6.1.2.1.2.2.1.2.1 = STRING: G1/0/1
1.3.6.1.2.1.2.2.1.2.2 = STRING: G1/0/2
1.3.6.1.2.1.2.2.1.2.3 = STRING: G1/0/3
$ snmpwalk -v 2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.3
1.3.6.1.2.1.2.2.1.3.1 = STRING: route
1.3.6.1.2.1.2.2.1.3.2 = STRING: bridge
1.3.6.1.2.1.2.2.1.3.3 = STRING: ppp
snmp 一般是靠索引来定位的,zabbix 内置关键字 discovery
为返回结果自动添加了索引,所以discovery[{#IFDESCR},1.3.6.1.2.1.2.2.1.2,{#IFTYPE},1.3.6.1.2.1.2.2.1.3]
最终获取出来的结果为(JSON格式也是定义好的,我们只是填充了值):
{
"data": [
{
"{#SNMPINDEX}": "1",
"{#IFDESCR}": "G1/0/1",
"{#IFTYPE}": "route"
},
{
"{#SNMPINDEX}": "2",
"{#IFDESCR}": "G1/0/2",
"{#IFTYPE}": "bridge"
},
{
"{#SNMPINDEX}": "3",
"{#IFDESCR}": "G1/0/3",
"{#IFTYPE}": "ppp"
}
]
}
zabbix 规定了自动发现规则必须是上面这种 JSON 格式,即:以 data
为字典的键,值为字典组成的列表,字典中为用户自定义的变量和根据关键字获取到的值。(实际测试,自定义的脚本只有值(字典组成的列表)也是可以的)。
接下来就是添加【监控项原型】,原型顾名思义就是一个模板,用来生成一系列监控项。
上图中:
-
Key
字段:if.in.bits
为了标识这个监控项的名字(同net.if.discovery
),后面跟着自动发现规则中定义的变量,用来自动生成监控项时区分出不同的接口 -
SNMP OID
字段:使用1.3.6.1.2.31.1.1.1.6
这个 OID 在加上具体接口的 index,即内置discovery自动生成的变量{$SNMPINDEX}
,来获取指定接口的入方向流量
自动发现规则 + 监控项原型,两者共同工作,原理大致为:
- discovery 获得 SNMPINDEX 和 IFDESCR 对应信息,如
{ {#SNMPINDEX}: 1, {#IFDESCR}: “G1/0/1”,
{#SNMPINDEX}: 2, {#IFDESCR}: “G1/0/2”} - 自动发现规则获取接口列表后,根据监控项原型中的 SNMP OID 获取流量,
为当前设备其中一个接口生成监控项如:if.in.bits.G1/0/1:102400
① 监控项的 key:if.in.bits[G1/0/1] 由第一步自动发现和监控项原型 key 拼接得到
② 流量信息102400 由 1.3.6.1.2.31.1.1.1.6.1 这个 OID 取得(类比snmpwalk)
将这个自动发现规则应用在设备上之后,可以获得三个监控项,分别是:
名称 | key | 流量获取方法 |
|
| 通过 OID |
|
| 通过 OID |
|
| 通过 OID |
以上是就是一个通过 snmp oid 获取自动发现接口入方向流量的例子。
自定义自动发现规则
为了加深理解,可以自己手动添加一个自定义发现规则。
以一个自动返回 ping 结果的自动发现规则为例,首先编写如下脚本,返回的 JSON 需要遵循固定格式:
#!/root/bin/python3
import sys
import json
import subprocess
dns_ip_map = {
"baidu" : "180.76.76.76",
"ali" : "223.5.5.5",
"tencent" : "119.29.29.29",
}
def ping(ip):
cmd = "ping -c 2 -W 2 %s" %(ip)
result = subprocess.getstatusoutput(cmd)[0]
return result
if __name__ == "__main__":
# 不加任何参数的时候,返回自动发现的变量,遵循指定的 JSON 格式,经 zabbix 5.0 版本测试
# 仅返回列表,没有 `data` 作为键也可以
if len(sys.argv) == 1:
lld_key_list = [
{"{#DNS_IP}": ip } for ip in dns_ip_map.keys()
]
print(json.dumps(lld_key_list))
# 传入参数的时候,即:将变量 {$DNS_IP} 对应的值传入的时候,可以获取到对应的执行结果
if len(sys.argv) == 2:
result = ping(dns_ip_map.get(sys.argv[1]))
print(result)
脚本有两个功能:
- 不加参数运行时输出自定义变量列表,可以作为【自动发现规则】的 key
- 加参数运行时输出指定 ip 的 ping 结果,ip 不存在时返回 -1,可以作为【监控项原型】的 key
执行结果如下:
# 直接执行
python3 dns_ping.py
[{"{#DNS_IP}": "baidu"}, {"{#DNS_IP}": "ali"}, {"{#DNS_IP}": "tencent"}]
# 加参数,网络是通的,返回 0
python3 ./dns_ping.py baidu
0
# 加参数,ip 不存在,返回 -1
python3 ./dns_ping.py baidu111
-1
一般情况下,实现这两个功能的脚本应该是分开的,示例为了简单放在一起了。
接下来在添加自动发现规则,以在 agent 添加自定义 key 为例:
# 修改 agent 的配置文件,添加客户端自定义 key,允许传参
AllowRoot=1
UserParameter=dns_ping[*],/root/dns_ping.py $1
页面上添加自动发现规则:
添加完成后,点进规则里面,添加【监控项原型】
添加完成后,手动执行一下发现规则:
查看自动发现的监控项:
查看获取到的数据: