Prometheus + Grafana 监控系统搭建实战 2026

📊 为什么需要监控? 你花几小时搭好的代理服务、博客、数据库,一旦半夜挂掉,没有监控你根本不知道。等到第二天用户来反馈,黄金恢复时间早就错过了。Prometheus + Grafana 是业界标准的开源监控组合——一个负责采集存储指标,一个负责可视化告警,配合起来几乎零成本就能拥有企业级监控能力。
本文将带你从零搭建一套完整的 VPS 监控系统:
- ✅ 监控 vs 告警:为什么两者缺一不可
- ✅ Prometheus 核心原理(时序数据库 / Pull 模型 / Exporter)
- ✅ Node Exporter 采集 CPU/内存/磁盘/网络
- ✅ Docker Compose 一键部署整套监控栈
- ✅ Grafana 看板导入与自定义
- ✅ Alertmanager 邮件 / Telegram 告警
- ✅ Nginx、SSL 证书、网站可用性进阶监控
- ✅ 多 VPS 集中管控与常见问题
一、为什么需要 VPS 监控
1.1 典型痛点
| 痛点 | 没有监控 | 有监控 |
|---|---|---|
| 服务宕机 | 用户反馈才知道 | 告警秒级推送 |
| 磁盘写满 | 数据库崩溃才发现 | 80% 容量就预警 |
| 流量异常 | 月底才发现被刷 | 实时流量曲线可见 |
| 性能劣化 | 凭感觉优化 | 数据驱动定位瓶颈 |
| 安全入侵 | 事后溯源困难 | 异常进程/连接立即可见 |
1.2 监控 vs 告警
很多人把监控等同于「看个图表」,这是片面的。两者职责不同:
- 监控(Monitoring):持续采集指标、可视化展示,让你「看得见」系统状态。
- 告警(Alerting):当指标突破阈值时主动通知你,让你「被提醒」。
💡 只有看板没有告警,等于装了摄像头却没人看;只有告警没有看板,出问题了却没法分析原因。两者必须配套。
1.3 开源方案对比
| 方案 | 组成 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| Prometheus + Grafana | 采集+可视化 | 生态最完善、查询强大、免费 | 组件稍多 | 通用首选 |
| Zabbix | 一体化 | 开箱即用、Agent 丰富 | 配置偏重、UI 老旧 | 传统企业 |
| Netdata | 一体化 | 安装极简、实时性强 | 长期存储弱、定制差 | 单机快速看 |
| Nagios | 告警为主 | 告警逻辑成熟 | 可视化弱、配置繁琐 | 纯告警场景 |
| VictoriaMetrics | 替代 Prometheus | 性能更高、存储更省 | 生态较新 | 超大规模 |
结论: 个人 VPS / 中小团队首选 Prometheus + Grafana,生态成熟、资料多、迁移成本低。
二、Prometheus 核心原理
2.1 时序数据库(TSDB)
Prometheus 存储的是时序数据——带时间戳的指标序列:
<指标名>{<标签1>=<值1>, <标签2>=<值2>} <数值> <时间戳>
node_memory_MemAvailable_bytes{instance="server-1:9100", job="node"} 3.2e+09 1750000000- 指标名:如
node_cpu_seconds_total - 标签(Label):区分维度,如
instance、job、mode - 数值:浮点数
- 时间戳:毫秒级
2.2 Pull 模型
Prometheus 采用主动拉取(Pull)模式:服务端定时去各 Exporter 的 HTTP 接口抓取指标。
Prometheus Server
│ (每 15s 拉取 /metrics)
├──> Node Exporter :9100/metrics
├──> Nginx Exporter :9113/metrics
└──> Blackbox Exporter :9115/metricsPull vs Push 对比:
| 维度 | Pull(Prometheus) | Push(如 StatsD) |
|---|---|---|
| 服务发现 | 天然支持 | 需额外注册 |
| 故障定位 | 谁挂了一目了然 | 推送失败难排查 |
| 防火墙 | 服务端主动出 | 客户端主动出 |
| 短任务 | 需 Pushgateway 中转 | 天然支持 |
2.3 Exporter 生态
Exporter 是「指标翻译器」,把各系统的内部状态暴露成 Prometheus 格式:
| Exporter | 监控对象 |
|---|---|
| Node Exporter | 主机 CPU/内存/磁盘/网络 |
| cAdvisor | Docker 容器 |
| Nginx Exporter | Nginx 连接/请求 |
| MySQL Exporter | 数据库状态 |
| Blackbox Exporter | HTTP/DNS/TCP 探测 |
| Redis Exporter | 缓存状态 |
| Process Exporter | 指定进程 |
三、Node Exporter 部署
3.1 Docker 方式
docker run -d \
--name node-exporter \
--restart=always \
--network host \
--pid host \
-v "/proc:/host/proc:ro" \
-v "/sys:/host/sys:ro" \
-v "/:/rootfs:ro" \
prom/node-exporter:latest \
--path.procfs=/host/proc \
--path.sysfs=/host/sys \
--path.rootfs=/rootfs3.2 二进制方式(Systemd)
# 下载
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xzf node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
# 创建 systemd 服务
sudo tee /etc/systemd/system/node-exporter.service > /dev/null <<'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# 创建专用用户并启动
sudo useradd -rs /bin/false node_exporter
sudo systemctl daemon-reload
sudo systemctl enable --now node-exporter3.3 验证指标
curl http://localhost:9100/metrics | head -20
# 应看到 node_cpu_seconds_total、node_memory_MemAvailable_bytes 等指标3.4 安全加固(重要)
Node Exporter 默认无认证,切勿直接暴露公网。推荐用 Nginx 反向代理 + Basic Auth 或仅监听内网:
# /etc/nginx/conf.d/node-exporter.conf
location /metrics {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:9100;
}四、Prometheus 服务端部署
4.1 Docker Compose 完整配置
创建 docker-compose.yml:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: always
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: always
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_strong_password
volumes:
- grafana_data:/var/lib/grafana
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: always
network_mode: host
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
volumes:
prometheus_data:
grafana_data:4.2 Prometheus 配置文件
prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
# 监控 Prometheus 自己
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 监控本机
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
labels:
instance: 'server-main'
# 监控另一台 VPS(通过内网/隧道 IP)
- job_name: 'node-remote'
static_configs:
- targets: ['10.0.0.2:9100']
labels:
instance: 'server-edge'4.3 数据保留与性能
| 参数 | 说明 | 建议 |
|---|---|---|
retention.time | 数据保留时长 | 15~30d(个人) |
retention.size | 数据体积上限 | 如 2GB 防止写满磁盘 |
wal-compression | WAL 压缩 | 开启节省空间 |
磁盘占用估算:
每目标 ≈ 1~2 MB/天(默认采集频率)
30 天 × 5 目标 ≈ 150~300 MB4.4 启动与验证
docker compose up -d
# 访问 http://你的IP:9090
# 在 Graph 页面执行: up → 应看到所有 target 的 up=1五、Grafana 可视化
5.1 首次登录
地址: http://你的IP:3000
默认账号: admin / admin(首次登录强制改密码)5.2 添加 Prometheus 数据源
- 左侧菜单 Connections → Data sources → Add data source
- 选择 Prometheus
- URL 填
http://prometheus:9090(同一 Docker 网络用服务名) - 点击 Save & test,显示绿色对勾即成功
5.3 导入 Node Exporter 看板
Grafana 社区有成熟的现成看板,无需从零画:
- 左侧 Dashboards → New → Import
- 输入官方 Dashboard ID:1860(Node Exporter Full)或 8919(新版)
- 选择刚才添加的 Prometheus 数据源
- 点击 Import
💡 推荐常用 Dashboard ID:
- 1860 — Node Exporter Full(主机监控经典)
- 11074 — Node Exporter 轻量版
- 893 — 主机硬件温度(需额外 exporter)
5.4 核心指标 PromQL 查询
如果你想自己画面板,以下是常用查询:
# CPU 使用率(非 idle)
100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 内存使用率
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
# 磁盘使用率(根分区)
100 * (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})
# 网络流入速率(Mbps)
rate(node_network_receive_bytes_total{device="eth0"}[5m]) * 8 / 1024 / 1024
# 1 分钟负载
node_load1 / count by(instance)(node_cpu_seconds_total{mode="idle"})六、核心 Dashboard 构建
6.1 推荐面板布局
| 行 | 面板 | 指标 |
|---|---|---|
| 概览 | 系统状态总览 | up |
| CPU | 使用率 / 核心分布 | node_cpu_seconds_total |
| 内存 | 已用 / 可用 / Swap | node_memory_* |
| 磁盘 | 分区使用率 / IO 速率 | node_filesystem_* / node_disk_* |
| 网络 | 入站 / 出站流量 | node_network_* |
| 进程 | 运行进程数 / 负载 | node_procs_running / node_load* |
6.2 示例面板 JSON 片段
Grafana 面板是 JSON 结构,以下是一个「CPU 使用率」面板核心字段:
{
"title": "CPU 使用率",
"type": "timeseries",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
"targets": [
{
"expr": "100 - (avg by(instance)(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"legendFormat": "{{instance}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent",
"max": 100
}
}
}6.3 阈值与单位
Grafana 支持在面板中设置阈值变色:
| 指标 | 单位 | 警告阈值 | 严重阈值 |
|---|---|---|---|
| CPU 使用率 | % | 70 | 90 |
| 内存使用率 | % | 80 | 95 |
| 磁盘使用率 | % | 80 | 90 |
| 网络流量 | MB/s | 按带宽定 | — |
七、告警规则配置
7.1 告警规则文件
alerts.yml:
groups:
- name: node-alerts
rules:
- alert: 实例宕机
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 已离线"
description: "实例 {{ $labels.instance }} 持续 1 分钟无法抓取"
- alert: 高CPU使用率
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} CPU 过高"
description: "CPU 使用率持续 5 分钟超过 85%"
- alert: 磁盘即将写满
expr: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘空间不足"
description: "根分区使用率超过 85%"
- alert: 内存不足
expr: 100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) > 90
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 内存紧张"
description: "内存使用率超过 90%"在 prometheus.yml 中引用:
rule_files:
- /etc/prometheus/alerts.yml7.2 Alertmanager 部署
# 在 docker-compose.yml 中追加
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
restart: always
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'prometheus.yml 添加告警路由:
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']7.3 邮件告警通道
alertmanager.yml:
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: 'monitor@gmail.com'
smtp_auth_username: 'monitor@gmail.com'
smtp_auth_password: '应用专用密码'
smtp_require_tls: true
route:
receiver: 'email-alert'
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: 'email-alert'
email_configs:
- to: 'admin@example.com'
subject: '[监控告警] {{ .CommonAnnotations.summary }}'
body: |
告警: {{ .CommonAnnotations.summary }}
详情: {{ .CommonAnnotations.description }}
时间: {{ .StartsAt }}7.4 Telegram 告警通道
Telegram 更适合移动端即时推送。先找 @BotFather 创建 Bot 获取 Token,再找 @userinfobot 获取 Chat ID。
receivers:
- name: 'telegram-alert'
telegram_configs:
- bot_token: '你的BOT_TOKEN'
chat_id: '你的CHAT_ID'
message: |
🔥 *{{ .CommonAnnotations.summary }}*
{{ .CommonAnnotations.description }}
🖥 实例: {{ .CommonLabels.instance }}八、进阶监控
8.1 Nginx 访问统计
启用 Nginx stub_status,再用 nginx-prometheus-exporter 采集:
# nginx.conf
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}docker run -d --name nginx-exporter \
-p 9113:9113 \
nginx/nginx-prometheus-exporter:latest \
-nginx.scrape-uri=http://你的IP/nginx_statusPrometheus 添加 job:
- job_name: 'nginx'
static_configs:
- targets: ['nginx-exporter:9113']看板 ID:11199(Nginx 请求/连接/状态码)。
8.2 SSL 证书过期监控
用 Blackbox Exporter 探测 HTTPS 并解析证书剩余天数:
# blackbox.yml
modules:
https:
prober: http
http:
preferred_ip_protocol: ip4
tls: truePrometheus 添加探测 job:
- job_name: 'ssl-check'
metrics_path: /probe
params:
module: [https]
static_configs:
- targets:
- https://y-m.top
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115证书剩余天数告警:
- alert: SSL证书即将过期
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 14
for: 1h
labels:
severity: warning
annotations:
summary: "SSL 证书将在 14 天内过期"
description: "域名 {{ $labels.instance }} 证书剩余不足 14 天"8.3 网站可用性探测
Blackbox Exporter 还能探测网站是否可访问、响应时间:
- alert: 网站不可达
expr: probe_success{job="blackbox-http"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 访问失败"
description: "HTTP 探测连续失败超过 2 分钟" - alert: 响应过慢
expr: probe_duration_seconds{job="blackbox-http"} > 3
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 响应缓慢"
description: "HTTP 响应时间持续超过 3 秒"九、常见问题
Q1:Prometheus 内存占用过高怎么办?
- 调低采集频率:
scrape_interval从 15s 调到 30s 或 60s - 减少目标数量:只为关键服务建 job
- 限制数据保留:
--storage.tsdb.retention.time=15d - 设置数据体积上限:
--storage.tsdb.retention.size=2GB - 给容器限制内存:
deploy.resources.limits.memory: 1g
Q2:数据存哪里?会不会写满磁盘?
默认存在 Docker 卷 prometheus_data(映射在 /var/lib/docker/volumes/)。务必设置 retention.size 上限,并监控宿主机磁盘。建议单独挂一块盘或定期备份:
# 手动备份(停止容器后)
docker run --rm -v prometheus_data:/data -v $(pwd):/backup alpine \
tar czf /backup/prometheus-backup.tar.gz -C /data .Q3:多台 VPS 如何集中监控?
三种方案:
| 方案 | 做法 | 适合 |
|---|---|---|
| 中心拉取 | 监控服务器直接拉各 VPS 的 Exporter(需网络可达) | 同内网/有隧道 |
| 反向代理 | 各 VPS 用 Nginx 暴露 Exporter,中心统一拉 | 有公网 IP |
| Pushgateway | 边缘节点定时推送(适合 NAT/动态 IP) | 无公网 IP |
最常用是中心拉取:监控服务器 Prometheus 配置多个 static_configs,targets 填各 VPS 内网 IP + 端口(通过 WireGuard 组网可互通)。
Q4:Grafana 进不去 / 密码忘了?
# 重置 admin 密码
docker exec -it grafana grafana-cli admin reset-admin-password newpasswordQ5:告警不触发?如何排查?
- 访问
http://IP:9090/alerts看规则是否PENDING/FIRING - 检查
alertmanager.yml语法:amtool check-config alertmanager.yml - 确认 Prometheus
alerting段指向正确的 Alertmanager 地址 - 用
amtool alert query查看当前告警 - Telegram 确认 Bot Token 和 Chat ID 正确(Chat ID 是负数需带负号)
Q6:能监控 Docker 容器吗?
能。部署 cAdvisor 采集容器指标:
docker run -d --name cadvisor \
-p 8080:8080 \
-v /:/rootfs:ro -v /var/run:/var/run:ro \
-v /sys:/sys:ro -v /var/lib/docker/:/var/lib/docker:ro \
gcr.io/cadvisor/cadvisor:latestPrometheus 添加 job 指向 cadvisor:8080,看板 ID:893(Docker 监控)。
Q7:生产环境如何保护监控面板?
- Grafana/Prometheus 不要直接暴露公网,套一层 Nginx + Basic Auth 或反向代理
- Grafana 配置
GF_AUTH_ANONYMOUS_ENABLED=false禁用匿名访问 - 修改默认端口(9090/3000 众所周知易被扫描)
- 启用 HTTPS(参考站内 VPS 安全加固实战指南)
- 定期更新镜像版本
Q8:和 VPS 供应商自带的监控(如阿里云云监控)有什么区别?
| 维度 | 厂商监控 | Prometheus+Grafana |
|---|---|---|
| 数据归属 | 厂商掌握 | 自己掌握 |
| 自定义 | 受限 | 完全自由 |
| 跨厂商 | 各看各的 | 统一看板 |
| 成本 | 高级功能收费 | 免费 |
| 告警渠道 | 厂商 App | 邮件/Telegram/钉钉/Slack |
自建监控的最大价值是跨厂商统一和数据自主。
总结
Prometheus + Grafana 是 VPS 监控的黄金组合。回顾核心要点:
- 架构清晰:Prometheus 拉取指标存储,Grafana 可视化,Alertmanager 管告警
- 部署简单:Docker Compose 一份配置拉起整套栈
- 看板现成:导入社区 Dashboard ID(1860/11199)即可用
- 告警灵活:邮件 + Telegram 双通道,PromQL 精准定义阈值
- 可扩展:Nginx / SSL / 网站可用性 / 多节点一站式覆盖
搭建顺序建议:
1. Node Exporter(采集主机指标)
2. Prometheus(存储 + 查询)
3. Grafana(可视化看板)
4. 导入 Dashboard 1860
5. Alertmanager(邮件/Telegram 告警)
6. 进阶:Blackbox + Nginx Exporter延伸阅读:
- VPS 安全加固实战指南 — 监控面板同样需要安全保护
- WireGuard 自建 VPN 完整教程 — 多 VPS 监控的组网方案
- VPS 供应商横向对比 — 选一台稳定的 VPS 跑监控
- Docker 多阶段构建优化 — 理解容器化部署
- VitePress SEO 优化指南 — 本站同款技术栈
🚀 监控不是锦上添花,而是系统稳定运行的底线。花一晚上搭好这套监控,未来无数个安稳的夜晚都是它换来的。
相关命令速查:
# 启动整套监控
docker compose up -d
# 查看状态
docker compose ps
# 重启单个服务
docker compose restart prometheus
# 热加载 Prometheus 配置(无需重启)
curl -X POST http://localhost:9090/-/reload
# 查看告警
docker logs alertmanager