前两篇文章分别讲了交换机接口监控和 SNMP 表格采集。这篇文章解决另一个生产问题:当设备不止一两台,而是几十、几百甚至更多时,SNMP 配置应该怎么组织?什么时候继续用 SNMPv2c,什么时候切到 SNMPv3?不同机房、不同厂商、不同凭据的设备能不能放到同一个 [[instances]]?超时、重试、GETBULK、健康检查又该怎么设置?
SNMP 单设备跑通不难,难的是批量接入后还能稳定、可维护、可排障。
核心要点
- SNMPv2c 配置简单,但 community 明文传输;安全要求较高的生产网络应优先使用 SNMPv3。
- 同一个
[[instances]]适合放协议、凭据、超时、采集字段一致的一组设备;凭据或采集模板不同,应拆成多个[[instances]]。 agents可以配置多台设备,Categraf 会按 agent 维度输出ident或agent_host标签。mappings适合给单台设备补充稳定标签,例如机房、厂商、设备角色、业务域。- 大规模采集时不要只调大重试;更重要的是拆分采集模板、控制字段数量、过滤表格行、合理设置采集间隔。
health_check_interval、max_fail_count和recovery_interval可以减少异常设备长期拖慢采集。- SNMPv3 参数要先用
snmpwalk验证,再放入 Categraf,避免在监控配置里盲调。
1. SNMPv2c 和 SNMPv3 怎么选
SNMPv2c 的优点是简单:
version = 2
community = "<COMMUNITY>"
只要设备开启 SNMP、ACL 放通、community 正确,就能采集。很多内网交换机、测试环境、隔离管理网仍然大量使用 SNMPv2c。
SNMPv2c 的问题也很明确:
- community 类似共享密码;
- 默认没有认证加密;
- 抓包能看到 community;
- 不适合跨不可信网络。
SNMPv3 可以提供认证和加密,常见安全级别包括:
sec_level |
含义 | 适用场景 |
|---|---|---|
noAuthNoPriv |
不认证、不加密 | 很少用于生产 |
authNoPriv |
认证、不加密 | 内网可信但要求身份认证 |
authPriv |
认证并加密 | 安全要求较高的生产网络 |
如果设备和组织安全策略允许,生产建议优先使用 authPriv。如果管理网络隔离充分、设备型号较旧或 SNMPv3 支持不稳定,可以先使用 SNMPv2c,但要通过 ACL 限制采集源。
2. 先用 snmpwalk 验证 SNMPv3
不要直接在 Categraf 里试错 SNMPv3。先用命令验证。
authPriv 示例:
snmpwalk -v3 \
-l authPriv \
-u '<USER>' \
-a SHA \
-A '<AUTH_PASSWORD>' \
-x AES \
-X '<PRIV_PASSWORD>' \
10.10.10.11 \
1.3.6.1.2.1.1.5.0
如果成功,再验证接口表:
snmpwalk -v3 \
-l authPriv \
-u '<USER>' \
-a SHA \
-A '<AUTH_PASSWORD>' \
-x AES \
-X '<PRIV_PASSWORD>' \
10.10.10.11 \
1.3.6.1.2.1.31.1.1.1.1
常见失败原因:
- 用户名不对;
sec_level与设备侧配置不一致;- auth 协议不一致,例如设备是 SHA,命令写了 MD5;
- priv 协议不一致,例如设备是 AES,命令写了 DES;
- 密码长度或字符集不符合设备要求;
- 设备侧 ACL 没放通 Categraf 所在机器;
- 设备使用了 SNMPv3 context,但命令没有指定。
只有命令行验证通过后,才把参数迁移到 Categraf。
3. Categraf SNMPv3 最小配置
SNMPv3 配置示例:
[[instances]]
agents = [
"udp://10.10.10.11:161",
"udp://10.10.10.12:161"
]
version = 3
agent_host_tag = "ident"
labels = { region = "cn-east", device_role = "switch" }
sec_name = "<USER>"
sec_level = "authPriv"
auth_protocol = "SHA"
auth_password = "<AUTH_PASSWORD>"
priv_protocol = "AES"
priv_password = "<PRIV_PASSWORD>"
context_name = ""
timeout = "5s"
retries = 2
max_repetitions = 10
这些字段对应关系如下:
| Categraf 配置 | snmpwalk 参数 | 含义 |
|---|---|---|
version = 3 |
-v3 |
SNMPv3 |
sec_name |
-u |
安全用户名 |
sec_level |
-l |
安全级别 |
auth_protocol |
-a |
认证算法 |
auth_password |
-A |
认证密码 |
priv_protocol |
-x |
加密算法 |
priv_password |
-X |
加密密码 |
context_name |
-n |
context 名称 |
Categraf 支持的认证协议包括 MD5、SHA、SHA224、SHA256、SHA384、SHA512 和空值。隐私协议包括 DES、AES、AES192、AES192C、AES256、AES256C 和空值。部分 AES 变体依赖底层 net-snmp 或设备支持,生产使用前必须验证。
4. 多设备应该怎么分组
一个常见误区是把所有设备都塞进一个 [[instances]]:
[[instances]]
agents = [
"udp://10.10.10.11:161",
"udp://10.20.10.11:161",
"udp://10.30.10.11:161"
]
这只适合设备协议、凭据、采集字段、超时策略都一致的场景。
建议按下面维度拆分:
- SNMP 版本不同:v2c 和 v3 分开;
- 凭据不同:不同 community 或 SNMPv3 用户分开;
- 设备类型不同:交换机、防火墙、负载均衡、无线控制器分开;
- 厂商不同:通用 IF-MIB 可以共用,私有 OID 应拆分;
- 采集频率不同:核心设备和低优先级设备分开;
- 网络质量不同:跨地域、跨专线、低质量链路分开。
示例:
[[instances]]
agents = [
"udp://10.10.10.11:161",
"udp://10.10.10.12:161"
]
version = 3
sec_name = "<CORE_USER>"
sec_level = "authPriv"
auth_protocol = "SHA"
auth_password = "<AUTH_PASSWORD>"
priv_protocol = "AES"
priv_password = "<PRIV_PASSWORD>"
agent_host_tag = "ident"
labels = { region = "cn-east", device_role = "core-switch", vendor = "h3c" }
[[instances]]
agents = [
"udp://10.20.10.11:161",
"udp://10.20.10.12:161"
]
version = 2
community = "<COMMUNITY>"
agent_host_tag = "ident"
labels = { region = "cn-north", device_role = "access-switch", vendor = "huawei" }
不要为了配置短,把不同凭据和不同设备类型混在一起。短配置不一定可维护。
5. 用 mappings 补充单设备标签
实例级 labels 适合一组设备共享的标签。如果同一组设备里每台设备还需要单独标签,可以使用 mappings。
示例:
[[instances]]
agents = [
"udp://10.10.10.11:161",
"udp://10.10.10.12:161"
]
labels = { region = "cn-east", device_role = "core-switch" }
[instances.mappings]
"udp://10.10.10.11:161" = { device_name = "sw-core-01", room = "room-a", rack = "rack-01" }
"udp://10.10.10.12:161" = { device_name = "sw-core-02", room = "room-a", rack = "rack-02" }
注意映射 key 要和 agents 中的字符串一致。你写的是 udp://10.10.10.11:161,mapping 里也要用这个完整形式,不要只写 10.10.10.11。
适合放在 mappings 的标签:
device_name;vendor;model;room;rack;network_zone;owner_team。
不建议放:
- 经常变化的端口备注;
- 工单号;
- 临时维护人员;
- 高基数业务对象。
6. 超时和重试怎么设置
SNMP 使用 UDP 时,超时和重试很关键。默认值不一定适合所有网络。
常用配置:
timeout = "5s"
retries = 2
经验建议:
- 同机房设备:
timeout = "2s"到"5s"; - 跨机房设备:
timeout = "5s"到"10s"; - 质量较差链路:先排网络,不要只靠调大 timeout;
retries一般 1 到 3 次,过高会拖慢整个采集周期。
重试不是越多越好。假设一台设备超时 5 秒、重试 3 次、还采了多张表,那么异常设备会显著拖慢采集。更好的做法是配合健康检查,让异常设备进入恢复探测,而不是每次完整采集都等到超时。
7. max_repetitions 怎么理解
SNMPv2c 和 SNMPv3 使用 GETBULK 时,max_repetitions 会影响单次请求返回多少行。
max_repetitions = 10
值太小,请求次数多,采集慢;值太大,设备负载、响应包大小和丢包风险可能增加。
建议:
- 普通交换机接口表从 10 或 20 开始;
- 大表、慢设备、跨地域链路适当降低;
- 稳定高速管理网可以适当提高;
- 任何调整都要看
snmp_gather_duration_seconds和设备 CPU。
如果设备经常出现 walk 超时,不要只调大 max_repetitions。先确认是网络丢包、设备慢、表太大,还是某个 OID 不稳定。
8. 健康检查和恢复探测
新版 SNMP 插件提供健康检查相关配置:
health_check_interval = "60s"
health_check_timeout = "5s"
max_fail_count = 3
recovery_interval = "5m"
含义是:
- 每隔
health_check_interval做健康检查; - 健康检查超时时间为
health_check_timeout; - 连续失败达到
max_fail_count后认为设备异常; - 异常后按
recovery_interval做恢复探测。
这对批量设备很重要。一个长期不可达的设备不应该每个采集周期都拖慢完整采集。健康状态相关指标可以看:
snmp_health_state
snmp_recovery_probe_total
snmp_transport_failure_total
如果某台设备频繁在 healthy/unhealthy 之间切换,通常说明网络质量、ACL、设备 SNMP 进程或超时配置有问题。
9. 采集规模怎么控制
批量 SNMP 采集的压力来自三个维度:
设备数量 x 表格行数 x 字段数量
例如:
- 200 台交换机;
- 每台 200 个接口行;
- 每行 12 个字段;
- 15 秒采集一次。
这会产生大量 SNMP walk 请求和时序数据。此时优化方向不是“机器加大一点”这么简单,而是要从采集策略上控制。
建议:
- 不要采所有端口,优先过滤核心端口、上联端口和有别名端口;
- 不要采所有字段,只采 Dashboard 和告警真正需要的字段;
- 接口流量可以 15 到 60 秒采集,硬件温度和电源状态可以更低频;
- 不同区域或设备类型拆分到不同 Categraf 实例;
- 对跨地域设备使用就近采集点;
- 对老旧设备降低采集频率和 GETBULK 压力。
10. 采集间隔怎么分层
SNMP 配置可以通过 interval 或实例采集周期控制频率。实际策略建议分层:
| 类型 | 建议间隔 | 说明 |
|---|---|---|
| 核心链路接口流量 | 15s - 30s | 需要较快发现拥塞 |
| 普通接入口 | 60s | 足够看趋势 |
| 设备可用性 | 30s - 60s | 配合持续时间告警 |
| 风扇、电源、温度 | 60s - 300s | 变化慢,不必高频 |
| 资产类标签 | 300s 或更低频 | 不适合频繁采 |
不要为了统一而所有 OID 都 15 秒采一次。SNMP 设备本身处理能力有限,尤其是老型号交换机和跨网络采集。
11. 批量配置模板示例
下面是一个把核心交换机和接入交换机分开的示例。
核心交换机使用 SNMPv3:
[[instances]]
agents = [
"udp://10.10.10.11:161",
"udp://10.10.10.12:161"
]
version = 3
agent_host_tag = "ident"
labels = { region = "cn-east", role = "core-switch", env = "prod" }
sec_name = "<USER>"
sec_level = "authPriv"
auth_protocol = "SHA"
auth_password = "<AUTH_PASSWORD>"
priv_protocol = "AES"
priv_password = "<PRIV_PASSWORD>"
timeout = "5s"
retries = 2
max_repetitions = 20
default_table_error_policy = "partial"
dependency_cache_ttl = "10m"
接入交换机暂时使用 SNMPv2c:
[[instances]]
agents = [
"udp://10.20.10.11:161",
"udp://10.20.10.12:161",
"udp://10.20.10.13:161"
]
version = 2
community = "<COMMUNITY>"
agent_host_tag = "ident"
labels = { region = "cn-east", role = "access-switch", env = "prod" }
timeout = "5s"
retries = 1
max_repetitions = 10
default_table_error_policy = "partial"
dependency_cache_ttl = "5m"
两组后面可以复用同一套接口表字段,也可以按设备能力拆分字段。
12. 密码和配置管理
SNMPv3 的 auth_password 和 priv_password 不应出现在公开文档、截图、工单或 Git 仓库里。生产环境建议:
- 由配置管理系统渲染 Categraf 配置;
- 限制配置文件权限,只允许运行用户读取;
- 按设备组分配最小权限 SNMP 用户;
- 定期轮换凭据;
- 变更前先用测试节点验证;
- 不同环境使用不同凭据。
示例里使用 <AUTH_PASSWORD> 和 <PRIV_PASSWORD> 占位,实际部署时不要照抄真实值进文章或代码仓库。
13. Dashboard 和告警标签设计
批量设备监控最怕告警只有 IP。建议至少保证以下标签:
ident
source
region
role
vendor
ifName
ifAlias
其中:
ident:Categraf 采集目标地址;source:设备自身名称,通常来自sysName.0;region:区域或机房;role:核心、汇聚、接入、防火墙等角色;vendor:厂商;ifName:接口名称;ifAlias:业务描述。
告警标题建议包含设备名和接口名:
SNMP 端口 down: {{ $labels.source }} {{ $labels.ifName }} {{ $labels.ifAlias }}
通知路由可以按 region、role、owner_team 分流,不要靠人工看到 IP 后再查 CMDB。
14. 常见问题
一个 instances 可以混用多个 SNMPv3 用户吗?
不建议,也通常做不到。一个 [[instances]] 里的 SNMP 认证参数是共享的。不同用户、不同认证协议、不同密码应拆成多个 [[instances]]。
SNMPv3 一直报认证失败怎么办?
先用 snmpwalk 验证,确认 sec_level、用户名、认证协议、认证密码、加密协议、加密密码和 context 都一致。不要在 Categraf 里盲调。
批量设备采集慢,是不是把 timeout 调大就行?
不是。timeout 变大会让失败设备拖更久。应该先看哪些设备慢、哪张表慢、是否字段过多、是否跨网络采集,再考虑拆实例、过滤端口、降低频率。
mappings 没生效怎么办?
检查 key 是否和 agents 里的字符串完全一致。udp://10.10.10.11:161 和 10.10.10.11 不是同一个 key。
是否应该给每台设备一个 [[instances]]?
少量关键设备可以这样做,便于单独标签和策略。大量同类设备不建议每台一个实例,配置会难维护。更常见的是按凭据、区域、角色、厂商分组。
15. 生产建议
批量 SNMP 采集的核心不是“把设备都写进 agents”,而是建立一套分组规则。
推荐分组顺序:
- 先按 SNMP 版本和凭据分组;
- 再按区域和网络距离分组;
- 再按设备角色和厂商分组;
- 最后按采集频率和字段模板分组。
上线前先选 3 到 5 台代表性设备灰度验证,覆盖核心交换机、接入交换机、老型号设备、跨网络设备。确认 snmp_up、接口表、Dashboard 变量、告警标签都正常后,再批量扩展。
SNMP 的规模化稳定性,更多来自配置治理和采集边界控制,而不是把所有参数都调大。