前言

“没有监控的运维等于裸奔”。Prometheus + Grafana 是云原生时代监控的事实标准,这篇从架构到实操搭一套最小可用体系。

一、架构与核心概念

┌─ 被监控目标 ────────────┐
│ node_exporter (主机)     │     ┌─────────────┐    ┌───────────┐
│ mysqld_exporter (DB)    │◄────┤ Prometheus  │───►│ Alertmanager ─► 钉钉/邮件
│ 应用 /metrics 端点        │ 拉取 │ (TSDB+采集) │    └───────────┘
└─────────────────────────┘     └──────┬──────┘
                                       │ PromQL 查询
                                  ┌────▼─────┐
                                  │ Grafana  │ ── 可视化大盘
                                  └──────────┘

关键设计:Pull 模型——Prometheus 主动周期性抓取目标的 /metrics 端点,数据存本地时序库(TSDB)。

指标四类型:

类型 语义 示例
Counter 只增不减的计数器 http_requests_total
Gauge 可增可减的瞬时值 memory_usage_bytes
Histogram 分桶统计分布 请求耗时分布(P99 就靠它)
Summary 分位数 直接给 P50/P99

指标命名惯例:<namespace>_<name>_<unit>,如 http_requests_total。

二、快速搭建(Docker Compose)

# docker-compose.yml
services:
  prometheus:
    image: prom/prometheus:v2.53.0
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./rules/:/etc/prometheus/rules/
    ports: ["9090:9090"]

  node-exporter:
    image: prom/node-exporter:v1.8.1
    pid: "host"
    command:
      - --path.rootfs=/host
    volumes:
      - /:/host:ro,readonly

  alertmanager:
    image: prom/alertmanager:v0.27.0
    ports: ["9093:9093"]

  grafana:
    image: grafana/grafana:11.1.0
    ports: ["3000:3000"]
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  grafana-data:

prometheus.yml:

global:
  scrape_interval: 15s

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

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

scrape_configs:
  - job_name: "prometheus"
    static_configs: [{targets: ["localhost:9090"]}]

  - job_name: "node"
    static_configs: [{targets: ["node-exporter:9100"]}]
docker compose up -d
# 验证: 浏览器开 http://服务器IP:9090/targets —— 两个 job 都是 UP

三、PromQL 入门(核心中的核心)

# 在 Prometheus Web UI (9090) 的 Graph 里练习
# 1. 即时查询
node_cpu_seconds_total                     # 原始序列(按 cpu/mode 多条)

# 2. 过滤标签 {}
node_cpu_seconds_total{mode="idle"}

# 3. rate(): Counter 必须配 rate 才有意义(每秒增长率)
rate(node_cpu_seconds_total{mode="idle"}[5m])

# 4. 聚合
avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))

# 5. 运算: CPU 使用率 = 1 - 空闲率
100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100

# 6. 常用函数
node_memory_MemAvailable_bytes / 1024 / 1024 / 1024       # 可用内存(GB)
100 - node_filesystem_avail_bytes{mountpoint="/"} 
  / node_filesystem_size_bytes{mountpoint="/"} * 100      # 根盘使用率%

# 7. histogram 的 P99(假设暴露了 http_request_duration_seconds)
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# 8. 一分钟增量
increase(node_network_receive_bytes_total[1m])

四、告警规则

rules/host.yml:

groups:
- name: host-alerts
  rules:
  - alert: HostDown
    expr: up{job="node"} == 0
    for: 1m
    labels: {severity: critical}
    annotations:
      summary: "主机 {{ $labels.instance }} 宕机"
      description: "已失联超过 1 分钟"

  - alert: HighCPU
    expr: 100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 85
    for: 5m                                  # 持续 5 分钟才报(防毛刺)
    labels: {severity: warning}
    annotations:
      summary: "{{ $labels.instance }} CPU 过高"
      description: "当前使用率 {{ $value | printf \"%.1f\" }}%"

  - alert: DiskWillFull
    expr: predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[1h], 4*3600) < 0
    for: 10m
    annotations:
      summary: "{{ $labels.instance }} 根盘预计 4 小时内写满"

for 的意义:条件先持续满足一段时间才触发,大幅减少误报。

Alertmanager 路由(分组/抑制/静默):

route:
  group_by: ["alertname", "instance"]
  group_wait: 30s
  receiver: dingtalk
receivers:
- name: dingtalk
  webhook_configs:
  - url: "http://dingtalk-webhook/..."       # 或用 prometheus-webhook-dingtalk

五、Grafana 出图

1. 打开 http://IP:3000 (admin/admin 首次改密)
2. Connections → Data source → Prometheus → URL: http://prometheus:9090
3. Dashboards → Import → 输入 1860(Node Exporter Full 官方大盘)
4. 秒得一张专业主机监控大屏

自建 Panel 的查询示例——“各实例内存使用率”:

(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

六、应用侧暴露指标

Go 应用一行接入:

import "github.com/prometheus/client_golang/prometheus/promhttp"

http.Handle("/metrics", promhttp.Handler())

四个黄金指标(Google SRE):延迟、流量、错误率、饱和度——给自己的服务都暴露这四类,监控就及格了。

七、常见坑

现象 原因
targets 显示 DOWN 网络不通/端口错;点开 error 看具体原因
图表没数据 Counter 没 rate;时间范围/步长不合理
告警风暴 没配 for、没分组
长期存储 本地 TSDB 有限;上 VictoriaMetrics/Thanos(进阶)
容器里看不到主机指标 node-exporter 要挂载宿主 / 且 pid: host

小结

组件 职责
exporter 把系统/应用状态翻译成 /metrics
Prometheus 拉取 + 存储 + 规则计算
PromQL rate 配 Counter、by 聚合
Alertmanager 分组、抑制、路由通知
Grafana 大盘可视化(1860 直接抄)

本文是「云原生」系列第 7 篇。