基于Prometheus与snmp_exporter的网络设备统一监控方案详解

发布时间:2026/10/15 4:20:18
基于Prometheus与snmp_exporter的网络设备统一监控方案详解
前阵子帮朋友公司调机房一大摞交换机、防火墙、路由器加起来四十多台设备品牌还混着来原有的监控系统早就停更了新设备根本加不进去平时全靠运维同事一台台登录设备后台看状态出了问题才发现已经晚了。我最后直接用Prometheus这套组合方案重新搭了一套网络设备监控从安装部署到第一张图表跑出来前后大概半天时间。这篇博文就把整个过程完全复盘一下覆盖交换机、防火墙、路由器这些主流网络设备的统一接入核心目标是让零基础的小白照着操作也能把整套体系跑起来真正做到开箱即用。这套方案要解决的问题很明确不同品牌、不同类型的网络设备通过一套监控平台统一采集、统一出图、统一告警。不再需要为每台设备单独登录Web管理界面也不需要给网络设备安装额外的Agent程序——网络设备大多只支持被动的管理协议我们直接利用设备原生能力做数据采集。适合谁用管理几台到几十台设备的运维新手、一个人兼任网管和服务器运维的小团队以及不想被商业网管软件授权费用和部署复杂度锁死的同学这篇文章都能帮你少走不少弯路。1. 为什么我会用Prometheus来统一监控网络设备1.1 传统网络设备监控的痛点先说说我为什么没有沿用更传统的思路。很多团队管网络设备无非几种路子买商业网管软件、用Zabbix、或者干脆手工管理。商业网管软件功能确实全但部署起来往往要先搭一个独立的采集服务器还要装数据库、配拓扑扫描、买授权大厂的价格对小团队来说不便宜而且后续升级也麻烦。Zabbix能做网络设备监控模板生态也不错但说实话一个小白从零开始配起Zabbix的模板、主机、宏、触发器光理解那套概念就需要不少时间模板里很多默认项在真实设备上根本采集不到还要自己去调。手工管理就更不用说了设备一多Excel表格根本跟不上。某台设备的接口流量从正常突然掉到0这种隐患很难靠肉眼及时看到。我曾经见过一个机房的出口链路半夜被打满第二天早上业务方投诉才发现后来一问链路监控一直没做连阈值告警都没有。我并不是说上面这些方案不行而是在“快速落地、开箱即用、资源占用可控”这三个维度上Prometheus这套组合确实更符合中小团队的实际需求。1.2 Prometheus方案的核心优势Prometheus本身最早是面向云原生监控设计的但它对网络设备监控的支持其实相当成熟核心组件就是snmp_exporter。这个组合方案的优势我总结为以下几点。第一部署成本极低。Prometheus、snmp_exporter、Grafana三个组件加起来用Docker Compose编排一个配置文件就能全部启动不需要独立数据库不需要额外中间件一台2核4G的Linux服务器就能带起几十台设备的监控任务。第二设备接入不需要装Agent。只要网络设备开启了SNMP协议就能被snmp_exporter采集这对交换机、防火墙、路由器这类不能随便装东西的网络设备来说是唯一的可行路径。第三数据模型统一。所有设备采集上来的数据在Prometheus里都是带标签的时间序列用同一条查询语法就能看懂所有设备的状态。比如想看所有设备里某个接口的流量一条PromQL就能算出来这种灵活度在传统网管软件里往往需要绕很多步骤才能实现。第四告警和可视化是天然闭环。Prometheus负责告警规则评估Alertmanager负责把告警发到邮件、WebhookGrafana负责出图整个链路都是围绕Prometheus的数据格式设计的不用做数据二次转换。1.3 与商业网管、Zabbix的横向对比为了让大家更直观理解选型逻辑我把这几种方案放在一起做了个对比。维度商业网管软件ZabbixPrometheus snmp_exporter部署难度复杂需独立数据库与采集架构中等需安装服务端与模板配置低Docker Compose一键启动许可证成本高开源免费开源免费设备接入方式SNMP/Agent混合SNMP/Agent混合SNMP为主天然适配网络设备模板维护成本厂家支持但定制贵模板多但需手工调默认snmp.yml覆盖主流MIB开箱即用告警扩展受产品限制灵活但学习成本高PromQLAlertmanager灵活度高与云原生监控整合困难一般天然融合从我实际使用的体验来看如果网络设备数量不大、团队没有专职监控开发人员Prometheus这套组合是性价比和上手速度最均衡的选择。而且后续你想把服务器、数据库、容器这些也纳入监控直接复用同一套Prometheus即可不用再单独铺一套新平台。2. 这套方案的核心原理SNMP到底是怎么工作的2.1 SNMP协议的基本认知很多刚开始接触网络设备监控的同学第一次看到SNMP三个字母容易懵其实它的原理可以拿一个生活里的场景来类比。SNMP就像是网络设备对外提供的一本标准电话黄页每个监控项都有一个唯一的电话号码也就是OID。监控系统拨打电话也就是发起一个SNMP GET请求设备就会把自己对应的状态告诉你。SNMP协议监听在UDP 161端口主流设备都默认支持。版本上常见的是v1、v2c和v3。v2c的认证方式比较原始靠一个community团体名来区分相当于黄页的暗号设备上配置了什么团体名监控端就得填一样的默认的团体名往往是public或private。v3则支持用户名和密码认证还能加密传输安全性更好但配置起来相对复杂。对于网络设备监控来说需要重点理解两个概念计数器Counter和计量器Gauge。计数器是只增不减的累计数值比如接口收到的总字节数计量器是当前状态的瞬时值比如CPU使用率、接口当前速率。Prometheus在计算接口速率的时候就是用计数器在两个时间点的差值除以间隔时间这就是rate()函数在做的事情。2.2 snmp_exporter那个连接Prometheus和设备的“翻译官”Prometheus本身并不懂SNMP协议它只会发HTTP请求然后解析返回的文本指标。所以中间需要一个翻译官就是snmp_exporter。snmp_exporter运行起来后会暴露一个HTTP接口路径通常为/snmp。Prometheus在配置里指定要采集的目标设备IP和要使用的模块名snmp_exporter收到HTTP请求后再去目标设备上通过UDP执行真正的SNMP采集然后把采集到的OID数值转换成一堆Prometheus格式的指标返回给Prometheus。为什么要有这层转换因为SNMP返回的数据是很原始的OID键值对比如1.3.6.1.2.1.2.2.1.10这个OID它只代表“接口收到的累计字节数”但不带任何业务语义。snmp_exporter会根据预置的snmp.yml配置文件把这个OID映射成类似ifHCInOctets{instance192.168.10.1,ifNameGigabitEthernet0/1}这种带标签的指标名。标签里包含了设备IP、接口名、索引等关键信息这样Prometheus才能对这些数据进行灵活的聚合和过滤。这套转换逻辑都定义在snmp_exporter的snmp.yml里官方发布的默认配置已经涵盖了绝大部分主流MIB库绝大多数标准设备装上就能直接用。2.3 一次完整的数据流从OID到监控面板我把一次完整的数据采集过程串起来大家就能对整个链路有清晰的认知。第一步Prometheus按照配置的采集周期向snmp_exporter发起HTTP请求URL里的参数会带上目标设备IP和模块名。第二步snmp_exporter根据这个请求去目标设备上执行实际的SNMP GET或者GETNEXT操作获取多个OID对应的原始数值。第三步snmp_exporter解析返回结果根据snmp.yml里的定义把OID转换成扁平化的Prometheus指标。第四步Prometheus等待snmp_exporter返回HTTP响应把指标解析出来后写入内嵌的时序数据库TSDB。第五步Grafana通过PromQL查询这些指标把流量、CPU、接口状态渲染成图表。告警链路也在这个基础上并行工作。Prometheus会定时评估我们写在告警规则文件里的表达式如果某个条件触发就推送给Alertmanager由它负责把告警消息发到目标渠道。这个整体架构听起来环节很多但每个组件都只负责一件事链路清晰排错时也容易定位问题到底出在哪一段。3. 从安装到出数据Docker Compose一键搭建全流程3.1 环境准备与端口规划这套方案的硬件要求很低我实际测试下来一台2核4G内存的Linux机器跑三四十台设备的SNMP采集完全没问题。如果设备数量更少比如就几台1核2G的轻量主机也够用。操作系统建议用Debian或Ubuntu系的Linux当然CentOS系也可以不影响Docker的正常使用。服务器准备好之后需要提前规划好端口。Prometheus Web界面9090端口snmp_exporter HTTP接口9116端口Grafana Web界面3000端口Alertmanager Web界面9093端口这里有个建议为了安全以上这些端口不要直接暴露到公网尤其是Prometheus的9090端口和Grafana的3000端口尽量只允许内网访问或者用反代加认证后再开放访问。网络设备那边需要做的准备启用SNMP协议。以最常见的交换机为例需要配置SNMP的读写团体名或v3用户并确认设备管理地址与监控服务器之间UDP 161端口能够互通。3.2 编辑Compose编排文件和挂载配置我习惯用Docker Compose把整个环境串起来这样一条命令就能拉起所有组件也方便以后规模变大时迁移到别的机器。先创建一个工作目录比如就叫network-monitor进入目录后新建docker-compose.yml文件。services: prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./rules:/etc/prometheus/rules:ro - prom-data:/prometheus ports: - 9090:9090 command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.retention.time90d restart: always snmp-exporter: image: prom/snmp-exporter:latest container_name: snmp-exporter volumes: - ./snmp.yml:/etc/snmp_exporter/snmp.yml:ro ports: - 9116:9116 restart: always grafana: image: grafana/grafana:latest container_name: grafana environment: - GF_SECURITY_ADMIN_PASSWORDadmin123 volumes: - grafana-data:/var/lib/grafana ports: - 3000:3000 restart: always volumes: prom-data: grafana-data:需要注意这里我先把Alertmanager去掉了等正式配告警的时候再单独加上避免一开始引入了太多组件让小白混淆。上面这个Compose文件里Prometheus的规则目录映射到了./rules所以工作目录下必须建一个rules文件夹否则Prometheus容器会因为找不到目录而启动失败这是我第一次部署时踩过的坑。3.3 初始化snmp_exporter与Prometheus抓取配置现在需要准备snmp_exporter的配置文件snmp.yml。好消息是官方默认配置就能覆盖绝大多数场景不需要自己用MIB生成器去从头生成。在workdir下把官方的snmp_exporter默认配置文件下载下来用snmpwalk对设备做连通性验证之后再接入。接下来是Prometheus的配置文件prometheus.yml。global: scrape_interval: 30s evaluation_interval: 30s rule_files: - /etc/prometheus/rules/network.yml scrape_configs: - job_name: network_device metrics_path: /snmp params: module: [if_mib] auth: [public_v2] static_configs: - targets: - 192.168.10.1 - 192.168.10.2 - 192.168.10.3 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: snmp-exporter:9116这个配置需要仔细说一下。metrics_path指定为/snmp表示采集路径走snmp_exporter的HTTP接口。params里的module指定了使用if_mib这个模块它主要采集接口相关的指标auth指定了认证方式默认snmp.yml里提供了一套public_v2的配置对应的就是SNMP v2c且团体名为public的情况。relabel_configs这一段是做动态参数替换的作用很关键。原始target是设备IP地址但Prometheus实际上要访问的却是snmp_exporter容器所以需要把原来的目标地址改掉先把__address__的值放入__param_target参数这样snmp_exporter就知道要去采集哪台设备再把instance标签设置为设备IP便于在图表和告警里区分最后把__address__改写成snmp-exporter:9116让请求发往snmp_exporter容器。如果设备的团体名不是Public可以提前在snmp.yml里改好对应的auth配置。打开snmp.yml找到auths下的public_v2段落把community的值改成你设备的实际团体名如果版本是SNMP v1就把version改成1。启动环境之前记得在rules目录里先放一个最简单的告警规则文件避免Prometheus因为规则文件缺失而报错。可以先放个空的rules文件占位后面再填充告警内容。运行docker compose up -d稍等片刻登录Prometheus的Web界面地址是服务器IP加端口9090打开Status-Targets页面就能看到network_device这个采集任务下的设备列表。如果状态是UP就说明SNMP采集链路已经通了。3.4 用Grafana把数据变成可视面板采集链路通了之后下一步就是出图。打开Grafana界面初始账号密码在Compose文件里已经设好首次登录后建议先改密码。在Grafana里添加数据源选择PrometheusURL填写http://prometheus:9090保存即可。这里注意写在Compose网络里的Grafana可以直接用服务名prometheus访问不需要填写服务器的外部IP。面板可以直接导入社区现成的网络设备监控模板也可以从零开始画。直接导入是最快的在Grafana的Dashboards-Import页面里输入模板ID或者上传导出的JSON文件就能获得一套已经排好版的图表里面通常包含接口流量、错误包、CPU、内存等常见指标。我建议从零开始画一个简单的接口流量面板这能帮助你真正理解这套监控的数据结构。新建面板后在查询编辑器里输入sum(rate(ifHCInOctets[5m])) by (instance, ifName) * 8这串PromQL的含义是计算每个设备实例上每个接口在过去5分钟内的平均入方向字节速率乘以8换算成比特速率。同理出方向流量就用ifHCOutOctets。如果想让图表以MB/s为单位显示除以1024再除以8即可。面板变量也是一个很实用的功能。可以在Dashboard Settings的Variables里新建一个变量查询条件写成label_values(ifHCInOctets, instance)这样面板顶部就会出现一个设备下拉列表切换设备就能快速查看不同设备的图表不用在查询里手动改IP。4. 三种主流设备接入实操从交换机到防火墙到路由器4.1 交换机端口流量、状态与错误监控交换机是网络设备监控里最常用的一类对象。标准IF-MIB就能覆盖接口层面的绝大部分数据包括接口名称、索引、速率、状态、流入流出字节数、错误包数等。推荐优先监控的指标包括ifOperStatus接口操作状态、ifInOctets和ifOutOctets接口出入方向流量、ifInErrors和ifOutErrors出入方向错误包、ifInDiscards和ifOutDiscards丢弃包以及ifHighSpeed接口协商速率。我在实际接入一台48口交换机时通过if_mib模块自动发现了上百个接口指标Grafana图里每个物理口都自动带上了ifName标签比如GigabitEthernet0/1这种命名一眼就能定位到具体端口。这里有个细节要提醒接口监控的计数器分32位和64位两类。32位计数器最大才到42.9亿按千兆速率来算每秒能累加约1.25亿字节大约34秒就会翻转归零。所以监控核心链路时一定优先选择64位的高容量计数器也就是ifHCInOctets和ifHCOutOctets而不是老的ifInOctets。接口状态这块还容易踩坑。ifOperStatus等于1表示接口up等于2表示down。如果你想在告警里区分“端口被人手动关闭”和“物理线路中断”可以同时看ifAdminStatus如果管理状态是down说明端口是主动关闭的属于预期行为如果管理状态up而操作状态down才说明物理链路出了问题。4.2 防火墙会话数与资源水位监控防火墙的监控重点和交换机不太一样。除了基本的接口流量防火墙最让人揪心的是会话数——当并发会话数逼近设备上限时新连接就会被拒绝影响范围往往不只是单个网络区域而是整个业务系统。标准MIB里其实没有“当前会话数”这种通用OID因为不同厂商把会话数暴露在不同的私有MIB区域。正确的做法是先登录防火墙管理界面确认是否支持通过SNMP查询会话数然后在监控服务器上用snmpwalk工具遍历设备的MIB树找到包含Session、Conn、Current这些关键字的OID把对应的OID手动补充到snmp_exporter配置里。这个过程对小白来说可能听起来有点深但实际操作并不复杂。找OID的通用套路是snmpwalk -v2c -c public 192.168.10.2 1.3.6.1.4.1这条命令会把设备私有MIB区域的所有OID和值都遍历出来输出量可能比较大建议配合grep过滤Session或Connection等关键词。如果暂时不想折腾私有OID退一步说先把防火墙的CPU利用率、内存使用率和接口吞吐监控起来也足以覆盖大部分日常故障场景了。我自己见过不少线上事故其实在出问题前半个小时CPU或者接口流量就已经出现明显异常有监控就能提前介入。4.3 路由器链路质量与资源监控路由器监控和交换机的重合度很高接口流量、状态这些照样要看。但路由器往往承担着链路接入的任务所以还需要额外关注链路质量方面的指标。如果路由器是连接运营商专线的建议监控出口接口的出入流量、带宽利用率、错误包率以及在Grafana里单独做一个链路质量仪表盘。还可以配合blackbox_exporter每隔一段时间主动探测一次对端网关地址或目标服务端口来判断链路是不是真的通着。这里说的探测不是SNMP协议而是通过ICMP ping或者TCP拨测来实现可以和SNMP采集形成互补。路由器自身的CPU和内存一般通过HOST-RESOURCES-MIB就能取到标准模块里通常会自动带上hrProcessorLoad和内存池相关指标。部分高端设备还支持温度、光模块功率、风扇转速等硬件健康指标但这些数据是否开放取决于设备型号和MIB库我们只需要在接入后发现没有对应的指标并不需要过度纠缠。4.4 批量接入多设备时建议使用的组织方式设备数量一多该怎么组织采集任务我的经验是尽量不要把所有品牌、所有类型的设备全部塞进同一个Job。建议按设备类型或者按机房位置划分多个Job比如network_device_site_a、network_device_site_b或者network_device_switch、network_device_firewall。每个Job可以配置不同的module和auth因为不同类型设备使用的认证信息可能并不一致拆开之后告警规则和图形查询也更好写。Prometheus里每个Job都是独立并发抓取的如果设备太多单实例的snmp_exporter可能成为瓶颈。最简单的扩展方式就是多起几个snmp_exporter容器实例然后在Prometheus配置里为不同的target组配置不同的exporter地址。Docker Compose里用replicas字段也能实现但要注意端口不能冲突可以给每个实例映射不同的物理端口。5. 真实环境踩坑记录与快速排查方法5.1 抓取超时、context deadline exceeded这是我最常遇到的报错prometheus日志里会出现context deadline exceeded通常由两个原因导致。第一个是Prometheus给snmp_exporter定的抓取超时太短。默认scrape_timeout是10秒但有些老设备响应慢走一趟SNMP GETNEXT要遍历整棵MIB树10秒根本不够。解决办法是在job配置里显式增加scrape_timeout比如改成60s。第二个原因是snmp_exporter自身的超时设置。snmp_exporter也有自己的超时参数默认可能是5秒如果设备UDP延迟高或者MIB树比较大在exporter内部就超时了。可以使用snmp-exporter启动参数--timeout来调大比如--timeout30s。排查这类问题建议先在服务器上直接手动执行snmpwalk命令测试对目标设备的实际响应速度。如果snmpwalk都慢说明问题出在设备侧或网络侧调Prometheus超时只是治标不治本。5.2 指标全为0或NaN怎么排查设备采集成功了导出指标也都存在但很多数值始终是0或者NaN这种场景常见的原因有三个。第一个是MIB不匹配。标准MIB和厂商私有MIB里的OID不是一回事如果某个指标在snmp_exporter配置里是从私有MIB取值的而目标设备并不支持这个MIB自然拿到空值。这种情况需要用snmpwalk先确认OID在目标设备上到底有没有返回值。第二个是计数器类型选择错误。在snmp.yml里配置的是32位计数器ifInOctets但设备接口速率高计数器频繁翻转rate计算出来就忽高忽低甚至接近0。换成ifHCInOctets这类64位计数器即可。第三个是设备本身接口没有流量或者接口处于down状态。这个看起来像废话但真遇到过有人拿一个没有接线的VLAN接口去验证面板查了半天配置最后发现物理口本来就是空的。先确认设备的基本状态再谈数据对不对。5.3 SNMP认证失败的一堆可能原因SNMP认证失败是另一个高频问题尤其是第一次接入新设备时。最常见的是团体名错误。很多同学以为团体名写着Public实际上设备上配的是public大小写不同直接不通。还有一种情况是设备对新连接有源IP限制只允许特定管理网段的IP来访问SNMP服务而监控服务器的IP不在白名单里。具体排查路径是这样的。先在监控服务器上用snmpget手动测一次snmpget -v2c -c public 192.168.10.1 1.3.6.1.2.1.1.5.0如果这个命令能返回设备名称说明SNMP基本通路没问题。如果返回超时再用tcpdump抓包看目标设备UDP 161端口有没有响应就能判断是网络不通还是设备拒绝了认证。SNMP v3的认证失败原因更复杂涉及username、auth protocol、passphrase、privacy protocol四组参数的匹配任何一个不对都会报错。我通常先在设备上用一个现成的SNMP v3客户端工具测试通过再把这些参数原封不动填到snmp.yml里能减少很多无谓的排查。5.4 设备计数器的翻转与走势异常如果Grafana里接口流量曲线突然断崖式下跌又快速恢复或者出现莫名其妙的大尖峰计数器翻转是最可能的原因之一。前面提到过32位计数器最大到42.9亿高速接口下很快就会翻转。对于这种场景查询接口速率时要用64位计数器的ifHCInOctets搭配rate函数来计算。使用rate计算时Prometheus会在内部做counter重置检测一旦发现下一个值比上一个值小就自动按翻转处理。但如果采集间隔较长以至于两次采样间隔内计数器翻转了不止一圈那Prometheus也无法还原真实增量。所以采集周期要足够短网络设备建议30秒到60秒一次不要因为省资源调到5分钟以上。关于曲线出现尖峰的另一个常见原因是设备重启。设备重启后计数器清零rate计算会把大量增量集中到一个时间点画出异常尖峰。这通常不是监控自身故障而是设备重启信号这时候反而要引起警觉。5.5 常见问题速查表症状可能原因处理建议Target状态为DOWN设备UDP不通、防火墙拦截、团体名错误用snmpget手动验证再检查Prometheus relabel配置抓取超时设备响应慢、MIB树太大、采集周期太短调大scrape_timeout和exporter的--timeout参数指标全为0MIB不匹配、计数器选错、接口本身无流量用snmpwalk确认OID切换64位计数器曲线出尖峰或断崖计数器翻转、设备重启、采集间隔过长改用64位计数器缩短scrape_interval接口状态误报ifAdminStatus被忽视结合ifAdminStatus判断接口是否预期downSNMP v3认证失败参数四项不匹配先用SNMP客户端工具验证再填配置我个人在实际操作中最受益的一条经验是先把所有设备的SNMP连通性用脚本批量测一遍别一台一台接。写个简单的shell循环逐个执行snmpget输出结果里一眼就能看出哪些设备通哪些不通。处理完连通性问题后再去调Prometheus配置效率会高非常多。最后再提醒一句snmp.yml和prometheus.yml这些配置文件改造完一定要随手备份并纳入版本管理因为在线上环境里一份写好的配置可能要用好几年。