真实场景:Zabbix把我逼疯了
2024年Q2公司扩张,服务器从10台暴涨到30台。我负责运维,之前用的Zabbix 6.0 LTS,每加一台机器就要手动安装agent、关联模板、配置告警,搞一次至少30分钟。更恶心的是,Zabbix server的MySQL(我用的Percona 8.0)数据量大了以后,图表加载要等5秒,告警延迟有时候超过1分钟。老板半夜打电话说“某个服务挂了但告警没收到”,我当场血压飙升。
于是决定换监控体系。调研了一周:Zabbix 7.0虽然改进了,但架构还是太重;Netdata适合单机不适合集群;Prometheus+Grafana社区活跃、云原生标配。最后敲定迁移。一个月后效果:配置效率提升5倍,资源占用降低70%,告警延迟压到5秒以内。下面直接上干货。
方案对比:Zabbix vs Prometheus+Grafana
| 对比项 | Zabbix 6.0 | Prometheus 2.53 + Grafana 11 |
|---|---|---|
| 架构 | Server+Proxy+Agent,数据入库MySQL/PostgreSQL | Pull模型,TSDB时序存储,无状态 |
| 配置复杂度(30台) | 2小时(创建主机、关联模板、调整触发器) | 20分钟(批量下发exporter,一个prometheus.yml搞定) |
| 性能(30台2000个metrics) | Server 8C16G,CPU 30%,内存4.2GB,查询QPS 100 | 4C8G,CPU 5%,内存1.1GB,查询QPS 8000 |
| 告警延迟(平均) | 30秒(依赖轮询间隔) | 5秒(默认15s scrape,Alertmanager即时计算) |
| 扩展性 | 需Proxy或集群,操作复杂 | 联邦集群、Thanos、VictoriaMetrics,社区方案成熟 |
| 学习曲线 | 表达式复杂,模板分散 | PromQL简洁,Dashboard开箱即用 |
数据来源:同样30台物理机(Intel Xeon 4214,64G内存,10K RPM SAS盘),各运行一个月统计。
方案设计:双机部署+容器化
我们用了两台服务器:monitor-01(4C8G 100G SSD)运行Prometheus + Alertmanager + Grafana;monitor-02(2C4G 50G SSD)作为测试和备用。所有被监控服务器安装node_exporter。推荐用Docker Compose管理,但二进制部署也给了详细步骤。
方式一:二进制安装(适合对系统侵入性要求高或容器不支持的场景)
1. 下载并安装Prometheus 2.53.0
cd /opt
wget https://github.com/prometheus/prometheus/releases/download/v2.53.0/prometheus-2.53.0.linux-amd64.tar.gz
tar xzf prometheus-2.53.0.linux-amd64.tar.gz
ln -s prometheus-2.53.0.linux-amd64 prometheus
useradd -r -s /sbin/nologin prometheus
mkdir -p /data/prometheus
chown prometheus:prometheus /data/prometheus -R
chown prometheus:prometheus /opt/prometheus -R
2. 创建systemd服务
cat <<'EOF' > /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
After=network.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/opt/prometheus/prometheus \
--config.file=/opt/prometheus/prometheus.yml \
--storage.tsdb.path=/data/prometheus \
--web.console.templates=/opt/prometheus/consoles \
--web.console.libraries=/opt/prometheus/console_libraries \
--web.listen-address=0.0.0.0:9090
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now prometheus
3. 配置prometheus.yml(全局和scrape目标)
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'my-monitor'
rule_files:
- "rules/*.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["127.0.0.1:9093"]
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['127.0.0.1:9090']
- job_name: 'node_exporter'
scrape_interval: 10s
static_configs:
- targets:
- '192.168.1.101:9100'
- '192.168.1.102:9100'
- '192.168.1.103:9100'
- '192.168.1.104:9100'
# ... 更多服务器
4. 安装node_exporter 1.8.1(每台被监控服务器执行)
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xzf node_exporter-1.8.1.linux-amd64.tar.gz
cp node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
useradd -r -s /sbin/nologin node_exporter
# systemd服务
cat <<'EOF' > /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
After=network.target
[Service]
Type=simple
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--web.listen-address=:9100 \
--collector.systemd \
--collector.processes
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now node_exporter
# 检查端口
ss -tlnp | grep 9100
5. 安装Grafana 11.0(二进制)
wget https://dl.grafana.com/oss/release/grafana-11.0.0.linux-amd64.tar.gz
tar xzf grafana-11.0.0.linux-amd64.tar.gz
ln -s grafana-11.0.0 grafana
useradd -r -s /sbin/nologin grafana
chown grafana:grafana -R /opt/grafana
# 配置
cp /opt/grafana/conf/sample.ini /opt/grafana/conf/custom.ini
# 修改 custom.ini 至少改 admin 密码和 server 端口
systemctl enable --now grafana # 需自己写 service,类似上面
方式二:Docker Compose(推荐,省事)
# docker-compose.yml - 版本3.8
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.53.0
container_name: prometheus
user: "0:0" # 解决权限
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./rules:/etc/prometheus/rules
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
restart: unless-stopped
alertmanager:
image: prom/alertmanager:v0.27.0
container_name: alertmanager
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
- alertmanager_data:/alertmanager
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
restart: unless-stopped
grafana:
image: grafana/grafana:11.0.0
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana_data:/var/lib/grafana
- ./grafana.ini:/etc/grafana/grafana.ini # 可选
restart: unless-stopped
volumes:
prometheus_data:
alertmanager_data:
grafana_data:
启动:docker-compose up -d
配置Alertmanager告警
alertmanager.yml(钉钉+企业微信)
route:
receiver: 'dingtalk'
routes:
- match:
severity: critical
receiver: 'wechat'
receivers:
- name: 'dingtalk'
webhook_configs:
- url: 'http://127.0.0.1:8060/dingtalk/webhook1/'
send_resolved: true
- name: 'wechat'
webhook_configs:
- url: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx'
send_resolved: true
告警规则示例(rules/host_alerts.yml)
groups:
- name: host_alerts
rules:
- alert: HostHighCpuUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} CPU usage > 80%"
description: "CPU usage is at {{ $value }}% for 10 min"
- alert: HostDiskFull
expr: 100 - ((node_filesystem_avail_bytes{mountpoint="/"} * 100) / node_filesystem_size_bytes{mountpoint="/"}) > 85
for: 5m
labels:
severity: critical
annotations:
summary: "Disk on {{ $labels.instance }} is almost full"
description: "Root disk usage > 85%"
效果数据:迁移前后对比
| 指标 | 迁移前(Zabbix) | 迁移后(Prometheus+Grafana) |
|---|---|---|
| 30台服务器配置耗时 | 2小时 | 20分钟(含批量分发exporter脚本) |
| 监控Server资源占用 | 8C16G,CPU 30%,内存4.2GB | 4C8G,CPU 5%,内存1.1GB |
| 告警平均延迟 | 30秒 | 5秒 |
| 图表加载时间(TopN查询) | 2.3秒 | 0.2秒(Prometheus TSDB的delta压缩) |
| 存储每日增量(2000 metrics) | 800MB(MySQL binlog+数据) | 250MB(Prometheus本地TSDB,含wal) |
避坑指南(6个亲身踩过的坑)
坑1:时间不同步
现象:告警一直触发“HostDown”,但服务正常。排查发现被监控机系统时间比真实时间慢5分钟。Prometheus抓取数据的时间戳基于被监控机,导致数据在时间轴上“错位”。
解决:所有服务器安装chrony,配置NTP,在prometheus.yml的global下加external_labels无意义,关键要确保node_time_seconds正常。
坑2:firewalld/iptables未放行端口
现象:Prometheus 4.3.1 连不上 node_exporter,报connection refused。检查发现9100端口没开。当时手忙脚乱开了端口但忘了重载firewalld。
命令:firewall-cmd --add-port=9100/tcp --permanent && firewall-cmd --reload。注意如果是容器,要确认宿主及容器防火墙。
坑3:Prometheus存储目录权限
现象:二进制部署时忘记chown -R prometheus:prometheus /data/prometheus,Prometheus启动报permission denied。更坑的是,用systemd后无法写WAL,但日志是INFO级别,不容易发现,直到服务莫名其妙挂了。
建议:部署后立即检查journalctl -u prometheus -f。
坑4:Grafana数据源URL问题
现象:添加Prometheus数据源,URL填localhost:9090,Grafana报HTTP Error Bad Gateway。必须加http://前缀。而且注意如果Grafana和Prometheus在同一台机器,用localhost即可;如果是跨主机,要填真实IP。
坑5:告警规则for字段设置不当
现象:设置了for: 1m,结果某个CPU短暂突增到90%然后回落,告警等了1分钟才触发,其实是按for持续评估。后来改为for: 5m才稳定。另外注意for: 0s会立即触发,但容易误报。生产环境至少设置5分钟。
坑6:node_exporter版本与Prometheus不兼容
现象:node_exporter v1.7.0 有一个collector默认开启--collector.disable-defaults导致某些指标缺失,升级到1.8.1后正常。建议使用最新稳定版,并仔细看release note。
总结
这套体系在我们公司跑了4个月,零故障。迁移时用Ansible批量分发exporter和配置文件,整个过程很平滑。如果你还在用Zabbix痛苦地维护,建议考虑切过来。下篇可以写如何用PromQL做业务级监控,以及Grafana面板设计技巧。