Zabbix + Prometheus 混合监控架构:传统基础设施 + 云原生服务的双栈方案
2024 年底我们完成了从 Zabbix 单栈到 Zabbix + Prometheus 双栈的迁移。原因很简单:Zabbix 管传统基础设施很稳,但 Prometheus 在 K8s 动态环境里是天生的。两个工具各管一段,Grafana 统一展示,告警收敛到一个出口。这篇把整个架构设计和迁移踩坑过程写下来。
为什么需要双栈
单一监控系统在以下场景会显得力不从心:
| 场景 | Zabbix 的短板 | Prometheus 的短板 |
|---|---|---|
| 动态 K8s 集群 | 静态配置,服务发现困难 | 擅长,原生 Service Discovery |
| 网络设备监控 | 擅长 SNMP | 需要 exporter,覆盖不全 |
| 高基数指标 | 关系库膨胀严重 | 高基数标签会撑爆内存 |
| 长期数据存储 | 擅长,SQL backed | 需要 Thanos/Cortex 扩展 |
| 告警规则 | 触发器语法老旧 | PromQL 灵活,但学习曲线陡 |
结论:传统设施用 Zabbix,云原生服务用 Prometheus,不要试图一个工具吃全部。
架构设计
┌─────────────────────────────────────────────────────────────┐
│ Grafana (统一展示) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 基础设施看板 │ │ 云原生看板 │ │ 告警收敛看板 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
└─────────┼────────────────┼────────────────────┼─────────────┘
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Zabbix │ │Prometheus │ │ Alertman. │
│ Server │ │ + │ │ │
│ (传统) │ │ Alerts │ │ 统一路由 │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Agent/ │ │ K8s │ │ 企微/ │
│ SNMP │ │ Service │ │ 钉钉 │
│ 设备 │ │ Discover │ │ Webhook │
└───────────┘ └───────────┘ └───────────┘
关键设计点:
- 数据源分离:Zabbix 只管 SNMP/Agent/主动检查,Prometheus 只管 HTTP Exporter/Service Discovery
- 统一展示:Grafana 同时连接 Zabbix 和 Prometheus 数据源
- 告警收敛:Alertmanager 和 Zabbix Action 都转发到同一个 Webhook,按 severity 合并路由
Zabbix 侧配置要点
1. 保留传统监控
已迁移到 Prometheus 的:
- Kubernetes 集群内的 Pod/Meta
- 微服务 HTTP 指标(/metrics 端点)
- 容器资源指标(cAdvisor)
保留在 Zabbix 的:
- 物理服务器(CPU/内存/磁盘)
- 网络设备(交换机/路由器 SNMP)
- 传统数据库(MySQL/PG 慢查询)
- 打印机、UPS、空调等 IoT 设备
2. Zabbix Agent 2 配置
# zabbix_agent2.conf
Server: 10.0.0.5
ServerActive: 10.0.0.5
Hostname: physical-server-01
# 启用 SNMP 模块监控网络设备
LoadModule: snmp.so
# 启用 Prometheus exporter 做双向桥接
LoadModule: prometheus.so
3. Zabbix 告警 Webhook 转发
// Zabbix Media Type - Webhook 配置
{
"url": "http://alert-router:8080/zabbix",
"method": "POST",
"body": {
"source": "zabbix",
"host": "{HOST.NAME}",
"item": "{ITEM.NAME}",
"value": "{ITEM.LASTVALUE}",
"severity": "{TRIGGER.SEVERITY}"
}
}
Prometheus 侧配置要点
1. K8s Service Discovery
# prometheus.yml
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- job_name: 'kubernetes-services'
kubernetes_sd_configs:
- role: service
2. 传统 Exporter 补充
# 覆盖 Zabbix 管不了的部分
scrape_configs:
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'blackbox'
static_configs:
- targets: ['https://example.com', 'https://api.example.com']
3. 告警路由收敛
# alertmanager.yml
route:
receiver: 'unified-webhook'
group_by: ['alertname', 'cluster', 'service']
routes:
- matchers:
- source = prometheus
receiver: 'p0-oncall'
repeat_interval: 30m
receivers:
- name: 'unified-webhook'
webhook_configs:
- url: 'http://alert-router:8080/alertmanager'
- name: 'p0-oncall'
webhook_configs:
- url: 'http://alert-router:8080/p0'
Grafana 统一展示
1. 添加数据源
Settings → Data Sources → Add data source
Prometheus:
URL: http://prometheus:9090
Access: Proxy
Zabbix:
URL: http://zabbix:80
JSON RPC API
Username/Password: Admin/zabbix
2. 混用 Dashboard
3. 统一告警看板
创建专门的"告警收敛"Dashboard,同时展示 Prometheus 和 Zabbix 的活跃告警:
# Prometheus 面板
title: "Prometheus 活跃告警"
targets:
- expr: ALERTS{alertstate="firing"}
format: table
# Zabbix 面板
title: "Zabbix 活跃触发器"
datasource: Zabbix
items:
- host: "All"
filter:
value: ">0"
告警收敛实战
问题:同一故障报两次
现象:服务器宕机,Zabbix 报 SNMP 不可达,Prometheus 报 Node Exporter 失联。
根因:两个系统独立告警,没有关联。
解决方案:
# Alertmanager 抑制规则:Zabbix 核心主机告警时,抑制 Prometheus 同主机告警
inhibit_rules:
- source_matchers:
- source = zabbix
- severity = critical
target_matchers:
- source = prometheus
equal: ['instance']
问题:告警风暴
现象:Zabbix 和 Prometheus 同时告警,微信群半小时刷 500 条。
解决方案:
# 统一的 group_by 维度
group_by: ['alertname', 'infrastructure', 'service']
group_wait: 10s
group_interval: 5m
repeat_interval: 4h
# 按来源分级
routes:
- matchers:
- severity = critical
receiver: 'p0-oncall'
- matchers:
- source = zabbix
receiver: 'zabbix-wechat'
- matchers:
- source = prometheus
receiver: 'prometheus-wechat'
迁移路线(四步走)
第一步:并行运行(第 1-2 周)
- Zabbix 继续管所有设备
- Prometheus 只采集新上线的 K8s 服务
- 两边独立告警,不影响生产
- 目标是验证 Prometheus 数据采集正常
第二步:Grafana 统一展示(第 3-4 周)
- Grafana 同时连接两个数据源
- 创建混合 Dashboard
- 团队习惯在新看板里查数据
- 旧 Zabbix UI 逐渐停用
第三步:告警收敛(第 5-6 周)
- 配置 Alertmanager 抑制规则
- 配置 Zabbix Webhook 转发
- 统一到企业微信/钉钉
- 验证告警不重复、不漏报
第四步:逐步迁移(第 7-8 周)
- 新上线服务一律走 Prometheus
- 旧物理机根据情况决定留 Zabbix 还是迁 Prometheus
- 网络设备继续 Zabbix(SNMP 是唯一选择)
- 保留 Zabbix 作为"保底",不急于删
翻车案例
案例 1:Zabbix 高基数标签爆炸
现象:Zabbix 导入 Prometheus 数据后,关系库每秒写入 10 万行,查询超时。
根因:Prometheus 的标签模型不适合 Zabbix 的关系库设计。
教训:Zabbix 只导入聚合后的指标(CPU 平均、内存总量),不导入原始的高基数时序数据。
案例 2:Grafana Zabbix 插件数据延迟
现象:Zabbix 数据在 Grafana 里显示有 5 分钟延迟。
根因:Zabbix API 默认缓存 300 秒,且查询是轮询模式。
教训:监控实时性要求高的场景(如故障定位),必须用 Prometheus,Zabbix 只用于历史趋势和容量规划。
案例 3:两套系统时间不同步
现象:Grafana 里 Prometheus 和 Zabbix 的时间轴对不上。
根因:两台服务器 NTP 不同步,时差 30 秒。
教训:所有监控服务器必须严格同步 NTP,偏差超过 1 秒就会导致关联分析出错。
架构选型决策树
你要监控什么?
│
├─ K8s 集群 / 微服务 / 容器
│ └─ 直接用 Prometheus + Alertmanager
│
├─ 物理服务器 / 虚拟机
│ ├─ 有 /metrics 端点 → Prometheus Node Exporter
│ └─ 只有 SNMP / 无 Exporter → Zabbix Agent
│
├─ 网络设备(交换机/路由器)
│ └─ 只用 Zabbix(SNMP 是唯一选择)
│
├─ 传统数据库(MySQL/PG)
│ ├─ 新版本有 exporter → Prometheus
│ └─ 老版本 → Zabbix DB 监控模板
│
└─ IoT 设备 / 打印机 / UPS
└─ Zabbix(SNMP/Modbus)
写在最后
混合监控不是"选 A 还是选 B"的问题,而是"谁干什么"的分层问题。Zabbix 和 Prometheus 不是竞争对手,是互补关系。
核心原则:
- 能分层就别堆砌——传统归传统,云原生归云原生
- 统一出口是关键——Grafana + 统一 Webhook
- 告警收敛是难点——抑制规则 + 重复维度 group_by
- 迁移要渐进——并行 → 统一展示 → 收敛 → 迁移,别一步到位
监控系统的终极目标不是"装了多少工具",而是"故障发生时能不能快速定位"。工具只是手段,分层架构才是正道。