第4章:Prometheus入门:架构、核心概念与PromQL基础
大家好,我是你们的老朋友。今天咱们聊聊Prometheus。说实话,在云原生监控这个领域,Prometheus几乎成了标配。我最早接触它是在2017年,那时候还在用Zabbix和Open-Falcon,后来Kubernetes一普及,Prometheus就跟着火起来了。为什么?因为它天生就是为动态环境设计的。
4.1 Prometheus架构:一张图看懂全局
先看这张架构图,我亲手画的,帮你理清Prometheus到底是怎么工作的。
这张图里,最核心的就是中间的Prometheus Server。它主动去拉取(Pull)各个目标的数据,而不是等目标把数据推过来。这个设计理念,跟传统的Push模型完全不同。我个人觉得,Pull模型在云原生环境里特别香——你想想看,服务实例随时可能扩缩容,如果靠Push,你得维护一份完整的目标列表,太累了。
4.2 Pull模型工作原理
Pull模型说白了就是:Prometheus定期去访问每个目标的/metrics接口,把数据拿回来存到自己的时序数据库里。
具体流程是这样的:
- 配置目标:在prometheus.yml里写上要监控的目标地址
- 服务发现:也可以让Prometheus自动发现目标(比如通过K8s API)
- 定时抓取:默认每15秒拉一次,这个间隔可以调
- 数据存储:拉回来的数据按时间戳+标签存进TSDB
- 规则评估: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