夜莺-Nightingale
夜莺V6
项目介绍 架构介绍
快速开始
黄埔营
安装部署
升级
采集器
使用手册
API
数据库表结构
FAQ
开源生态
Prometheus
版权声明
第1章:天降奇兵
第2章:探索PromQL
第3章:Prometheus告警处理
第4章:Exporter详解
第5章:数据与可视化
第6章:集群与高可用
第7章:Prometheus服务发现
第8章:监控Kubernetes
第9章:Prometheus Operator
参考资料

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" # 不调用translator
  • oid="IF-MIB::ifInOctets" # 调用translator

使用gosmi时要注意,path中一定要包含所有依赖的mib文件,不是只放你的私有mib路径就可以了。

translator="gosmi"
path = ["/usr/share/snmp/mibs", "/path/to/your/other/mibs"]

不同的field

配置中支持两种field

  • instances.field
  • instances.table.fields

使用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.5index就是.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=“hextoint:X:Y” # 将hex值转为int.
    • hextoint:LittleEndian:uint64 将hex值按照小端序转为无符号64位int
    • hextoint: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_tablesecondary_index_usesecondary_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_joinsecondary_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是匹配ifDescreno开头的对象,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 或者3
  • A&&B 最终匹配的是 eno1 这块网卡
  • C 匹配的是所有UP的对象 ,对应的是ifIndex 为1、2、7、1210的对象
  • A&&B || C 最终匹配的是 lo eno1tun0 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带引号。

开源版
Flashcat
Flashduty