跳转至

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  │
    └───────────┘    └───────────┘       └───────────┘

关键设计点:

  1. 数据源分离:Zabbix 只管 SNMP/Agent/主动检查,Prometheus 只管 HTTP Exporter/Service Discovery
  2. 统一展示:Grafana 同时连接 Zabbix 和 Prometheus 数据源
  3. 告警收敛: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

// Prometheus 查询(云原生)
up{job="kubernetes-pods"} == 0

// Zabbix 查询(传统)
last(/Zabbix server/uptime)

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 不是竞争对手,是互补关系。

核心原则:

  1. 能分层就别堆砌——传统归传统,云原生归云原生
  2. 统一出口是关键——Grafana + 统一 Webhook
  3. 告警收敛是难点——抑制规则 + 重复维度 group_by
  4. 迁移要渐进——并行 → 统一展示 → 收敛 → 迁移,别一步到位

监控系统的终极目标不是"装了多少工具",而是"故障发生时能不能快速定位"。工具只是手段,分层架构才是正道。