Prometheus + Grafana 云原生监控告警实战:从指标采集到可视化大盘与告警规则完整指南

监控是系统稳定运行的"眼睛"。当服务从单机走向容器化、微服务化之后,传统靠人工 top 看一眼的方式彻底失效:实例动态扩缩、IP 随时漂移、调用链跨几十个服务。本文以 Prometheus + Grafana + Alertmanager 这套云原生事实标准监控栈为主线,带你从零搭建一套"采集 → 存储 → 查询 → 可视化 → 告警"的完整体系,并给出可直接抄进生产环境的配置。

一、为什么是 Prometheus

在微服务与 Kubernetes 场景下,监控对象有两个特征:数量多、生命周期短。这带来三个核心诉求:

  • 自动发现:新实例上线要能被自动纳入监控,而不是改配置文件。
  • 高维数据模型:能用 服务名 / 实例 / 接口 / 状态码 等多维度自由切片。
  • 拉取模型 + 时序存储:统一从目标抓取指标,天然适合做趋势与告警。

Zabbix 这类基于 Agent 主动上报 + 关系型存储的方案,在标签维度爆炸和动态拓扑面前力不从心;而 Prometheus 的 Pull + TSDB + Label 设计正好命中痛点,因此成为 CNCF 毕业项目中采用率最高的监控系统。

二、Prometheus 核心架构与数据模型

Prometheus 采用拉取(Pull)模型:服务端周期性地访问各目标暴露的 /metrics HTTP 端点,抓取文本格式的指标。一条完整的指标由三部分构成:

  • Metric Name(指标名):如 http_requests_total
  • Label(标签键值对):如 {method="POST", status="200", instance="10.0.0.3:8080"},维度就来自这里。
  • Sample(样本):由时间戳 + 浮点数值组成,即 (timestamp, value)

关键纪律:标签的**基数(cardinality)**要可控。千万不要把 `user_id`、`order_id` 这种取值无限多的字段做成标签,否则 TSDB 内存和磁盘会被瞬间打爆。

一次抓取的数据流如下:

Exporter/App (/metrics)
        │  Pull (HTTP)
        ▼
   Prometheus Server ──▶ TSDB 本地时序库
        │                      │
        │ PromQL 查询          │ 远程写(可选)
        ▼                      ▼
     Grafana 可视化      VictoriaMetrics / Thanos
        │
        ▼
   Alertmanager ──▶ 钉钉 / 邮件 / Webhook

三、快速部署:docker-compose 一键拉起

先写 prometheus.yml,定义抓取目标与频率:

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: prod-cn

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

  - job_name: node
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: app
    # 配合 K8s 时改用 kubernetes_sd_configs 做服务发现
    static_configs:
      - targets: ['app:8080']

再用 docker-compose.yml 编排 Prometheus 与 Node Exporter:

version: '3'
services:
  prometheus:
    image: prom/prometheus:v2.53.0
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prom-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=15d'

  node-exporter:
    image: prom/node-exporter:v1.8.0
    container_name: node-exporter
    ports:
      - "9100:9100"

volumes:
  prom-data:

启动后访问 http://localhost:9090,在 Graph 页输入 up 就能看到所有目标的存活状态——up == 1 表示抓取成功,up == 0 意味着目标下线或端口不通。

四、指标采集:Exporter 与自定义埋点

大多数中间件官方或社区都提供了 Exporter,直接挂上即可:

  • node-exporter:主机 CPU、内存、磁盘、网络。
  • mysqld-exporter / redis-exporter:数据库内部指标。
  • cadvisor / kube-state-metrics:容器与 K8s 对象状态。

业务应用自身也要埋点。以 Go 为例,暴露一个 HTTP 请求计数器:

var httpReqTotal = prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_requests_total",
        Help: "HTTP 请求总量",
    },
    []string{"method", "status"},
)

func init() {
    prometheus.MustRegister(httpReqTotal)
}

func handler(w http.ResponseWriter, r *http.Request) {
    httpReqTotal.WithLabelValues(r.Method, "200").Inc()
    w.Write([]byte("ok"))
}

func main() {
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}

Python(Prometheus Client)同理:

from prometheus_client import Counter, start_http_server
import time

REQ = Counter("http_requests_total", "请求总数", ["method", "status"])

start_http_server(8080)
while True:
    REQ.labels(method="GET", status="200").inc()
    time.sleep(1)

五、PromQL 查询语言实战

PromQL 是 Prometheus 的灵魂。几个最常用、也最容易被用错的函数:

函数作用典型用法
`rate()`区间内的平均每秒增长率(自动去毛刺)`rate(http_requests_total[5m])`
`irate()`只取区间首尾两个点,更灵敏`irate(http_requests_total[5m])`
`histogram_quantile()`计算分位数延迟`histogram_quantile(0.95, ...)`
`sum by()`按标签聚合`sum by (instance) (rate(...))`

几个高频实战查询:

# 1. QPS(按接口聚合)
sum by (method) (rate(http_requests_total[5m]))

# 2. 错误率(5xx 占比)
sum(rate(http_requests_total{status=~"5.."}[5m]))
  /
sum(rate(http_requests_total[5m]))

# 3. P95 接口延迟(假设用了 histogram 指标 http_request_duration_seconds)
histogram_quantile(0.95,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

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

经验法则:看趋势、画图的报表用 `rate`;做实时灵敏度要求高的告警阈值可酌情用 `irate`,但注意 `irate` 在区间内有数据缺失时会显得很跳。

六、Grafana 可视化大盘

Grafana 负责把 PromQL 查询结果变成好看的面板。接入步骤:

  1. 添加数据源:Configuration → Data Sources → Prometheus,URL 填 http://prometheus:9090
  2. 新建 Dashboard,每个 Panel 的查询框直接写 PromQL。
  3. 推荐直接导入社区成熟模板:Node Exporter 官方模板 1860,K8s 集群模板 6417,改改数据源即可用。

一个典型的"服务健康度"大盘应包含:QPS、P95/P99 延迟、错误率、实例 CPU/内存、GC 停顿。把核心 SLO(如错误率 < 0>

七、告警体系:Alertmanager 实战

可视化让人"看见"问题,告警让人"被通知"问题。告警分两层:Prometheus 负责判定规则,Alertmanager 负责路由与分发

prometheus.yml 中挂载规则文件:

rule_files:
  - /etc/prometheus/rules/*.yml

编写 rules/alert.yml

groups:
  - name: service-alerts
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
          /
          sum(rate(http_requests_total[5m])) > 0.05
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "服务错误率超过 5%(持续 10 分钟)"
          description: "当前错误率 {{ $value | humanizePercentage }}"

      - alert: InstanceDown
        expr: up == 0
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "实例 {{ $labels.instance }} 已下线"

for: 10m 表示条件持续 10 分钟才真正触发,避免瞬时抖动产生误报——这是生产环境减少"告警疲劳"的关键。

Alertmanager 配置化路由与通知渠道:

route:
  receiver: dingtalk
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - match:
        severity: critical
      receiver: dingtalk

receivers:
  - name: dingtalk
    webhook_configs:
      - url: https://oapi.dingtalk.com/robot/send?access_token=xxxx

进阶:用 `inhibit_rules` 做告警抑制——比如"实例宕机"的告警触发后,自动抑制该实例上的"错误率过高"告警,避免一条根因引发一堆连锁噪音。

八、生产级最佳实践

  • 长期存储:单机 Prometheus 本地 TSDB 建议保留 15–30 天。需要长期留存或跨集群聚合时,用 ThanosVictoriaMetrics 做远程写与全局查询。
  • 标签基数治理:定期用 prometheus_tsdb_head_series 监控序列总量,对高基数标签做降维(如把 path 改为有限的 route 模板)。
  • 高可用:Prometheus 本身无内置 HA,采用"双副本采集 + 上层 Thanos/VictoriaMetrics 去重"是主流方案。
  • 告警分级warning 走 IM 通知,critical 同时打电话/短信,并接入值班轮转(如 Grafana OnCall)。
  • 配置即代码prometheus.ymlrulesdashboards 全部纳入 Git,配合 CI 做规则语法校验,变更可回溯。

九、总结

本文梳理了一条从 0 到生产的监控告警主线:用 Exporter / 自定义埋点采集指标,Prometheus 以 Pull + TSDB 存储,靠 PromQL 灵活查询,Grafana 做可视化大盘,Alertmanager 完成分级告警与路由。真正落地时,记住三句话——标签基数要克制、for 阈值要留缓冲、配置全部进 Git。把这套体系搭稳,系统的每一次异常都会第一时间"自己喊出来"。

下一篇可延展方向:Thanos 全局视图搭建、eBPF 无侵入采集、或 OpenTelemetry 统一 Trace/Metric/Log。欢迎在评论区点单。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部