Categraf SNMP 硬件与厂商私有 OID 监控:风扇、电源、温度、CPU 和内存

本文介绍如何用 Categraf SNMP 插件采集网络设备硬件和厂商私有 OID,覆盖 ENTITY-MIB、ENTITY-SENSOR-MIB、风扇、电源、温度、CPU、内存、snmpwalk 验证、convert_rule、状态枚举和告警语义。

作者 快猫星云

接口监控解决的是链路层问题:端口是否 up、流量是否高、错包丢包是否增长。但网络设备还有另一类风险:风扇停转、电源模块异常、温度过高、CPU 飙升、内存不足、光模块异常。这些问题不一定马上表现为端口 down,却可能是设备故障的前兆。

SNMP 硬件监控比接口监控更复杂,因为不同厂商、不同型号、不同系统版本暴露的 OID 差异很大。本文给出一套可落地的方法:先用通用 MIB 找设备实体和传感器,再针对厂商私有 OID 补齐风扇、电源、温度、CPU、内存等关键指标。

核心要点

  • 硬件监控没有绝对通用模板,应先用 snmpwalk 确认目标设备真实支持哪些 OID。
  • 通用入口优先看 ENTITY-MIB 和 ENTITY-SENSOR-MIB,它们能发现实体、模块、传感器和部分状态。
  • 厂商私有 OID 必须配合设备型号、系统版本和 MIB 文档验证,不要照搬其他设备的 OID。
  • 状态类指标要先搞清楚枚举值含义,例如 1 是否代表 normal,不同厂商可能不同。
  • 字符串状态、百分比、带单位数值可以用 conversionconvert_rule 转成可告警的数字。
  • 硬件指标采集频率通常不需要和接口流量一样高,60 秒到 300 秒更常见。
  • 告警要区分“硬件模块异常”和“设备不可达”,SNMP 不通时不要把所有硬件指标缺失都当成硬件故障。

1. 硬件监控应该覆盖什么

网络设备硬件监控通常关注这些对象:

对象 典型指标 告警含义
风扇 状态、转速 风扇停转、转速异常
电源 在位、状态、输入/输出功率 电源模块故障、单电源运行
温度 传感器温度、阈值 设备过热、机房散热异常
CPU 使用率、控制平面负载 路由震荡、控制面异常、SNMP 进程压力
内存 使用率、空闲内存 控制面内存压力、泄漏风险
板卡/模块 在位、运行状态 线卡异常、模块离线
光模块 收发光功率、温度、电压 光衰、模块故障、链路隐患

第一篇硬件监控不要试图覆盖所有对象。建议先从风扇、电源、温度、CPU、内存开始,光模块可以单独成篇,因为它涉及更多厂商差异和阈值语义。

2. 先用通用 MIB 做发现

很多网络设备支持 ENTITY-MIB。先验证实体表:

snmpwalk -v2c -c '<COMMUNITY>' 10.10.10.11 1.3.6.1.2.1.47.1.1.1.1.2
snmpwalk -v2c -c '<COMMUNITY>' 10.10.10.11 1.3.6.1.2.1.47.1.1.1.1.5
snmpwalk -v2c -c '<COMMUNITY>' 10.10.10.11 1.3.6.1.2.1.47.1.1.1.1.7

这三项分别是:

  • entPhysicalDescr:实体描述;
  • entPhysicalClass:实体类别;
  • entPhysicalName:实体名称。

常见 ENTITY-MIB OID:

字段 OID 说明
entPhysicalDescr 1.3.6.1.2.1.47.1.1.1.1.2 实体描述
entPhysicalContainedIn 1.3.6.1.2.1.47.1.1.1.1.4 父实体索引
entPhysicalClass 1.3.6.1.2.1.47.1.1.1.1.5 实体类别
entPhysicalName 1.3.6.1.2.1.47.1.1.1.1.7 实体名称
entPhysicalSerialNum 1.3.6.1.2.1.47.1.1.1.1.11 序列号
entPhysicalMfgName 1.3.6.1.2.1.47.1.1.1.1.12 厂商
entPhysicalModelName 1.3.6.1.2.1.47.1.1.1.1.13 型号
entPhysicalIsFRU 1.3.6.1.2.1.47.1.1.1.1.16 是否现场可替换单元

这些指标更适合做资产和标签,不一定直接告警。

3. 传感器优先看 ENTITY-SENSOR-MIB

如果设备支持 ENTITY-SENSOR-MIB,可以继续验证:

snmpwalk -v2c -c '<COMMUNITY>' 10.10.10.11 1.3.6.1.2.1.99.1.1.1

常见字段:

字段 OID 说明
entPhySensorType 1.3.6.1.2.1.99.1.1.1.1 传感器类型
entPhySensorScale 1.3.6.1.2.1.99.1.1.1.2 数值缩放
entPhySensorPrecision 1.3.6.1.2.1.99.1.1.1.3 精度
entPhySensorValue 1.3.6.1.2.1.99.1.1.1.4 传感器值
entPhySensorOperStatus 1.3.6.1.2.1.99.1.1.1.5 传感器运行状态
entPhySensorUnitsDisplay 1.3.6.1.2.1.99.1.1.1.6 单位显示

这张表能覆盖一部分温度、电压、电流、功率、风扇转速等指标。但不同设备支持程度差异很大,必须以实际 walk 结果为准。

4. ENTITY-MIB 配置示例

下面是一份实体表配置,主要用于识别硬件模块:

[[instances.table]]
name = "entity"
index_as_tag = true
error_policy = "partial"
filters = [
  "A:entPhysicalClass:^(3|5|6|7|8|9|10)$"
]
filters_expression = "A"
filters_mode = "strict"

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.2" # entPhysicalDescr
name = "entPhysicalDescr"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.5" # entPhysicalClass
name = "entPhysicalClass"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.7" # entPhysicalName
name = "entPhysicalName"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.11" # entPhysicalSerialNum
name = "entPhysicalSerialNum"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.13" # entPhysicalModelName
name = "entPhysicalModelName"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.47.1.1.1.1.16" # entPhysicalIsFRU
name = "entPhysicalIsFRU"

这里的 entPhysicalClass 是实体类别。不同值代表 chassis、backplane、container、powerSupply、fan、sensor、module、port、stack 等类型。具体枚举以设备 MIB 为准。

这张表本身不一定需要频繁采集,更多是为了给硬件告警提供上下文。

5. ENTITY-SENSOR-MIB 配置示例

传感器表配置:

[[instances.table]]
name = "sensor"
index_as_tag = true
error_policy = "partial"
filters = [
  "A:entPhySensorOperStatus:^1$"
]
filters_expression = "A"
filters_mode = "strict"

[[instances.table.field]]
oid = "1.3.6.1.2.1.99.1.1.1.1" # entPhySensorType
name = "entPhySensorType"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.99.1.1.1.2" # entPhySensorScale
name = "entPhySensorScale"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.99.1.1.1.3" # entPhySensorPrecision
name = "entPhySensorPrecision"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.2.1.99.1.1.1.4" # entPhySensorValue
name = "entPhySensorValue"

[[instances.table.field]]
oid = "1.3.6.1.2.1.99.1.1.1.5" # entPhySensorOperStatus
name = "entPhySensorOperStatus"

这里有一个重点:entPhySensorValue 的真实单位和缩放要结合 entPhySensorTypeentPhySensorScaleentPhySensorPrecision 判断。不要看到值是 45 就直接认为是 45 摄氏度。设备、MIB 和传感器类型不同,解释方式可能不同。

如果目标只是温度告警,很多厂商会提供更直接的私有温度 OID,反而比通用传感器表更容易落地。

6. 厂商私有 OID 怎么找

厂商私有 OID 的路径通常在:

1.3.6.1.4.1.<enterprise>

查找方法有三种。

第一,看厂商 MIB 文档。设备厂商通常会提供 MIB 文件或网管手册,里面有风扇、电源、温度、CPU、内存、光模块等 OID。

第二,用 snmpwalk 从私有企业号下探索:

snmpwalk -v2c -c '<COMMUNITY>' 10.10.10.11 1.3.6.1.4.1

这条命令可能很大,不建议在生产核心设备上随意执行全量 walk。更稳妥的做法是结合厂商 enterprise OID 或文档缩小范围。

第三,从已有监控系统迁移。例如 Zabbix 模板、老的 SNMP exporter 配置、厂商 NMS 系统,都可以作为 OID 来源。但迁移时必须逐条验证,不能直接搬。

每个 OID 至少要确认:

  • 它在目标设备上存在;
  • 返回值类型是什么;
  • 单位是什么;
  • 枚举值含义是什么;
  • 是否每个型号都支持;
  • 是否会带来高基数标签。

7. 风扇监控示例

假设某厂商风扇表有三个字段:

fanName
fanStatus
fanSpeed

配置可以这样写:

[[instances.table]]
name = "fan"
index_as_tag = true
error_policy = "partial"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.1.1.1.1" # fanName
name = "fanName"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.1.1.1.2" # fanStatus
name = "fanStatus"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.1.1.1.3" # fanSpeed
name = "fanSpeed"
conversion = "float"

[[instances.table.field.convert_rule]]
match = "offline"
value = -1

告警前要先确认 fanStatus 枚举。例如有些设备 1 是 normal,有些设备可能 1 是 unknown。不要凭经验写:

snmp_fan_fanStatus != 1

应该先用 snmpwalk 和设备页面对照状态,再确定阈值。

风扇转速告警也不能只看绝对值。有些设备支持自动调速,低负载低温时转速低是正常的。更常见的规则是“状态异常”优先于“转速低”。

8. 电源监控示例

电源监控至少关注两个问题:

  • 电源模块是否在位;
  • 在位电源是否正常。

示例配置:

[[instances.table]]
name = "power"
index_as_tag = true
error_policy = "partial"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.2.1.1.1" # powerName
name = "powerName"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.2.1.1.2" # powerPresent
name = "powerPresent"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.2.1.1.3" # powerStatus
name = "powerStatus"

如果设备双电源设计,告警语义要区分:

  • 单个电源模块不在位;
  • 单个电源模块故障;
  • 两个电源都异常;
  • 设备只配置单电源,但模板按双电源告警。

不要在不了解硬件设计的情况下,对所有 powerPresent != 1 直接告警。很多接入交换机本来就只有单电源或空电源槽。

9. 温度监控示例

温度指标可以来自通用传感器表,也可以来自厂商私有 OID。

私有 OID 示例:

[[instances.table]]
name = "temperature"
index_as_tag = true
error_policy = "partial"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.3.1.1.1" # temperatureName
name = "temperatureName"
is_tag = true

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.3.1.1.2" # temperatureValue
name = "temperatureValue"
conversion = "float"

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.3.1.1.3" # temperatureStatus
name = "temperatureStatus"

基础 PromQL:

snmp_temperature_temperatureValue

告警可以按设备类型分层:

snmp_temperature_temperatureValue > 70

但固定阈值要谨慎。不同设备、不同传感器位置、不同厂商阈值不同。更稳妥的做法是:

  • 优先使用设备返回的温度状态;
  • 状态不可用时再使用温度绝对值;
  • 核心设备阈值更保守;
  • 结合机房温湿度和风扇状态判断。

10. CPU 和内存监控

网络设备的 CPU 和内存通常是厂商私有 OID。即使都是“CPU 使用率”,也可能存在不同语义:

  • 1 分钟、5 分钟、5 秒平均值;
  • 控制平面 CPU;
  • 每个板卡 CPU;
  • 每个核心 CPU;
  • 主控板 CPU。

示例:

[[instances.field]]
oid = "1.3.6.1.4.1.XXX.4.1.0" # cpuUsage
name = "cpu_usage"
conversion = "float"

[[instances.field]]
oid = "1.3.6.1.4.1.XXX.4.2.0" # memoryUsage
name = "memory_usage"
conversion = "float"

输出指标:

snmp_cpu_usage
snmp_memory_usage

告警建议:

snmp_cpu_usage > 80
snmp_memory_usage > 85

但不要只看 CPU 高就判断设备故障。网络设备 CPU 高可能来自:

  • 路由震荡;
  • ARP 或广播风暴;
  • SNMP walk 太重;
  • 控制平面被攻击;
  • 管理登录或配置变更;
  • 设备本身 bug。

排障时应结合接口流量、错误包、日志、路由协议状态和设备告警一起看。

11. convert_rule 处理异常字符串

厂商私有 OID 经常返回字符串。比如正常返回:

45 C

异常返回:

unavailable

可以用规则提取:

[[instances.table.field]]
oid = "1.3.6.1.4.1.XXX.3.1.1.2"
name = "temperatureValue"
conversion = "float"

[[instances.table.field.convert_rule]]
match = "unavailable"
value = -1

[[instances.table.field.convert_rule]]
regex = "^([0-9.]+) C$"
extract = "$1"
conversion = "float"

这样:

  • unavailable 转成 -1
  • 45 C 提取为 45
  • 其他值回退到默认 conversion = "float"

状态类字符串也可以转换:

[[instances.table.field.convert_rule]]
match = "normal"
value = 1

[[instances.table.field.convert_rule]]
match = "warning"
value = 2

[[instances.table.field.convert_rule]]
match = "critical"
value = 3

转换后的数字更适合 PromQL 告警。

12. 采集频率和性能

硬件指标变化通常比接口流量慢。建议:

指标类型 建议采集间隔
设备可用性 30s - 60s
接口流量 15s - 60s
风扇、电源、温度 60s - 300s
CPU、内存 30s - 120s
资产信息 300s 或更低频

如果把 ENTITY-MIB、ENTITY-SENSOR-MIB、接口表、光模块表和多个厂商私有表都放在 15 秒采集周期里,老设备很容易压力过大。

更好的做法是拆分实例:

[[instances]]
# 高频接口监控
# interval_times = 1

[[instances]]
# 低频硬件监控
# interval_times = 4

具体能否用实例级采集周期,要结合全局 interval 和当前部署配置。核心原则是:硬件类指标不必跟接口流量同频。

13. 告警建议

风扇状态异常

snmp_fan_fanStatus != 1

前提是已经确认该设备 1 表示正常。

电源状态异常

snmp_power_powerStatus != 1

建议结合 powerPresent,避免空槽误报。

温度过高

snmp_temperature_temperatureValue > 70

阈值要按设备和传感器位置调整。

CPU 持续高

snmp_cpu_usage > 80

建议持续 5 到 10 分钟再告警,避免短时管理操作造成噪音。

内存使用率高

snmp_memory_usage > 85

如果设备内存长期高但稳定,需要结合厂商建议阈值,不要机械套用服务器经验。

14. 常见问题

为什么同一个 OID 在不同型号上没有值?

厂商私有 OID 常常和型号、系统版本、板卡类型有关。必须按型号验证,不能认为同厂商所有设备都支持。

ENTITY-MIB 能替代厂商私有 OID 吗?

不能完全替代。ENTITY-MIB 适合发现实体和部分传感器,但很多 CPU、内存、风扇、电源细节仍然需要厂商私有 MIB。

状态值怎么确认?

snmpwalk 输出、厂商 MIB 文档和设备管理页面三者对照。不要凭别人的模板猜枚举。

字符串能不能直接作为指标值?

Prometheus 风格时序需要数值。字符串更适合作为标签;如果字符串代表状态,应通过 convert_rule 转成数字。

硬件表要不要加 partial?

建议加。硬件私有 OID 更容易出现部分字段不支持或偶发失败。partial 可以避免一个低优先级字段拖垮整张表,但标签和过滤依赖仍然会保守处理。

15. 生产建议

硬件监控要按“通用发现 + 厂商模板”建设。

第一步,用 ENTITY-MIB 和 ENTITY-SENSOR-MIB 了解设备能暴露哪些实体和传感器。

第二步,按厂商和型号整理私有 OID,不同型号不要强行共用一份模板。

第三步,把状态类指标转换成清晰数字,并在文章、配置注释或内部文档里写明枚举含义。

第四步,给硬件指标单独设置采集频率,不要和接口流量同频。

第五步,把硬件告警和设备角色结合起来。核心设备风扇、电源、温度异常应高优先级;普通接入设备可以按持续时间和影响面降噪。

SNMP 硬件监控的价值不是“采到很多厂商 OID”,而是能在设备真正出故障前,把风扇、电源、温度和控制面压力这些早期信号暴露出来。

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云