首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Zabbix和Prometheus咋结合使用?

Zabbix和Prometheus咋结合使用?

作者头像
IT运维技术圈
发布2025-10-09 12:15:10
发布2025-10-09 12:15:10
13900
代码可运行
举报
文章被收录于专栏:IT运维技术圈IT运维技术圈
运行总次数:0
代码可运行

0. 写在前面:为什么你需要“神器”而非“常用命令

大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.

帮老杨点赞、转发、在看以及打开小星标哦

攒今世之功德,修来世之福报


大部分公司都是同时跑 Zabbix 和 Prometheus。 告警在两个地方响,查问题得在两个系统里切换。 这很消耗时间,也容易漏细节。 但是又没必要二选一,直接把数据打通即可

为什么要打通?

Zabbix 擅长老设备和长期历史数据。 Prometheus 擅长容器、实时指标和复杂查询。 把两者结合,可以更快定位业务问题。 举例说明。双十一时,Prometheus 报订单延迟高。 同时查看 Zabbix 的底层指标,能判断是不是服务器或网络问题。 我在一次大促里,用这种方法把排查时间从 30 分钟缩到 5 分钟。

它们的关键差异

  • • 采集方式不同。Zabbix 用 Agent 推或轮询。Prometheus 用拉取 Exporter。
  • • 存储策略不同。Zabbix 用关系型数据库,数据能存很多年。Prometheus 默认保留期短。
  • • 查询与告警不同。Zabbix 用触发器。Prometheus 用 PromQL,可以写更灵活的查询。
  • • 可视化不同。Zabbix 自带图表。Prometheus 常配 Grafana。

这些差异决定了分工方式。分工常比替换更实际。

三种常见的并行方案

方案 A — Zabbix 为主,Prometheus 打辅助 适合设备多、容器少的公司。改动小,上手快。

方案 B — Prometheus 为主,Zabbix 管老设备 适合容器多的团队。Prometheus 做实时监控。Zabbix 留给 SNMP 和历史报表。

方案 C — 双系统并行,统一展示与告警 适合大型团队。两边各自运行。用 Grafana 做统一看板,告警统一推送。配置复杂但稳妥。

选方案前,先评估资产与团队能力。先做小规模试点。

让它们对话的几个要点

要点很直接。先打通告警,再共享数据,最后统一展示。 我常用的流程是:

  1. 1. Alertmanager 发现异常。
  2. 2. 通过 Webhook 把告警发到一个中间服务。
  3. 3. 中间服务调用 Zabbix API,创建或关闭问题。
  4. 4. Grafana 同时连接 Zabbix 和 Prometheus。这样能在一个看板看到全链路数据。

Alertmanager webhook 配置示例

代码语言:javascript
代码运行次数:0
运行
复制
# alertmanager.yml
global:
  smtp_smarthost: 'localhost:587'

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'webhook-zabbix'

receivers:
- name: 'webhook-zabbix'
  webhook_configs:
  - url: 'http://zabbix-webhook-service:8080/webhook'
    send_resolved: true

Webhook 中间服务(接收告警并写入 Zabbix)

代码语言:javascript
代码运行次数:0
运行
复制
# webhook_handler.py
from flask import Flask, request, jsonify
import requests
import json
import datetime

app = Flask(__name__)

# Zabbix API 配置
ZABBIX_URL = "http://zabbix-server/api_jsonrpc.php"
ZABBIX_USER = "admin"
ZABBIX_PASSWORD = "zabbix"

def get_zabbix_token():
    """获取 Zabbix API 认证 token"""
    payload = {
        "jsonrpc": "2.0",
        "method": "user.login",
        "params": {
            "user": ZABBIX_USER,
            "password": ZABBIX_PASSWORD
        },
        "id": 1
    }
    
    response = requests.post(ZABBIX_URL, json=payload)
    result = response.json()
    
    if "result" in result:
        return result["result"]
    else:
        raise Exception(f"Failed to login: {result}")

def create_zabbix_problem(alert_data, token):
    """在 Zabbix 中创建问题"""
    severity_map = {
        "critical": 5,
        "warning": 3,
        "info": 1
    }
    
    for alert in alert_data["alerts"]:
        problem_data = {
            "jsonrpc": "2.0",
            "method": "problem.create",
            "params": {
                "eventid": f"prometheus_{alert['fingerprint']}",
                "source": 0,  # 0 = trigger, 1 = discovery, 2 = auto registration, 3 = internal
                "object": 0,  # 0 = trigger
                "objectid": 1,  # 可以配置具体的 trigger ID
                "clock": int(datetime.datetime.now().timestamp()),
                "value": 1,  # 1 = problem, 0 = ok
                "severity": severity_map.get(alert.get("labels", {}).get("severity", "info"), 1)
            },
            "auth": token,
            "id": 2
        }
        
        # 发送到 Zabbix
        response = requests.post(ZABBIX_URL, json=problem_data)
        print(f"Zabbix response: {response.json()}")

@app.route('/webhook', methods=['POST'])
def webhook():
    """处理 Prometheus Alertmanager 的 Webhook"""
    try:
        alert_data = request.get_json()
        
        # 获取 Zabbix token
        token = get_zabbix_token()
        
        # 在 Zabbix 中创建对应的问题
        create_zabbix_problem(alert_data, token)
        
        # 可以选择同时发送钉钉通知
        send_dingtalk_notification(alert_data)
        
        return jsonify({"status": "success"}), 200
        
    except Exception as e:
        print(f"Error processing webhook: {e}")
        return jsonify({"status": "error", "message": str(e)}), 500

def send_dingtalk_notification(alert_data):
    """发送钉钉通知"""
    dingtalk_webhook = "YOUR_DINGTALK_WEBHOOK_URL"
    
    for alert in alert_data["alerts"]:
        message = {
            "msgtype": "text",
            "text": {
                "content": f"""
🚨 Prometheus 告警
- 服务: {alert.get('labels', {}).get('service', 'Unknown')}
- 严重程度: {alert.get('labels', {}).get('severity', 'Unknown')}
- 详情: {alert.get('annotations', {}).get('summary', 'No details')}
- 时间: {alert.get('startsAt', 'Unknown')}
                """.strip()
            }
        }
        
        requests.post(dingtalk_webhook, json=message)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Grafana 统一看板示例

代码语言:javascript
代码运行次数:0
运行
复制
{
  "dashboard": {
    "title": "统一监控看板",
    "panels": [
      {
        "title": "服务器 CPU 使用率(Zabbix)",
        "type": "graph",
        "targets": [
          {
            "datasource": "Zabbix",
            "queryType": "",
            "refId": "A",
            "application": "CPU",
            "item": "CPU utilization"
          }
        ]
      },
      {
        "title": "应用 QPS(Prometheus)",
        "type": "graph",
        "targets": [
          {
            "datasource": "Prometheus",
            "expr": "rate(http_requests_total[5m])",
            "refId": "B"
          }
        ]
      },
      {
        "title": "应用延迟分布(Prometheus)",
        "type": "heatmap",
        "targets": [
          {
            "datasource": "Prometheus",
            "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
            "refId": "C"
          }
        ]
      }
    ]
  }
}

实操节奏

我建议按周推进。步骤短而具体。每步都能带来价值。

第 1 周 — 清点资产与命名规范 把哪些由 Zabbix 管,哪些由 Prometheus 管列清楚。 制定命名规则。命名乱会翻车。

  • • 下面是资产清单脚本。请在你的环境运行。
代码语言:javascript
代码运行次数:0
运行
复制
#!/bin/bash
# inventory.sh - 资产清单脚本

echo "=== Zabbix 监控资产清单 ==="
echo "生成时间: $(date)"
echo ""

# 检查 Zabbix Agent
echo "## Zabbix Agent 部署情况"
for host in $(cat hosts.txt); do
    echo -n "$host: "
    if timeout 5 telnet $host 10050 </dev/null 2>/dev/null | grep -q Connected; then
        echo "✅ Zabbix Agent 运行中"
    else
        echo "❌ Zabbix Agent 未响应"
    fi
done
echo ""

# 检查 Prometheus Exporter
echo "## Prometheus Exporter 部署情况"
for host in $(cat hosts.txt); do
    echo -n "$host: "
    # 检查常见的 exporter 端口
    exporters_found=""
    
    # Node Exporter (9100)
    if timeout 3 curl -s http://$host:9100/metrics >/dev/null 2>&1; then
        exporters_found="$exporters_found node_exporter(9100)"
    fi
    
    # Application metrics (8080)
    if timeout 3 curl -s http://$host:8080/metrics >/dev/null 2>&1; then
        exporters_found="$exporters_found app_metrics(8080)"
    fi
    
    if [ -n "$exporters_found" ]; then
        echo "✅ $exporters_found"
    else
        echo "❌ 无 Prometheus Exporter"
    fi
done

第 2 周 — 搭试点 选 1~2 个非关键服务做试点。 部署 Prometheus 和 Grafana。接入这些服务的指标。

  • • 试点部署脚本如下。
代码语言:javascript
代码运行次数:0
运行
复制
#!/bin/bash
# pilot_setup.sh - 试点环境部署

echo "开始部署 Prometheus 试点环境..."

# 创建 prometheus 配置
cat > prometheus.yml << EOF
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node1:9100', 'node2:9100']

  - job_name: 'application'
    static_configs:
      - targets: ['app-server:8080']
    metrics_path: '/metrics'
    scrape_interval: 5s
EOF

# 启动 Prometheus
docker run -d \
  --name prometheus \
  -p 9090:9090 \
  -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus:latest

# 启动 Grafana
docker run -d \
  --name grafana \
  -p 3000:3000 \
  -e "GF_SECURITY_ADMIN_PASSWORD=admin123" \
  grafana/grafana:latest

echo "部署完成!访问地址:"
echo "- Prometheus: http://localhost:9090"
echo "- Grafana: http://localhost:3000 (admin/admin123)"

1–3 个月 — 逐步推广 别一次性全量迁移。并行采集同一指标。 做数据对比后,再决定是否切换采集口径。

  • • 下面是一个对比脚本。它能帮助验证两边数据差异是否在可接受范围内。
代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python3
# compare_metrics.py - 监控数据对比工具

import requests
import json
import time
from datetime import datetime, timedelta

class MetricsComparator:
    def __init__(self, zabbix_url, zabbix_token, prometheus_url):
        self.zabbix_url = zabbix_url
        self.zabbix_token = zabbix_token
        self.prometheus_url = prometheus_url
    
    def get_zabbix_metric(self, host, item_key, time_range=3600):
        """从 Zabbix 获取指标数据"""
        payload = {
            "jsonrpc": "2.0",
            "method": "history.get",
            "params": {
                "hostids": host,
                "itemids": item_key,
                "time_from": int(time.time()) - time_range,
                "time_till": int(time.time()),
                "sortfield": "clock",
                "sortorder": "DESC",
                "limit": 100
            },
            "auth": self.zabbix_token,
            "id": 1
        }
        
        response = requests.post(self.zabbix_url, json=payload)
        return response.json().get("result", [])
    
    def get_prometheus_metric(self, query, time_range="1h"):
        """从 Prometheus 获取指标数据"""
        url = f"{self.prometheus_url}/api/v1/query_range"
        params = {
            "query": query,
            "start": (datetime.now() - timedelta(hours=1)).isoformat() + "Z",
            "end": datetime.now().isoformat() + "Z",
            "step": "60s"
        }
        
        response = requests.get(url, params=params)
        return response.json().get("data", {}).get("result", [])
    
    def compare_cpu_usage(self):
        """对比 CPU 使用率"""
        print("=== CPU 使用率对比 ===")
        
        # Zabbix CPU 数据
        zabbix_data = self.get_zabbix_metric("10001", "system.cpu.util")
        zabbix_avg = sum(float(d["value"]) for d in zabbix_data) / len(zabbix_data) if zabbix_data else 0
        
        # Prometheus CPU 数据
        prom_data = self.get_prometheus_metric("100 - (avg(rate(node_cpu_seconds_total{mode='idle'}[5m])) * 100)")
        prom_avg = 0
        if prom_data and prom_data[0].get("values"):
            values = [float(v[1]) for v in prom_data[0]["values"]]
            prom_avg = sum(values) / len(values)
        
        print(f"Zabbix CPU 平均值: {zabbix_avg:.2f}%")
        print(f"Prometheus CPU 平均值: {prom_avg:.2f}%")
        print(f"差异: {abs(zabbix_avg - prom_avg):.2f}%")
        
        return abs(zabbix_avg - prom_avg) < 5  # 差异小于5%认为正常

# 使用示例
if __name__ == "__main__":
    comparator = MetricsComparator(
        zabbix_url="http://zabbix-server/api_jsonrpc.php",
        zabbix_token="your-token",
        prometheus_url="http://prometheus:9090"
    )
    
    if comparator.compare_cpu_usage():
        print("✅ 数据一致性检查通过")
    else:
        print("⚠️  数据存在较大差异,需要检查配置")

告警规则的实用建议

不要用太多瞬时阈值。短期波动会导致误报。 用 for 窗口来保证稳定告警。 在 Alertmanager 做路由与抑制,避免重复通知。 Zabbix 继续担任历史报表和设备检查的角色。Prometheus 做实时告警和复杂查询。

代码语言:javascript
代码运行次数:0
运行
复制
# alert_rules.yml - 优化后的告警规则
groups:
  - name: infrastructure
    rules:
      # CPU 使用率告警(避免短期波动)
      - alert: HighCPUUsage
        expr: avg(100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 80
        for: 10m  # 持续10分钟才告警
        labels:
          severity: warning
          service: infrastructure
        annotations:
          summary: "CPU 使用率持续过高"
          description: "服务器 CPU 使用率超过 80% 已持续 10 分钟"

  - name: application
    rules:
      # 应用响应时间告警
      - alert: HighResponseTime
        expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2
        for: 5m
        labels:
          severity: critical
          service: application
        annotations:
          summary: "应用响应时间过长"
          description: "95% 请求响应时间超过 2 秒"

      # 错误率告警
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
        for: 3m
        labels:
          severity: critical
          service: application
        annotations:
          summary: "应用错误率过高"
          description: "应用 5xx 错误率超过 5%"

真实案例

场景:电商大促。 事件:Prometheus 报订单延迟从 200ms 升到 2s。 流程:Alertmanager 触发告警。Webhook 通知中间服。中间服在 Zabbix 创建问题。运维在 Grafana 上看板查看全链路。定位到数据库连接池满。5 分钟内扩容连接池,业务恢复。

关键点是:告警互通、统一看板、提前演练。

90 分钟快速体验脚本

想快速验证?按这个脚本做。它能帮你在本地快速搭起一个体验环境。按需改配置。

代码语言:javascript
代码运行次数:0
运行
复制
#!/bin/bash
# quick_start.sh - 90分钟快速体验

echo "🚀 开始 90 分钟快速体验..."

# 1. 启动基础服务(10分钟)
echo "步骤1: 启动基础服务"
docker-compose up -d prometheus grafana node-exporter

# 2. 配置数据源(20分钟)
echo "步骤2: 配置 Grafana 数据源"
sleep 30  # 等待服务启动

# 添加 Prometheus 数据源
curl -X POST \
  http://admin:admin123@localhost:3000/api/datasources \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Prometheus",
    "type": "prometheus",
    "url": "http://prometheus:9090",
    "access": "proxy",
    "isDefault": true
  }'

# 添加 Zabbix 数据源(如果有的话)
curl -X POST \
  http://admin:admin123@localhost:3000/api/datasources \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Zabbix",
    "type": "alexanderzobnin-zabbix-datasource",
    "url": "http://zabbix-server/api_jsonrpc.php",
    "access": "proxy",
    "jsonData": {
      "username": "admin",
      "password": "zabbix"
    }
  }'

# 3. 导入示例 Dashboard(30分钟)
echo "步骤3: 导入示例 Dashboard"
# 这里可以导入预设的 Dashboard JSON

# 4. 配置简单告警(30分钟)
echo "步骤4: 配置告警规则"
# 复制告警规则到 Prometheus

echo "✅ 体验环境搭建完成!"
echo "访问 http://localhost:3000 查看效果"
echo "用户名: admin, 密码: admin123"

我给你的三条实用建议

  1. 1. 先做试点,别急着全量替换。
  2. 2. 让 Zabbix 管历史与设备,让 Prometheus 管实时与服务。
  3. 3. 用 Grafana 统一看板。别让同事看两个屏幕。

老杨时间

这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.

运维X档案系列文章:

从告警到CTO:一个P0故障的11小时生死时速

企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)

看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报

点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com

老杨AI的号: 98dev

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要打通?
  • 它们的关键差异
  • 三种常见的并行方案
  • 让它们对话的几个要点
    • Alertmanager webhook 配置示例
    • Webhook 中间服务(接收告警并写入 Zabbix)
    • Grafana 统一看板示例
  • 实操节奏
  • 告警规则的实用建议
  • 真实案例
  • 90 分钟快速体验脚本
  • 我给你的三条实用建议
  • 老杨时间
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档