Prometheus 监控系统

从数据模型、拉取架构、PromQL、规则系统到 Pushgateway / Remote Write,系统理解 Prometheus

Posted by Ekko on May 21, 2026

这篇笔记以 Prometheus 官方文档为主线整理,目标不是只会“把 /metrics 抓起来”,而是把 Prometheus 的数据模型、抓取架构、规则系统、查询语义和常见误区连成一个完整脑图。

Prometheus Data Model

Prometheus Jobs and Instances

PromQL Basics

Prometheus Configuration

Recording Rules

Alerting Rules

When to use the Pushgateway

[TOC]


1. Prometheus 是什么

最简洁但不失真的定义是:

  • Prometheus 是一个面向数值型时序数据的监控与告警系统

它至少同时承担了 4 个角色:

  • 指标采集器
  • 本地时序数据库
  • 查询引擎
  • 规则评估器

很多人第一次接触时,只记住了:

  • 它会抓 /metrics

但这只是入口。真正要理解的是:

  • 它不是单纯 exporter 集合
  • 也不是单纯图表后端
  • 更不是“Grafana 的数据源而已”

它本身就是:

  • 监控系统的核心计算与存储中枢

2. Prometheus 不是什么

理解边界比理解功能更重要。

2.1 它不是日志系统

Prometheus 处理的是:

  • 数值型、可聚合、可采样的时序数据

它不适合存:

  • 文本日志
  • 请求明细
  • 原始事件详情

日志要交给:

  • ELK / OpenSearch
  • Loki
  • 其他日志系统

2.2 它不是 Trace 系统

Prometheus 能告诉你:

  • 整体错误率升没升
  • p99 抖没抖
  • 哪个实例的请求量异常

但它不能像 Trace 那样回答:

  • 某个请求具体经过了哪些服务
  • 哪一段 span 慢了

2.3 它也不是可视化平台

Prometheus 自带表达式浏览器和简单图表,但它的定位不是高级可视化。

真正复杂的面板、变量、多数据源联动、丰富图形展示,通常交给:

  • Grafana

所以后面你会发现:

  • Prometheus 负责“采、存、算、告”
  • Grafana 更偏“查、看、呈现、协作”

3. 为什么 Prometheus 会成为事实标准

它流行不是因为“最万能”,而是因为它在云原生场景里做了几件特别对的事。

3.1 数据模型简单但足够强

Prometheus 官方文档强调:

  • 它所有数据本质上都是 time series
  • 一条时序由指标名和一组标签唯一标识

这种模型的好处是:

  • 足够统一
  • 足够适合聚合
  • 足够适合服务化系统

3.2 默认拉取模型很适合动态环境

Prometheus 的核心是:

  • server 主动去 scrape targets

这种 pull 模型对容器化、服务发现、弹性扩缩容很友好,因为中心节点始终掌握:

  • 当前有哪些目标
  • 哪些目标正在健康暴露指标

3.3 PromQL 很强

Prometheus 能成为核心,不只是因为能采集,还因为:

  • 它能把查询、聚合、规则、告警全部统一在 PromQL 上

也就是说:

  • 你看图用 PromQL
  • 录规则用 PromQL
  • 报警也用 PromQL

这让整个监控栈的认知成本下降很多。

3.4 单机模型简单可靠

Prometheus 核心 server 是单二进制、单节点本地 TSDB。

这不是缺点,而是它的重要设计哲学:

  • 先把单点系统做得简单、可靠、可运维

后续再通过:

  • federation
  • remote write
  • 外部长存储

去扩展,而不是一开始就做成极重的分布式数据库。


4. Prometheus 的核心数据模型

这一节是最底层认知。

4.1 一切都是 time series

Prometheus 官方原话可以概括成:

  • 它存储的所有数据,都是带时间戳的 time series

一条时间序列由下面两部分唯一确定:

  • 指标名
  • 标签集合

例如:

1
http_requests_total{job="api", instance="10.0.0.1:8080", method="GET", code="200"}

一旦标签变了,就已经不是同一条序列了。

4.2 标签不是描述信息,而是维度

这个观念非常重要。

标签的意义是:

  • 用一组有限维度去切分同一个指标

例如:

  • method
  • code
  • job
  • instance

都非常适合作为维度,因为它们通常是:

  • 有限集合
  • 需要聚合分析

4.3 高基数是 Prometheus 最常见的敌人

Prometheus 官方文档虽然讲的是数据模型,但它背后最关键的工程含义是:

  • label 值变化会创建新 time series

因此如果你把这些东西放进标签:

  • userId
  • traceId
  • orderId
  • 原始 URL

就会造成:

  • 序列数爆炸
  • 内存压力上升
  • 查询性能下降
  • 写入成本暴涨

所以 Prometheus 学习到后面,你会发现很多问题其实都不是 PromQL 不会写,而是:

  • 序列设计一开始就错了

4.4 指标名和标签名也有规范

Prometheus 官方文档建议:

  • 指标名推荐匹配 [a-zA-Z_:][a-zA-Z0-9_:]*
  • 标签名推荐匹配 [a-zA-Z_][a-zA-Z0-9_]*

此外一个容易被忽视的点是:

  • 冒号 : 保留给 recording rules 生成的指标名

所以业务直接埋点时,不要乱用冒号。


5. Jobs、Instances、Target 到底是什么

这几个词在 Prometheus 里有明确语义。

5.1 Instance

Prometheus 官方定义里:

  • 一个可被 scrape 的 endpoint 叫做 instance

通常它对应:

  • 一个进程实例
  • 一个 exporter 实例
  • 一个暴露 /metrics 的服务地址

5.2 Job

  • 一组有相同职责的 instances 组成一个 job

例如:

  • api-server
  • order-service
  • node-exporter

5.3 自动附加的标签

Prometheus 在抓取时会自动附加至少两个重要标签:

  • job
  • instance

这两个标签对后续查询非常关键。

5.4 自动生成的 scrape 元指标

Prometheus 官方文档还提到,每次抓取会自动产生一些非常重要的时间序列:

  • up
  • scrape_duration_seconds
  • scrape_samples_scraped
  • scrape_samples_post_metric_relabeling
  • scrape_series_added

其中最常用的是:

  • up

它的意义非常朴素但非常关键:

  • 1 表示这次 scrape 成功
  • 0 表示 scrape 失败

这就是为什么 Prometheus 的 pull 模型天然就能附带:

  • “目标活着没”

这种基础健康语义。


6. Prometheus 的工作流程

可以把它理解成下面这条链路:

1
2
3
4
5
6
7
服务 / exporter 暴露 /metrics
    -> Prometheus 通过 service discovery 找到 targets
    -> 定期 scrape
    -> 写入本地 TSDB
    -> PromQL 查询
    -> recording rules / alerting rules 评估
    -> Alertmanager 路由通知

6.1 暴露指标

被监控对象要么自己暴露:

  • /metrics

要么通过 exporter 暴露。

例如:

  • node_exporter
  • mysqld_exporter
  • blackbox_exporter

6.2 发现目标

Prometheus 会根据配置和服务发现机制,决定:

  • 当前有哪些 target

这可以来自:

  • static configs
  • Kubernetes
  • Consul
  • file_sd
  • 其他 SD 机制

6.3 定期抓取

Prometheus 按固定 interval 发 HTTP 请求去抓指标。

注意这不是被动接收,而是:

  • 主动拉取

6.4 写入本地 TSDB

抓到的数据被解析成样本并写入本地时序数据库。

6.5 规则评估

Prometheus 会按 evaluation_interval 周期执行 recording rules 和 alerting rules。

6.6 对外查询和报警

  • Grafana 通过 PromQL 查询 Prometheus
  • Alertmanager 接收 Prometheus 发送的告警事件并负责路由

7. 拉取模型为什么重要

Prometheus 的很多设计都围绕 pull model。

7.1 Pull 模型的优点

  • 中心端统一掌握抓取节奏
  • 目标是否可达天然可见
  • 对短生命周期实例更容易做统一发现
  • 更容易结合服务发现和 relabeling

7.2 Pull 模型不是绝对真理

它也有边界:

  • 目标必须能被 Prometheus 访问
  • NAT / 防火墙 / 跨网段场景可能不方便
  • 纯批处理短任务天生不适合长期暴露 endpoint

7.3 为什么官方不鼓励到处用 Pushgateway

Prometheus 官方文档对 Pushgateway 的态度其实很明确:

  • 只推荐在有限场景使用

原因包括:

  • Pushgateway 会变成额外单点
  • 会丢掉 up 这种自动健康语义
  • 它不会自动忘记旧 series,容易残留脏数据

官方认为它最合理的使用场景通常是:

  • service-level batch job

也就是:

  • 面向整个服务的短时批任务结果上报

而不是:

  • 普通在线服务也统统改成 push

7.4 替代思路

官方文档还提到:

  • 如果是机器级批任务,更适合 node_exporter 的 textfile collector
  • 如果是网络边界导致拉不到,优先考虑让 Prometheus 部署到目标网络内

这说明一个原则:

  • 遇到 pull 不方便,不要第一反应就是全面改 push

8. TSDB 怎么理解

先放一张“首屏速记图”,把这一章最容易混淆的三件事先压缩到一起:

  1. Prometheus 默认把数据存在本地 TSDB
  2. HA 双 Prometheus 是高可用,不是共享同一份底层存储
  3. 规模化通常靠 Thanos / Mimir 这类统一查询与长存储体系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
【形态 1:单机】
Grafana --> Prometheus --> Local TSDB --> Targets

【形态 2:HA 双 Prometheus】
                 +--> Prom A --> Local TSDB --+
Grafana ---------+                            +--> Same Targets
                 +--> Prom B --> Local TSDB --+

【形态 3:规模化】
Grafana --> Thanos / Mimir --> Prom A / Prom B / Prom C --> Local TSDB
                                |        |        |
                                +--------+--------+--> Targets
                                |
                                +--------------------> Object Storage / Remote Store

如果只记一句话,可以记成:

  • Prometheus 负责采集和本地热数据,Thanos/Mimir 负责统一查询、聚合和长存储,Grafana 负责展示

8.1 Prometheus 自带本地 TSDB

Prometheus 不是“只采不存”,它有自己的本地时序数据库。

这个 TSDB 的特点是:

  • 针对最近时间窗口的时序数据做了高效优化
  • 适合高频写入、按时间范围查询

更直白一点说:

  • Prometheus 默认就是把采集到的时序数据存到本机磁盘

不是默认写进:

  • MySQL
  • Oracle
  • Elasticsearch

它的默认存储形态就是:

  • Prometheus 自己的本地 TSDB 文件

8.2 数据到底怎么存

Prometheus 的一条时序数据,本质上可以理解成:

  • 指标名
  • 一组 labels
  • 按时间追加的 sample 值

例如:

1
http_requests_total{job="api", instance="10.0.0.8:8080", method="GET"}

它不是像关系型数据库那样先设计表结构,再插入行。

更准确地说,Prometheus 内部更像是在维护大量:

  • series = metric name + label set

然后每条 series 后面不断追加:

  • (timestamp, value) 样本点

所以它存的是:

  • 时序序列

而不是你熟悉的那种:

  • 关系表
  • 文档记录
  • 向量 embedding

8.3 写入路径怎么理解

Prometheus 的本地存储,大致可以按下面这个流程理解:

  1. scrape 到指标
  2. 先写入内存中的 head
  3. 同时顺序追加到 WAL
  4. 达到一定条件后切成 block 落盘
  5. 后续再做 compaction

这里面最关键的 3 个词是:

  • Head
  • WAL
  • Block

Head 可以理解成:

  • 当前正在被写入的热点数据区

新采集到的样本会先进入这里,因此最近时间窗口的数据查询通常会比较快。

WAL

WAL 是:

  • Write-Ahead Log,预写日志

它的作用不是给你直接查,而是:

  • 在 Prometheus 异常退出后,尽量通过日志重放恢复最近的数据

这也是为什么 Prometheus 不是“只在内存里攒着”,而是会先顺序写一份日志到磁盘。

Block

当 head 中的数据满足切块条件后,会被刷成持久化 block。

你可以把 block 理解成:

  • 一段时间范围内、已经整理好的只读数据块

后续查询历史数据时,Prometheus 主要就是在这些 block 上做读取。

8.4 它是真的落硬盘文件吗

是的,默认就是落到本地磁盘目录。

最常见的是启动参数里指定:

1
--storage.tsdb.path=/prometheus

或者用默认数据目录。

这个目录里通常会看到类似结构:

1
2
3
4
5
6
data/
  wal/
  chunks_head/
  01ABC...
  01DEF...
  queries.active

可以这样理解这些内容:

  • wal/:预写日志
  • chunks_head/:head 阶段相关的 chunk 文件
  • 01ABC...01DEF...:已经持久化的 block 目录

每个 block 目录里一般会有这几类文件:

  • chunks/:真正的样本 chunk 数据
  • index:series 和 labels 的索引
  • meta.json:这个 block 的元信息

这说明 Prometheus 的本地存储不是:

  • 一个单独的大数据库文件

而是:

  • 一组按 block 组织的目录和文件

8.5 为什么 Prometheus 适合时序场景

因为它的存储布局就是围绕时序查询优化的。

核心优化点通常可以这样理解:

  • 写入基本是追加写
  • 历史数据按时间块组织
  • labels 有专门索引
  • 样本会以 chunk 形式压缩存储

这和 OLTP 数据库关注的重点不一样。

关系型数据库更偏:

  • 事务一致性
  • 复杂 join
  • 行列级通用查询

Prometheus 更偏:

  • 高频采样写入
  • 时间范围聚合
  • label 维度过滤

8.6 保留期、压缩和删除怎么理解

Prometheus 不会无限保存本地数据。

通常会受到这些策略约束:

  • retention time
  • retention size

也就是说,本地 TSDB 更适合:

  • 近期热数据

而不是:

  • 无限期归档仓库

随着时间推进,Prometheus 会做 compaction,把较小的数据块合并成更大的块,以降低查询和存储开销。

超过保留期或超出容量限制的数据会被删除。

8.7 Prometheus 更偏近期热数据

工程上通常把它理解成:

  • 最近一段时间的核心观测库

而不是:

  • 无限期长期归档仓库

这也是为什么实际生产里经常会结合:

  • remote_write
  • 长期存储后端

8.8 Prometheus 是单机 TSDB,不是无限水平扩展数据库

这里非常容易产生误解。

Prometheus 非常强,但它的核心 server 设计并不是:

  • 一个天然无限水平扩展的分布式写入集群

它更像:

  • 每个 Prometheus server 负责自己的一块监控职责

当规模变大时,再通过:

  • federation
  • remote write
  • 外部兼容后端

来做聚合或长存储。

这里的“单机 TSDB”不是说它只能监控一台机器,而是说:

  • 一个 Prometheus 实例本质上有自己独立的数据目录
  • 它自己负责采集、写入、查询这份本地 TSDB
  • 它不是那种多节点共同写一个统一分布式存储面的原生数据库

8.9 水平扩展是不是“集群模式”

如果你问:

  • 水平扩展是不是集群模式?

答案要分两层看。

从原生 Prometheus 角度看

严格说:

  • Prometheus 没有一个像 MySQL 主从、ES 集群那样的“原生统一存储集群模式”

也就是说,官方单个 Prometheus server 的常规用法仍然是:

  • 单实例持有自己的本地 TSDB

当采集规模变大时,常见做法是:

  • 按职责拆多个 Prometheus
  • 按环境拆多个 Prometheus
  • 按业务域拆多个 Prometheus

这更准确地叫:

  • functional sharding
  • scrape sharding

而不是一个“大家共同写同一份分布式块存储”的原生集群。

从整套监控平台角度看

如果把生态一起算上,那确实可以做成“集群化的 Prometheus 体系”,但通常依赖的是外部系统,例如:

  • Thanos
  • Cortex
  • Grafana Mimir
  • VictoriaMetrics

这类方案的思路一般是:

  • 每个 Prometheus 继续本地采集和短期存储
  • 再通过 remote_write 或 sidecar 把数据送到外部统一存储
  • 由外部查询层把多实例数据聚合起来

所以更准确的结论是:

  • 原生 Prometheus 不是传统意义上的分布式集群数据库
  • 但 Prometheus 生态可以组合出集群化、长存储、多副本、高可用方案

一个直观三层图:多个 Prometheus -> Thanos/Mimir -> Grafana

如果只想先建立最直观的空间感,可以先看这个三层图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+------------------------------------------------------+
|                       Grafana                        |
|      Dashboard / Explore / Alerting / Variables     |
+--------------------------+---------------------------+
                           |
                           | Query
                           v
+------------------------------------------------------+
|             Thanos / Mimir / Cortex Query            |
|         统一查询入口 / 聚合 / 去重 / 长期查询         |
+--------------------+----------------+----------------+
                     |                |
          remote_write / sidecar      | Query fan-out
                     |                |
     +---------------+-----+   +------+--------------+
     |                     |   |                     |
     v                     v   v                     v
+-----------+         +-----------+           +-----------+
| Prom A    |         | Prom B    |    ...    | Prom C    |
| Prod      |         | Staging   |           | Team-X    |
| TSDB本地  |         | TSDB本地  |           | TSDB本地  |
+-----+-----+         +-----+-----+           +-----+-----+
      |                     |                       |
      v                     v                       v
  Targets A             Targets B               Targets C

这张图表达的是:

  • 最底层多个 Prometheus 各自采集、各自本地存储
  • 中间层 Thanos / Mimir 负责统一查询、聚合、去重、长存储能力
  • 最上层 Grafana 不一定要分别连每个 Prometheus,也可以只连中间统一入口

因此在工程上更常见的结果是:

  • 采集层分散
  • 存储与查询能力集中
  • 展示层统一

8.10 “集群化”以后数据怎么存

这要看你用哪种扩展方案。

方案 1:多个 Prometheus 各存各的

这是最朴素也最常见的方式。

每个 Prometheus:

  • 采自己负责的 targets
  • 数据写自己本地磁盘
  • 必要时通过 federation 汇总部分结果

这种方式下没有一个真正统一的底层存储池。

方案 2:Prometheus 本地存短期,外部系统存长期

这是生产里更常见的“大规模方案”。

例如:

  • Prometheus 本地只保留 7 天或 15 天
  • 同时把数据通过 remote_write 发到长期存储后端

这时数据会变成两层:

  1. 近实时热点数据在 Prometheus 本地 TSDB
  2. 长期历史数据在外部后端

外部后端内部可能用的是:

  • 对象存储
  • 分布式索引
  • 自己实现的时序存储引擎

具体细节取决于 Thanos / Mimir / Cortex / VictoriaMetrics 的实现。

方案 3:高可用双 Prometheus

很多团队会部署两个 Prometheus 抓同一批 targets。

这主要是为了解决:

  • 单点故障

这时两台 Prometheus 往往会:

  • 各自保留一份本地数据

如果后面接了统一后端,查询层再负责:

  • 去重
  • 聚合

一个更容易一眼看懂的三层架构演进图

你也可以把 Prometheus 的常见架构演进理解成下面 3 层:

形态 1:单机 Prometheus
1
2
3
4
5
6
7
+-----------+        Query        +-----------+
| Grafana   | ------------------> | Prometheus|
+-----------+                     | 本地 TSDB |
                                  +-----+-----+
                                        |
                                        v
                                     Targets

特点是:

  • 最简单
  • 部署成本低
  • 适合个人学习、小团队、单环境

局限也很直接:

  • 单点
  • 本地存储能力有限
  • 长期历史和多副本能力弱
形态 2:HA 双 Prometheus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
                 +----------------------+
                 |       Grafana        |
                 +----+------------+----+
                      |            |
                    Query        Query
                      |            |
                      v            v
              +-----------+  +-----------+
              | Prom A    |  | Prom B    |
              | 本地 TSDB |  | 本地 TSDB |
              +-----+-----+  +-----+-----+
                    |              |
                    +------++------+
                           ||
                           vv
                        Same Targets

特点是:

  • 两台都抓同一批目标
  • 主要目的是高可用,不是为了把底层存储拼成一块
  • 任意一台挂掉,另一台还能继续采集和查询

但这时仍然存在:

  • 数据各存各的
  • 查询入口不统一
  • 跨实例聚合和长期存储仍然不优雅
形态 3:Prometheus + Thanos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+-----------+            Query            +------------------+
| Grafana   | --------------------------> | Thanos Query     |
+-----------+                             | 聚合 / 去重      |
                                          +----+--------+----+
                                               |        |
                                               |        |
                                        +------+        +------+
                                        |                    |
                                        v                    v
                                  +-----------+        +-----------+
                                  | Prom A    |        | Prom B    |
                                  | + Sidecar |        | + Sidecar |
                                  | 本地 TSDB |        | 本地 TSDB |
                                  +-----+-----+        +-----+-----+
                                        |                    |
                                        +---------++---------+
                                                  ||
                                                  vv
                                               Targets

                     Sidecar / Store Gateway
                              |
                              v
                      Object Storage (S3/MinIO ...)

这时体系会更成熟:

  • Prometheus 继续负责采集和短期本地查询
  • Thanos Query 提供统一查询入口
  • Sidecar 把 block 暴露出去,或配合对象存储实现长期保留
  • 多个 Prometheus 的数据可以被统一聚合和去重

如果把 Thanos 换成 Mimir,可以理解成另一种实现路线:

  • Prometheus 通过 remote_write 把数据写入 Mimir
  • Grafana 再查询 Mimir 的统一入口

可以把这 3 种形态记成一个演进路径:

  1. 单机:先跑起来
  2. HA 双 Prometheus:先解决单点
  3. Prometheus + Thanos/Mimir:再解决统一查询、长存储和规模化

8.11 是否支持 MySQL、Oracle、Elasticsearch 或向量库

如果你的问题是:

  • Prometheus 本地 TSDB 能不能直接把底层存储换成 MySQL、Oracle、Elasticsearch 或向量库?

通常答案是:

  • 不作为官方主流方案

Prometheus 默认和最核心支持的是:

  • 自己的本地 TSDB
  • remote_write 到兼容的远端时序存储系统

它并不是一个“可自由切换底层数据库驱动”的框架。

为什么不是 MySQL / Oracle

因为 Prometheus 的写入模式和查询模式决定了它更适合:

  • 专门的时序存储引擎

而不是传统关系型数据库。

关系型数据库理论上可以存时序数据,但工程上通常会遇到:

  • 高频写入成本高
  • 高基数标签处理不理想
  • 时间序列聚合效率不优
  • 存储和索引成本偏高

所以它不是 Prometheus 官方主流落地方向。

为什么不是 Elasticsearch

Elasticsearch 更偏:

  • 文档检索
  • 日志搜索
  • 全文分析

它很适合日志和搜索场景,但不是 Prometheus 原生本地 TSDB 的替代目标。

很多团队会出现“Prometheus + Elasticsearch”同时存在,但通常分工是:

  • Prometheus 负责 metrics
  • Elasticsearch 负责 logs / search

而不是:

  • Prometheus 把 metrics 默认存进 ES

为什么也不是向量库

向量数据库更偏:

  • embedding 相似度检索

这和 Prometheus 的核心需求不是一个问题域。

Prometheus 关心的是:

  • 按时间和标签查询时序样本

不是:

  • 做语义向量召回

所以向量库基本不在 Prometheus 的主流存储讨论范围内。

那到底应该接什么“外部存储”

更常见、更合理的方向是:

  • Thanos
  • Cortex
  • Grafana Mimir
  • VictoriaMetrics

也就是:

  • 专门面向 Prometheus 生态的远端时序存储方案

8.12 一个最实用的工程结论

你可以把 Prometheus 存储层记成下面这张心智图:

  1. 默认存储:本地磁盘上的 Prometheus TSDB
  2. 本地结构:head + WAL + blocks
  3. 默认定位:近期热数据,不是无限长存储
  4. 原生形态:单实例独立存储,不是天然分布式集群
  5. 扩展方式:分片、federation、remote write、外部时序后端
  6. 外部后端选择:优先选 Prometheus 生态时序系统,不是 MySQL / Oracle / ES / 向量库

如果只记一句话,我建议记这句:

  • Prometheus 默认把 metrics 存在本地 TSDB 文件里;规模变大时,不是把底座换成 MySQL,而是接专门的远端时序存储体系

9. 配置文件怎么读

Prometheus 官方文档强调:

  • flags 配置不可热更新的系统参数
  • YAML 配置定义抓取 jobs、rule files 等可热更新内容

9.1 两类配置来源

  • 启动参数:例如数据目录、存储相关参数
  • 配置文件:例如 scrape_configsrule_files

9.2 配置支持热加载

官方文档明确提到:

  • 可以通过 SIGHUP
  • POST /-/reload

触发配置重载。

这个能力很实用,因为它意味着:

  • 目标发现和规则文件可以在不停服务的情况下更新

9.3 最核心的配置块

一个典型配置大致包含:

1
2
3
4
5
6
7
8
9
10
11
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "rules/*.yml"

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

重点是理解每一块职责:

  • global:全局抓取和评估默认值
  • rule_files:录制规则和报警规则文件
  • scrape_configs:采集目标定义

9.4 scrape_intervalevaluation_interval

这两个参数经常被混淆:

  • scrape_interval:多久抓一次指标
  • evaluation_interval:多久评估一次规则

它们可以相同,也可以不同。

工程上更重要的是:

  • 你要明确规则评估依赖于采集数据是否已经到位

否则会出现:

  • 报警窗口设置看起来正确,但数据还没到

10. Service Discovery 和 Relabeling 是生产环境关键

很多入门文章只停在 static_configs,但真实生产里 Prometheus 很大一部分威力来自:

  • service discovery
  • relabeling

10.1 为什么需要服务发现

在容器化和云环境里,实例不是静态的。

实例可能:

  • 频繁扩缩容
  • 重建
  • 改 IP
  • 重新调度

如果你完全手写静态 target,很快就会失控。

10.2 relabeling 的本质

relabeling 可以理解成:

  • 对目标标签和指标标签做加工、过滤、改写

它是 Prometheus 非常强但也最容易写复杂的能力之一。

10.3 工程上它解决什么

  • 过滤不需要采集的 target
  • 重写 job / instance
  • 从服务发现元数据里提取业务标签
  • 丢弃高风险标签

所以生产里经常真正决定“这个监控体系是否能规模化”的,不只是 PromQL,而是:

  • 你的 relabel 设计是否干净

11. PromQL 是 Prometheus 的灵魂

如果说 exporter 是 Prometheus 的入口,PromQL 就是它的大脑。

Prometheus 官方文档强调:

  • PromQL 支持实时选择和聚合 time series

11.1 Instant Query 和 Range Query

PromQL 有两个基本查询方式:

  • instant query:某个时间点的值
  • range query:一段时间范围内按步长多次求值

这也是为什么同一个表达式:

  • 在表格里看是一个点
  • 在图表里看是一条线

11.2 选择器语义

最基础的选择器是:

http_requests_total

带标签筛选:

http_requests_total{job="api", method="GET"}

11.3 PromQL 不是 SQL

它更像:

  • 面向时间序列的函数式查询语言

你最常见的不是 join table,而是:

  • 选择
  • 聚合
  • 速率计算
  • 时间窗口函数

11.4 Counter 一定要会 rate

例如:

rate(http_requests_total[5m])

这是因为 Counter 通常看的不是绝对值,而是:

  • 增长速率

11.5 聚合的常见形式

例如:

sum by (job) (rate(http_requests_total[5m]))
avg by (instance) (process_cpu_seconds_total)
max without (instance) (jvm_memory_used_bytes)

PromQL 的日常工作,大量都在做:

  • label 维度上的聚合和收敛

11.6 Histogram 查询是进阶分水岭

例如看 p95:

histogram_quantile(
  0.95,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)

这类查询的关键不只是会背,而是理解:

  • 先对 bucket 做聚合
  • 再算 quantile

这也是为什么 Prometheus 生态里 Histogram 很重要。


12. Recording Rules 是性能和可读性的拐点

Prometheus 官方文档对 recording rules 的定义很清楚:

  • 预先计算常用或昂贵表达式,并把结果存成新的 time series

12.1 为什么需要 recording rules

因为很多表达式会被反复查询:

  • 仪表盘反复刷
  • 多个图反复用
  • 告警规则也依赖

如果每次都临时算,会带来:

  • 查询成本高
  • 仪表盘慢
  • 告警表达式难读

12.2 recording rule 的价值

  • 预聚合
  • 提升查询性能
  • 统一口径
  • 让 dashboard 和 alert 直接复用

12.3 一个简单例子

1
2
3
4
5
groups:
  - name: api.rules
    rules:
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))

这样后面无论 dashboard 还是 alert 都可以直接用:

  • job:http_requests:rate5m

12.4 recording rules 不是越多越好

它是非常有价值的能力,但也要节制。

如果滥用,会出现:

  • 规则过多
  • 额外 series 增长
  • 口径难维护

所以更好的原则是:

  • 对高频复用、计算重、口径稳定的表达式录制

13. Alerting Rules 怎么理解

Prometheus 的 alerting rules 其实就是:

  • 定期用 PromQL 判断某条件是否成立

13.1 一个基本结构

官方格式大致如下:

1
2
3
4
5
6
7
8
9
10
groups:
  - name: alert.rules
    rules:
      - alert: HighErrorRate
        expr: sum(rate(http_requests_total{code=~"5.."}[5m])) > 10
        for: 5m
        labels:
          severity: page
        annotations:
          summary: "5xx 错误率过高"

13.2 for 非常重要

for 的语义是:

  • 条件持续满足多久后,告警才真正 firing

它的作用是:

  • 避免瞬时抖动

13.3 keep_firing_for

官方文档还支持:

  • keep_firing_for

它控制:

  • 条件恢复后告警还维持 firing 多久

这个参数有时对抖动场景很有帮助,但大多数团队更常用的仍是先把:

  • 条件表达式
  • 时间窗口
  • for

设计好。

13.4 Alertmanager 不是同一个组件

Prometheus 负责:

  • 计算是否触发告警

Alertmanager 负责:

  • 去重
  • 分组
  • 静默
  • 路由
  • 通知

这两个经常被混成一个东西,但职责其实不同。


14. 规则执行也有成本和坑

Prometheus 官方文档在 recording rules 里专门提到几个容易忽视的点。

14.1 规则组按间隔评估

规则是按 group 周期执行的,同组规则共享评估时间。

14.2 规则过慢会跳过后续评估

官方文档明确说:

  • 如果一个 rule group 还没执行完,下次该执行时会被跳过

这会带来:

  • 规则结果缺口
  • 告警延迟

这说明一件事:

  • PromQL 不只是写对,还要写得足够高效

14.3 rule group 的设计要有层次

工程上通常应该:

  • 把基础预聚合放在 recording rules
  • 告警尽量依赖已经录好的指标

不要把特别重的表达式直接层层套进告警。


15. Pushgateway 要非常克制地用

这个单独拎出来再强调一次,是因为太多人把它用成反模式。

15.1 为什么它危险

Prometheus 官方文档明确指出几个核心问题:

  • 会成为单点故障或瓶颈
  • 失去 up 这类自动健康检查能力
  • 不会自动清理失效实例的历史 pushed metrics

15.2 真正合理的使用场景

通常只有:

  • 服务级短任务

例如:

  • 每天一次的全局结算任务
  • 每小时一次的全服务数据清理任务

这类任务结束就没进程了,但你又想保留:

  • 本次任务是否成功
  • 处理了多少数据
  • 耗时多少

15.3 不合理的用法

  • 在线服务也走 push
  • 每台机器 cron 都往 Pushgateway 推
  • 用 Pushgateway 代替正常 target scrape

这类设计后面一般都会带来:

  • stale metrics
  • lifecycle 混乱
  • 监控语义失真

16. Remote Write、Federation、长存储怎么区分

这是 Prometheus 中高级阶段常见混淆点。

16.1 Federation

federation 更像:

  • 一个 Prometheus 从另一个 Prometheus 拉一部分聚合结果

它适合:

  • 分层汇总
  • 上层只关心一部分指标

16.2 Remote Write

remote_write 更像:

  • 把采集到的数据副本持续推送到外部兼容后端

它通常用于:

  • 长期存储
  • 全局统一查询
  • 多集群汇聚

16.3 不要把 Prometheus 本地 TSDB 当无限长期仓库

工程上更稳妥的理解是:

  • Prometheus 本地库负责近期高价值观测
  • 长期保留和大规模集中查询通常交给远端后端

16.4 Agent Mode 要知道,但别乱套

Prometheus 新一些的文档里也强调了 agent mode。

它的思路是:

  • 更轻量地采集并 remote write
  • 不以本地完整 TSDB 查询为目标

所以它适合某些集中式架构,但并不意味着:

  • 所有场景都该放弃标准 Prometheus server

17. 实战里最常看的内置页面

Prometheus 本身就有几个非常有用的页面。

17.1 /targets

看:

  • 哪些 target 正在被抓
  • 哪些 target down 了
  • 抓取错误是什么

17.2 /graph

看:

  • 临时 PromQL 查询
  • 表达式调试

17.3 /alerts

看:

  • 当前有哪些 alert 在 pending / firing

17.4 /config

看:

  • 当前生效配置

这几个页面在日常排障时很有价值,不要只盯着 Grafana。


18. 常见误区

18.1 把 Prometheus 当成“会抓指标的数据库”

这理解太窄了。

它还是:

  • 查询引擎
  • 规则引擎
  • 告警触发器

18.2 把所有字段都做成 label

这是 Prometheus 最常见的生产事故来源之一。

18.3 把 Pushgateway 当通用采集入口

官方并不推荐这么做。

18.4 告警直接写超级复杂 PromQL

这样会导致:

  • 查询难维护
  • 性能差
  • 难调试

更好的方式通常是:

  • 先 recording rule
  • 再 alerting rule

18.5 只会看平均值

Prometheus 的价值之一就是:

  • 可以非常方便地看速率、分位数、长尾

如果最后只看平均值,其实浪费了它很多能力。

18.6 觉得有了 Prometheus 就等于有了完整可观测性

没有。

你还需要:

  • Grafana 做可视化
  • Alertmanager 做告警路由
  • 日志系统
  • Trace 系统

19. 我对 Prometheus 的一个实用理解

如果要用一句更偏工程的话总结:

  • Prometheus 是“围绕 time series 构建的采集、存储、查询、规则与告警系统”

它最强的地方不是某一个点,而是:

  • 数据模型统一
  • PromQL 统一
  • 规则和告警统一
  • 生态统一

所以它真正厉害的不是“能抓很多指标”,而是:

  • 它把监控这件事抽象成了一套非常一致的语言

20. 这篇笔记最该带走的结论

  1. Prometheus 本质上是时序监控与告警系统,不只是采集器。
  2. 一条 time series 由指标名和标签集合唯一确定。
  3. label 设计失控,最终会演化成高基数灾难。
  4. jobinstance 是 Prometheus 里非常基础的定位标签。
  5. up 是 pull 模型天然附带的健康信号,非常重要。
  6. PromQL 是 Prometheus 的核心能力,不只是一个附属查询语言。
  7. recording rules 用来预聚合和统一口径,alerting rules 用来触发告警。
  8. Pushgateway 只能有限使用,绝不是通用 push 入口。
  9. Prometheus 本地 TSDB 更偏近期观测,不是无限长存储。
  10. Prometheus 要和 Grafana、Alertmanager、日志、Trace 一起看,才是完整体系。

21. 相关阅读

和本文衔接最自然的一篇是:

  • Grafana 深度学习笔记

因为当你理解了 Prometheus 的“采、存、算、告”之后,下一步就应该理解:

  • Grafana 为什么不是 Prometheus 的替代品
  • 它在展示、探索、变量、看板设计上到底做了什么