4、监控系统部署:Prometheus+Grafana监控栈搭建、Exporter开发、告警规则配置
好,咱们进入实战环节。这一章我打算把PTN网络的监控系统完整地搭起来。说白了,就是让Prometheus当数据采集员,Grafana当仪表盘画师,再配上我们自己写的Exporter,最后把告警规则一配——一套能用的监控栈就齐活了。
我在多个运营商的项目里都这么干过,这套组合拳打下来,PTN网络的流量、时延、丢包率基本都能实时看到。嗯,咱们一步步来。
4.1 Prometheus + Grafana 基础部署
先装Prometheus。我个人习惯用Docker部署,省心、干净、好迁移。你想想看,要是每台机器都手动装一遍,那得多累。
# docker-compose.yml 示例
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- ./grafana-data:/var/lib/grafana
Prometheus的配置文件是关键。你得告诉它去哪抓数据。这里我踩过一个坑——抓取间隔设得太短,结果把PTN设备的CPU打满了。后来我改成15秒一次,稳得很。
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'ptn_exporter'
static_configs:
- targets: ['192.168.1.100:9100']
labels:
group: 'ptn-devices'
4.2 Exporter 开发实战
Prometheus自己没法直接读懂PTN设备的SNMP数据,所以得写个Exporter做翻译。说白了,Exporter就是个中间人——它去设备上抓数据,然后转成Prometheus能吃的格式。
我推荐用Python写,快。下面这个例子,是我从一个真实项目中抽出来的核心代码。它通过SNMP采集PTN设备的端口流量。
# ptn_exporter.py
from prometheus_client import start_http_server, Gauge
import time
import subprocess
# 定义指标
port_rx_bytes = Gauge('ptn_port_rx_bytes', '接收字节数', ['device', 'port'])
port_tx_bytes = Gauge('ptn_port_tx_bytes', '发送字节数', ['device', 'port'])
def collect_snmp_data(device_ip, community='public'):
"""通过SNMP采集端口流量"""
oid_if_in_octets = '1.3.6.1.2.1.2.2.1.10'
oid_if_out_octets = '1.3.6.1.2.1.2.2.1.16'
# 用snmpwalk获取数据
result = subprocess.run(
['snmpwalk', '-v2c', '-c', community, device_ip, oid_if_in_octets],
capture_output=True, text=True
)
for line in result.stdout.split('\n'):
if line:
# 解析SNMP响应
parts = line.split('=')
if len(parts) == 2:
port_index = parts[0].split('.')[-1]
value = int(parts[1].strip().split()[0])
port_rx_bytes.labels(device=device_ip, port=port_index).set(value)
if __name__ == '__main__':
start_http_server(9100)
while True:
collect_snmp_data('192.168.1.1')
time.sleep(15)
4.3 告警规则配置
数据有了,仪表盘有了,但你不能24小时盯着屏幕吧?告警才是监控的灵魂。Prometheus的告警规则用YAML写,语法很直观。
我一般把告警分成三级:信息、警告、严重。比如端口流量超过80%带宽就警告,超过95%就严重。下面是我常用的规则。
# alert_rules.yml
groups:
- name: ptn_alerts
rules:
- alert: PortBandwidthHigh
expr: |
rate(ptn_port_rx_bytes[5m]) / 1000000000 > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "端口 {{ $labels.port }} 带宽使用率超过80%"
description: "设备 {{ $labels.device }} 端口 {{ $labels.port }} 当前带宽使用率 {{ $value | humanizePercentage }}"
- alert: PortBandwidthCritical
expr: |
rate(ptn_port_rx_bytes[5m]) / 1000000000 > 0.95
for: 2m
labels:
severity: critical
annotations:
summary: "端口 {{ $labels.port }} 带宽使用率超过95%"
description: "立即检查!设备 {{ $labels.device }} 端口 {{ $labels.port }} 已接近满载"
for字段很重要。它表示持续多长时间才触发告警。我建议设5分钟以上,避免网络抖动导致的误报。你想想看,要是半夜被一个假告警吵醒,那多闹心。
4.4 集成测试与验证
所有组件都部署好了,怎么验证?我有个习惯——先手动触发一个告警,看看能不能收到通知。比如用curl模拟高流量数据。
# 模拟高流量,触发告警
curl -X POST http://localhost:9100/metrics \
-d 'ptn_port_rx_bytes{device="192.168.1.1",port="1"} 950000000'
然后去Grafana的Alerting页面看,告警状态应该从pending变成firing。嗯,这里要注意——Prometheus的告警状态机:pending表示条件满足但还没到持续时间,firing才是真正触发。
我曾在一次割接中,因为忘了配告警接收人,结果设备挂了半小时没人知道。从那以后,我每次部署完都会做一次端到端测试:从数据采集到告警通知,全链路走一遍。
4.5 避坑指南
最后,分享几个我踩过的坑,你遇到了能少走弯路。
- 时间不同步:Prometheus和PTN设备的时间必须一致。我遇到过因为NTP没配,导致数据对不上的情况。解决办法:所有设备统一用NTP服务器同步。
- SNMP版本:PTN设备大多支持v2c,但有些老设备只支持v1。我建议统一用v2c,性能好,安全性也还行。
- 数据存储:Prometheus默认存15天。如果你需要长期保存,要么调大retention时间,要么用Thanos做远端存储。我个人习惯保留30天,够用了。
- 告警风暴:别把所有告警都设成严重级别。我曾经一次割接触发了200多条告警,手机都快炸了。后来我按优先级分级,关键告警才发短信。
好了,这一章的内容就到这。Prometheus+Grafana这套栈,说白了就是三个步骤:搭环境、写Exporter、配告警。你按这个顺序来,基本不会出大问题。下一章咱们聊聊流量分析的高级玩法,比如如何识别异常流量模式。