第4章:Prometheus入门:架构、核心概念与PromQL基础

大家好,我是你们的老朋友。今天咱们聊聊Prometheus。说实话,在云原生监控这个领域,Prometheus几乎成了标配。我最早接触它是在2017年,那时候还在用Zabbix和Open-Falcon,后来Kubernetes一普及,Prometheus就跟着火起来了。为什么?因为它天生就是为动态环境设计的。

4.1 Prometheus架构:一张图看懂全局

先看这张架构图,我亲手画的,帮你理清Prometheus到底是怎么工作的。

Prometheus 核心架构图 被监控目标 Exporter / 应用 /metrics 端点 服务发现 K8s / Consul / DNS Prometheus Server 抓取 (Pull) 存储 (TSDB) 告警规则评估 Alertmanager 告警去重 / 分组 通知 (邮件/钉钉) 可视化 Grafana / Console 远程存储 InfluxDB / Thanos Pull (HTTP) 目标列表 告警推送 查询 (HTTP API) 数据写入 数据抓取 服务发现 告警 可视化 远程存储

这张图里,最核心的就是中间的Prometheus Server。它主动去拉取(Pull)各个目标的数据,而不是等目标把数据推过来。这个设计理念,跟传统的Push模型完全不同。我个人觉得,Pull模型在云原生环境里特别香——你想想看,服务实例随时可能扩缩容,如果靠Push,你得维护一份完整的目标列表,太累了。

4.2 Pull模型工作原理

Pull模型说白了就是:Prometheus定期去访问每个目标的/metrics接口,把数据拿回来存到自己的时序数据库里。

具体流程是这样的:

  1. 配置目标:在prometheus.yml里写上要监控的目标地址
  2. 服务发现:也可以让Prometheus自动发现目标(比如通过K8s API)
  3. 定时抓取:默认每15秒拉一次,这个间隔可以调
  4. 数据存储:拉回来的数据按时间戳+标签存进TSDB
  5. 规则评估:Prometheus会定期检查告警规则,触发告警就推给Alertmanager

核心要点:Pull模型让监控系统对目标无侵入。你只需要在应用里暴露一个/metrics端点,Prometheus自己会来取数据。我曾经在迁移一个老系统时,就因为这点省了不少事——不用改应用代码,加个Exporter就行。

4.3 核心概念:Metric与Label

在Prometheus里,数据叫Metric(指标)。每个Metric由三部分组成:

  • 指标名:比如http_requests_total
  • 标签:键值对,比如method="GET", status="200"
  • 样本值:一个float64的数字

举个例子:

http_requests_total{method="POST", handler="/api/v1/orders"} 1024

这个Metric表示:POST方法请求/api/v1/orders这个接口的总次数是1024次。

我的经验:标签设计是门学问。标签太多会导致基数爆炸,把Prometheus搞崩。我见过一个团队给每个请求加上了user_id标签,结果几百万用户一跑,内存直接爆了。记住:标签的基数(不同取值数量)要控制在几千以内。

4.4 PromQL基础语法:四种核心Metric类型

PromQL是Prometheus的查询语言。你想想看,数据都存进去了,怎么查出来用?PromQL就是干这个的。咱们先看四种最基础的Metric类型。

4.4.1 Gauge(仪表盘)

Gauge表示一个可增可减的值。比如CPU使用率、内存使用量、当前连接数。

特点:

  • 值可以上升也可以下降
  • 适合表示瞬时状态

示例:

# 查询当前CPU使用率
node_cpu_seconds_total{mode="idle"}

# 查询当前内存使用量
node_memory_MemAvailable_bytes

Gauge最常用的PromQL操作是计算变化率,但更多时候我们直接看原始值。比如:

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

4.4.2 Counter(计数器)

Counter只增不减。比如HTTP请求总数、错误次数、CPU时间片。

特点:

  • 只能增加,重启时归零
  • 适合统计累计值

示例:

# 查询HTTP请求总数
http_requests_total

# 查询过去5分钟的请求速率
rate(http_requests_total[5m])

注意:Counter直接用原始值意义不大,因为它是累计的。我们通常用rate()或irate()函数计算速率。我曾经见过有人直接用Counter值做告警,结果服务器重启后告警就误报了——因为Counter归零了。

4.4.3 Histogram(直方图)

Histogram用于统计分布情况。比如请求延迟的分布、响应大小的分布。

它包含三个部分:

  • 桶(Bucket):落在某个范围内的计数
  • 总和(Sum):所有值的总和
  • 计数(Count):总样本数

示例:

# 查询请求延迟分布
http_request_duration_seconds_bucket{le="0.1"}  # 延迟≤0.1秒的请求数
http_request_duration_seconds_bucket{le="0.5"}  # 延迟≤0.5秒的请求数
http_request_duration_seconds_sum               # 总延迟
http_request_duration_seconds_count             # 总请求数

用Histogram可以计算百分位数:

# 计算P99延迟
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

我的习惯:做SLA监控时,我一般用Histogram算P99和P95。但要注意,桶的边界设置要合理。比如延迟监控,桶可以设为{0.01, 0.05, 0.1, 0.5, 1, 5}秒。太粗了算不准,太细了浪费存储。

4.4.4 Summary(摘要)

Summary跟Histogram类似,也是统计分布。但区别在于:Summary在客户端直接算好了百分位数,服务端拿到的就是现成的值。

特点:

  • 客户端计算,服务端直接使用
  • 无法对多个Summary做聚合计算

示例:

# 查询P99延迟(客户端已算好)
http_request_duration_seconds{quantile="0.99"}

# 查询总延迟和请求数
http_request_duration_seconds_sum
http_request_duration_seconds_count

Histogram vs Summary 怎么选?

特性 Histogram Summary
计算位置 服务端 客户端
可聚合 可以(用histogram_quantile) 不可以
存储开销 较高(多个桶) 较低(固定几个分位点)
适用场景 需要自定义分位点、跨实例聚合 已知分位点、不需要聚合

我个人建议:大部分场景用Histogram。因为你可以随时调整分位点,还能跨多个实例做聚合。Summary一旦配好分位点,后面想改就得改代码重新部署。

4.5 实战:写一条完整的PromQL

咱们来写一个实际场景的查询。假设你要监控线上服务的错误率:

# 错误率 = 错误请求数 / 总请求数 * 100
(
  sum(rate(http_requests_total{status=~"5.."}[5m]))
  /
  sum(rate(http_requests_total[5m]))
) * 100

这条PromQL做了几件事:

  • 用rate()计算过去5分钟每秒的请求速率
  • 用{status=~"5.."}过滤出5xx错误
  • 用sum()聚合所有实例
  • 最后算百分比

避坑指南:我曾经在写类似查询时,忘了加sum(),结果返回了每个实例的错误率。在Grafana面板上显示了一堆曲线,根本没法看。记住:多实例场景下,一定要考虑是否需要聚合。

4.6 本章小结

咱们这一章把Prometheus的骨架搭起来了。Pull模型、四种Metric类型、PromQL基础语法,这些都是后面所有监控实践的地基。你想想看,理解了这些,后面学告警规则、Grafana面板、甚至Thanos集群,都会轻松很多。

嗯,今天就到这儿。下一章咱们会深入PromQL的高级用法,包括聚合操作、子查询、以及如何写出高效的查询。到时候见。


公众号:蓝海资料掘金营,微信deep3321