0. 写在前面:为什么你需要“神器”而非“常用命令
大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.
帮老杨点赞、转发、在看以及打开小星标哦
攒今世之功德,修来世之福报
大部分公司都是同时跑 Zabbix 和 Prometheus。 告警在两个地方响,查问题得在两个系统里切换。 这很消耗时间,也容易漏细节。 但是又没必要二选一,直接把数据打通即可
Zabbix 擅长老设备和长期历史数据。 Prometheus 擅长容器、实时指标和复杂查询。 把两者结合,可以更快定位业务问题。 举例说明。双十一时,Prometheus 报订单延迟高。 同时查看 Zabbix 的底层指标,能判断是不是服务器或网络问题。 我在一次大促里,用这种方法把排查时间从 30 分钟缩到 5 分钟。
这些差异决定了分工方式。分工常比替换更实际。
方案 A — Zabbix 为主,Prometheus 打辅助 适合设备多、容器少的公司。改动小,上手快。
方案 B — Prometheus 为主,Zabbix 管老设备 适合容器多的团队。Prometheus 做实时监控。Zabbix 留给 SNMP 和历史报表。
方案 C — 双系统并行,统一展示与告警 适合大型团队。两边各自运行。用 Grafana 做统一看板,告警统一推送。配置复杂但稳妥。
选方案前,先评估资产与团队能力。先做小规模试点。
要点很直接。先打通告警,再共享数据,最后统一展示。 我常用的流程是:
# 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_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)
{
"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 管列清楚。 制定命名规则。命名乱会翻车。
#!/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。接入这些服务的指标。
#!/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 个月 — 逐步推广 别一次性全量迁移。并行采集同一指标。 做数据对比后,再决定是否切换采集口径。
#!/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 做实时告警和复杂查询。
# 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 分钟内扩容连接池,业务恢复。
关键点是:告警互通、统一看板、提前演练。
想快速验证?按这个脚本做。它能帮你在本地快速搭起一个体验环境。按需改配置。
#!/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"
这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.
运维X档案系列文章:
企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)
看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报
点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com
老杨AI的号: 98dev