snmp插件
snmp
snmp 插件之前秦老师已经整理过很详细的文章了,这里就不再赘述了,直接访问:
translator
v0.3.44及以后的版本支持gosmi, 之前的版本只支持netsnmp作为translator。translator是配置文本类型的oid时做一次snmptranslate,如果配置为数字型的oid时,是不需要做snmptranslate的。
oid=".1.3.6.1.2.1.2.2.1.10"
# 不调用translatoroid="IF-MIB::ifInOctets"
# 调用translator
使用gosmi时要注意,path中一定要包含所有依赖的mib文件,不是只放你的私有mib路径就可以了。
translator="gosmi"
path = ["/usr/share/snmp/mibs", "/path/to/your/other/mibs"]
max_repetitions
一次读取的对象数,但是有的设备有限制,超过限制无数据返回。 建议保持默认值 max_repetitions = 10
unconnected_udp_socket
当设置为真时,SNMP 响应将接受来自任何地址响应,而不仅仅是请求的地址的响应。 一般juniper设备采集不到数据时,请设置true
不同的field
配置中支持两种field
instances.field
instances.table.field
使用snmpget可以获取到值的oid,用instances.field
。 用snmpwalk获取数据的oid使用instances.table.field
. 使用instances.table.field
要先配置一个instances.table
, 哪怕是一个虚拟表,但是不能少。
虚拟表
[[instances.table]]
name = "interface"
当intstances.table
不设置oid时候,categraf
不会去采集这个table. 此时instances.table
是一张虚拟表,用于聚合它的instances.table.field
,这样它的instances.table.field指标都会带上前缀 interface_
index_as_tag
当index_as_tag
只能用在instances.table
,当设置为true时,表示会附加oid对应的index作为标签。
IF-MIB::ifInOctets
这张表返回数据如下
# $snmpwalk -v 2c -c private 127.0.0.1 IF-MIB::ifInOctets
IF-MIB::ifInOctets.1 = Counter32: 2929719593
IF-MIB::ifInOctets.2 = Counter32: 4020819726
IF-MIB::ifInOctets.3 = Counter32: 0
IF-MIB::ifInOctets.4 = Counter32: 816099251
IF-MIB::ifInOctets.5 = Counter32: 0
IF-MIB::ifInOctets.7 = Counter32: 184035929
IF-MIB::ifInOctets.9 = Counter32: 182159256
IF-MIB::ifInOctets.11 = Counter32: 161707290
IF-MIB::ifInOctets.13 = Counter32: 184387456
IF-MIB::ifInOctets.15 = Counter32: 184936929
IF-MIB::ifInOctets.17 = Counter32: 185552762
IF-MIB::ifInOctets.19 = Counter32: 182004023
IF-MIB::ifInOctets.21 = Counter32: 184076634
IF-MIB::ifInOctets.23 = Counter32: 184995236
IF-MIB::ifInOctets.25 = Counter32: 181069060
IF-MIB::ifInOctets.27 = Counter32: 162922666
IF-MIB::ifInOctets.29 = Counter32: 162307954
附加index 作为label 与得到的指标如下
[[instances.table]]
name = "interface"
index_as_tag=true # 附加index
[[instances.table.field]]
oid="IF-MIB::ifInOctets"
# oid=".1.3.6.1.2.1.2.2.1.10"
name="ifInOctets"
指标
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=2 4156981106
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=9 182362007
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=19 182206658
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=23 185201785
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=29 162490093
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=21 184282189
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=11 161889686
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=13 184592291
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=27 163104850
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=5 0
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=7 184241127
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=25 181272715
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=4 816997503
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=1 2933872158
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=17 185759529
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=3 0
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test index=15 185143913
不使用index_as_tag=true
得到的指标
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 162791450
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 162191982
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 182697739
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 182542638
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 0
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 0
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 186101019
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 184581212
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 2940870282
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 181609012
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 185486731
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 163407370
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 84568089
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 185543869
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 818473860
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 184622605
snmp_interface_ifInOctets agent_host=127.0.0.1 agent_hostname=test 184932731
指定index的后缀/长度(任选其一 不是非要放到一起用)
注:index
=返回的oid-查询oid,例如,查询oid是.1.2.3
,返回的oid是.1.2.3.4.5
那index
就是.4.5
- oid_index_length=10 # 表示取index的前10位
- oid_index_suffix = “.5” # 表示将index的后缀.5去掉
值转换
当oid对应的值是ip/mac/hex 特殊类型时需要进行转换
[[instances.table.field]]
oid = ".1.3.6.1.4.1.2636.5.1.1.2.1.1.1.11"
name = "peer_addr"
conversion = "ipaddr"
is_tag = true
这样会将.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.11 对应的值 转换为ip 作为label附加到指标上。 conversion支持的类型转换包括
- conversion=“ipaddr” # 将值转为ip地址
- conversion=“hwaddr” # 将值转为mac地址
- conversion=“float(X)” # 将值转为float,并保留X位小数
- conversion=“float” # 将值转为float, 相当于float(0)
- conversion=“int” # 将值转为int
- conversion=“byte” # 将
xxGB xx GB xxKiB
转换为float类型,单位byte - conversion=“hextoint:X:Y” # 将hex值转为int.
hextoint:LittleEndian:uint64
将hex值按照小端序转为无符号64位inthextoint:BigEndian:uint32
将hex值按照大端序转为无符号32位int
relabel
比如index原始值如下, 想把2个字段前3位1.1.4.和1.2.16.去掉,生成新标签peer_addr
# 原始值
index="1.2.16.36.4.255.64.0.1.0.99.0.0.0.0.0.0.0.2"
index="1.1.4.103.140.146.151"
# 目标值
peer_addr="36.4.255.64.0.1.0.99.0.0.0.0.0.0.0.2"
peer_addr="103.140.146.151"
按照如下配置, 即可得到
[[instances.relabel_configs]]
source_labels = [ "index"]
target_label = "peer_addr"
#separator = "/"
regex = "\\d+\\.\\d+\\.\\d+\\.(.*)"
action = "replace"
replacement = "$1"
熟悉prometheus relabel的都知道,上面只是得到了peer_addr,原始的index还在。如果不想要index label那么再配置一条
[[instances.relabel_configs]]
regex = "index"
action = "labeldrop"
两张表关联
两张表关联查询,用到的主要配置secondary_index_table
和secondary_index_use
或secondary_outer_join
,再辅以oid_index_length
oid_index_suffix
.
secondary_index_table
放在指定的oid下,表示这个oid的index所对应值(并非index本身)会作为令一张表的index引用, 我们称这张表为第一张表secondary_index_use
放在指定的oid下, 表示这个oid的index等于secondary_index_table
的index对应的值(并非index) 我们称这张表为第二张表secondary_outer_join
跟secondary_index_use
类似,如果这里设置为true,第二张表中如果出现了第一张表index的值对应不到的情况,那第二张表的index会展示位Secondary.xxxx
接下来看一个比较综合的case, 假设有两张表需要做关联 , 比如bgp中peer_index对应的oid是.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.14, 另一张receive表对应的oid是.1.3.6.1.4.1.2636.5.1.1.2.6.2.1.7,想对两张表做关联,peer_index表的index中第一位作为 receive表的index的一部分。
先看peer_index的返回
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.1.128.1.130.176.1.128.1.130.178 = 0
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.1.128.1.130.176.1.128.1.130.179 = 1
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.1.128.1.130.176.1.128.1.130.180 = 2
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.2 = 3
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.3 = 4
.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.14.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.4 = 5
再看receive表的返回
.1.3.6.1.4.1.2636.5.1.1.2.6.2.1.7.0.1.1 = 2071
.1.3.6.1.4.1.2636.5.1.1.2.6.2.1.7.3.2.1 = 0
两张表的index和返回值对比
.0.1.128.1.130.176.1.128.1.130.178=0
.0.1.128.1.130.176.1.128.1.130.179=1
.0.1.128.1.130.176.1.128.1.130.180=2
.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.2=3
.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.3=4
.0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.4=5
...
.0.1.1=2071
.3.2.1=0
这两张表关联查询,那就用peer_index对应的值0/1/2/3/4/5 和rececive表中的index 0.1.1/3.2.1 关联匹配,但是因为他们长度不同(peer_index的值只有一位),所以长度对齐就用到了一个oid_index_length 配置。 比如 oid_index_length=1 表示receive表的index的第一位只要匹配到0/1/2/3/4/5 中任意一位就认为匹配成功。
peer_index的配置如下
[[instances.table.field]]
oid = ".1.3.6.1.4.1.2636.5.1.1.2.1.1.1.14"
name = "peer_index"
is_tag = true
secondary_index_table = true # 这个表的index对应的值0/1/2/3/4/5要被其他表使用
receive表配置如下
[[instances.table.field]]
oid = ".1.3.6.1.4.1.2636.5.1.1.2.6.2.1.7"
name = "receive_total_prefix"
oid_index_length=1 # 只取index的第一位(因为上面的index得值只有一位)
secondary_index_use = true # 使用上面指定的index
这样最终取到值
snmp_juniper_bgp_prefix_receive_total_prefix{index="0.1.128.1.130.176.1.128.1.130.178", peer_index="0"} 2071
snmp_juniper_bgp_prefix_receive_total_prefix{index=".0.2.38.4.9.128.224.5.47.255.0.0.0.0.0.0.0.1.2.38.4.9.128.224.5.47.255.0.0.0.0.0.2", peer_index="3"} 0
oid_index_suffix 用法
oid_index_suffix 用于两张表的index 相差一个固定后缀的场景。配置后,长的index后缀被trim掉,与短的index匹配一致,这样短index对应的字段即可作为长index字段的标签。
[[instances.table.field]]
oid = ".1.3.6.1.4.1.30065.4.1.1.2.1.2"
name = "addr_type"
is_tag = true
[[instances.table.field]]
oid = ".1.3.6.1.4.1.30065.4.1.1.2.1.10"
name = "peer_as"
is_tag = true
[[instances.table.field]]
oid = ".1.3.6.1.4.1.30065.4.1.1.8.1.3"
name = "receive_total_prefix"
oid_index_suffix=".1.1"
[[instances.relabel_configs]]
source_labels = ["peer_as"]
regex = ".+"
action = "keep"
新特性
categraf从v0.3.9版本开始,支持
- 正则过滤端口号、端口类型等
- 支持批量设置label
过滤
在table section中设置如下
[[instances.table]]
oid = "IF-MIB::ifTable"
name = "interface"
inherit_tags = ["source"]
filters = ["A:ifIndex:^2$","B:ifDescr:^eno.*", "C:ifOperStatus:1"]
filters_expression = "(A && B) || C"
oid
定义了采集的对象IF-MIB::ifTable
name
定义指标名称inherit_tags
定义了要继承的标签,这里继承了source标签 就是把前面的source=xxxx
附加到指标上filters
定义表达式A 是匹配ifIndex == 2
, 表达式B是匹配ifDescr
为eno
开头的对象,C是匹配ifOperStatus
为1的对象,filters_expression
定义了过滤表达式,表示filters
中表达式的逻辑关系, 这里是A和B的结果取交集,再和C取并集
假设oid对应的数据如下,
IF-MIB::ifIndex.1 = INTEGER: 1
IF-MIB::ifIndex.2 = INTEGER: 2
IF-MIB::ifIndex.3 = INTEGER: 3
IF-MIB::ifIndex.6 = INTEGER: 6
IF-MIB::ifIndex.7 = INTEGER: 7
IF-MIB::ifIndex.9 = INTEGER: 9
IF-MIB::ifIndex.10 = INTEGER: 10
IF-MIB::ifIndex.1210 = INTEGER: 1210
....
IF-MIB::ifDescr.1 = STRING: lo
IF-MIB::ifDescr.2 = STRING: eno1
IF-MIB::ifDescr.3 = STRING: eno2
IF-MIB::ifDescr.6 = STRING: virbr0
IF-MIB::ifDescr.7 = STRING: tun0
IF-MIB::ifDescr.9 = STRING: macvtap1
IF-MIB::ifDescr.10 = STRING: docker0
IF-MIB::ifDescr.1210 = STRING: tun1
....
IF-MIB::ifOperStatus.1 = INTEGER: up(1)
IF-MIB::ifOperStatus.2 = INTEGER: up(1)
IF-MIB::ifOperStatus.3 = INTEGER: down(2)
IF-MIB::ifOperStatus.6 = INTEGER: down(2)
IF-MIB::ifOperStatus.7 = INTEGER: up(1)
IF-MIB::ifOperStatus.9 = INTEGER: down(2)
IF-MIB::ifOperStatus.10 = INTEGER: down(2)
IF-MIB::ifOperStatus.1210 = INTEGER: up(1)
A
匹配到的是ifIndex
为2的对象B
是匹配eno
开头的对象, 也就是ifIndex
为2 或者3A&&B
最终匹配的是eno1
这块网卡C
匹配的是所有UP的对象 ,对应的是ifIndex
为1、2、7、1210的对象A&&B || C
最终匹配的是lo
eno1
和tun0
tun1
这些网卡
注意: v0.3.7 和 v0.3.8 版本中用的是include_filter
这个配置,并且只支持 两段式的配置 ifIndex:2
这种,不支持正则表达式,而且默认是所有表达式做OR(||)运算。
v0.3.9 版本,使用filters
代替 include_filter
。虽然依然支持include_filter
并且兼容两段式配置,但是建议使用filters
+三段式配置,这样可以使用更丰富的逻辑运算。
批量设置label
[mappings]
"udp://192.168.11.102:161" = { name = "switch001.bj", region = "beijing", ip = "192.168.11.102"}
"udp://192.168.11.103:161" = { name = "switch002.bj", region = "shanghai", ip = "192.168.11.103"}
[[instances]]
agents = [
"udp://192.168.11.102:161",
...
]
[[instances]]
agents = [
"udp://192.168.11.103:161",
...
]
可以通过[mappings]
给每个agent设置label,采集的时候,就会自动带上这些label。注意格式,mappings是单个[]
, key 不带引号,value带引号。