Prometheus 监控系统搭建:从指标采集到告警通知

Prometheus 是云原生计算基金会(CNCF)的毕业项目,已经成为监控领域的标准工具。它采用“拉取”模式:监控目标暴露 /metrics 端口,Prometheus 定期去抓取。这种设计让监控系统不依赖目标端主动上报,天然适合动态扩容的环境。

一、架构概览

Exporter → Prometheus Server → AlertManager → 通知渠道
                                  ↓
                              Grafana (可视化)

Exporter 负责把系统或应用的指标翻译成 Prometheus 格式,AlertManager 负责把告警去重、分组后发到邮件/IM,Grafana 负责可视化。这四层分工清晰,也方便各管一段:数据采集和存储归 Prometheus,告警归 AlertManager,展示归 Grafana,任何一层都可以独立升级或替换,不需要推倒重来。

二、指标类型:先搞懂四种基础类型

类型 说明 典型例子
Counter 只增不减的计数器 请求总数、CPU 时间
Gauge 可增可减的当前值 内存使用量、在线连接数
Histogram 观测值分布(分位数) 请求延迟 P50/P95/P99
Summary 客户端计算的摘要 同 Histogram,客户端算好分位

绝大多数系统监控只需要 Counter 和 Gauge,理解这两类就够搭起一套能用的监控。另外建议了解一下命名约定:Prometheus 约定 Counter 以 _total 结尾(如 node_cpu_seconds_total),单位信息放进指标名(如 _bytes_seconds),这样查询和团队协作时不会产生歧义。

三、安装配置

# docker-compose.yml
version: '3'
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"

scrape_interval 的默认值是 15s,抓取频率越高,指标越平滑,但存储和开销也越大;对主机监控 15s 或 30s 通常足够,没必要一味追求高频。规则评估间隔(evaluation_interval)建议与抓取间隔一致,避免告警计算基于过期数据。

Prometheus 的抓取目标、告警规则文件都写在 prometheus.yml 里:

global:
  scrape_interval: 15s
rule_files:
  - /etc/prometheus/rules/*.yml
scrape_configs:
  - job_name: node
    static_configs:
      - targets: ["node-exporter:9100"]

四、PromQL 常用查询

# CPU 使用率
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 内存使用率
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)

# 磁盘使用率
100 * (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})

这三条分别对应服务器最核心的三项:CPU、内存、磁盘,加进 Grafana 就能组成一个基础主机看板。

五、告警规则

groups:
  - name: server
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU usage above 80%"

for: 5m 表示条件持续 5 分钟才触发,避免瞬时抖动引发误报。告警规则建议按 severity 分级:warning(可观察)、critical(需要立刻处理),并接上 AlertManager 通知:

route:
  receiver: "webhook"
  routes:
    - match:
        severity: critical
      receiver: "pager"
receivers:
  - name: "webhook"
    webhook_configs:
      - url: "https://hooks.slack.com/services/xxx"

六、Grafana 可视化

Grafana 首次登录默认账号 admin/admin。推荐两步:先导入官方的 Node Exporter Full 看板(ID 1860),再用上面的 PromQL 加一个自定义看板,把首页 PV、接口延迟、错误率这类业务指标也接进来。看板数量不在多,能让人 30 秒内判断“系统现在健不健康”就够了。

一个真实场景

某站点在促销前一天接入了这套监控。促销当天凌晨,CPU 告警(持续 5 分钟超过 80%)被触发,值班同学顺着 Grafana 看到商品页接口的延迟指标飙高,定位到是数据库慢查询,赶在流量上来之前完成了索引优化。整场促销零事故。如果当时没有监控,大概率是用户先发现页面打不开,再层层排查。

监控上线检查清单

  • 每个服务器都部署了 node-exporter
  • 关键应用暴露了自定义指标
  • 告警至少接了一个通知渠道,且有人真的能看到
  • 告警阈值避免误报(加 for 持续时长)
  • Grafana 看板能让新人 30 秒看懂

常见问题

指标数据越来越大,磁盘不够怎么办? Prometheus 是时序数据库,数据会持续增长。常规做法:一是调整保留周期 --storage.tsdb.retention.time(比如保留 15 天,历史数据交给对象存储归档);二是用 --storage.tsdb.retention.size 限制存储上限;三是给业务类指标单独一个实例,避免和主机指标混在一起。

告警一晚上响个不停,怎么治理? 这是“告警风暴”。常见原因:阈值设得太敏感、没有加 for 持续时长、告警没有去重分组。建议按下面顺序治理:先给每条告警加 for(至少 1-5 分钟),再用 AlertManager 的 group_by 把同类告警合并成一条,最后对已知的维护窗口做静默(silence),并定期清理没人处理的告警规则。

只监控 CPU 内存够吗? 不够,那只覆盖了“服务器层面”。业务层面同样重要:接口延迟、错误率、队列积压、数据库慢查询,这些才是用户能感知的。node-exporter 只是第一步,下一步让应用通过 Prometheus 客户端库暴露自定义指标,或使用现成的集成(如 nginx exporter、mysql exporter),形成“主机 + 中间件 + 业务”三层覆盖。

Grafana 打开很慢怎么办? 先检查看板是不是一次加载了太多查询和大时间范围,其次确认 Grafana 与 Prometheus 之间的网络延迟,必要时开启 Grafana 的缓存。看板数量建议控制在 10 个以内,把常用的钉在侧边栏,减少每次加载的计算量。

参考:Prometheus 官方文档 https://prometheus.io/docs/introduction/overview/
参考:Grafana 官方文档 https://grafana.com/docs/
参考:AlertManager 配置 https://prometheus.io/docs/alerting/latest/alertmanager/