LabHub
学习 学习路径 课程

PCA — Prometheus 认证助理

up 本身就是信号 — pull 与 TSDB 的设计

在 LabHub 中继续学习

一句话总结

Prometheus 选择 pull 的原因不是性能,而是可观测性。服务器主动抓取时,“没有响应”这一事实本身也会成为数据,这就是 up metric。TSDB 会先把收到的 sample 顺序写入 WAL,集中到两小时的 Head Block 中,再 compaction 为持久 block。

概念图: 可观测性 · 存储路径 · 压缩 · 每个 sample 平均 1.37 字节

为什么需要了解这一点

在 push 模型中,无法区分数据没有到达与进程已经终止,因为两者看起来都是“什么都没有”。pull 模型会留下服务器尝试过的记录,因此失败会成为一个值。

up{job="checkout-api"} == 0
or
absent(up{job="checkout-api"})

考试经常考查这两个条件代表不同情况。up == 0 表示 target 已被发现,但 scrape 失败;absent(up{...}) 表示 target 整体从 discovery 中消失,连 up time series 本身都不存在。漏掉后者,service 被删除时 alert 会悄悄失效。

当然,pull 不是万能的。在 Prometheus 前来抓取之前就结束的短期 batch job 无法通过 pull 捕获,所以才有 Pushgateway 这一例外通道。让例外保持为例外,正是设计要点。

工作原理

存储路径分三层。

层级 位置 特性
WAL wal/ segment(默认 128MB) 顺序写入,用于 crash recovery
Head Block 内存 + chunks_head/ mmap 最近约 2 小时,可写入
持久 block ULID 目录 meta.jsonindexchunks/tombstones

新 sample 先写入 WAL,再附加到 Head Block 的 memSeries。active chunk 达到 120 个 sample 或 2 小时时便会封存,落入 chunks_head/ 的 mmap 文件,由 OS page cache 代为管理内存。compaction 按 level 进行:多个两小时 block 合并成六小时,再合并成十八小时。删除不会立即执行,而是先标记为 tombstone,直到 compaction 时才真正移除。

压缩源自 Gorilla 论文。timestamp 使用 delta-of-delta 存储,scrape 规律时大部分只需 1 bit;value 与前一个值做 XOR,再去掉前后的 0 bit。最终结果是每个 sample 平均 1.37 字节。记住这个数字,容量计算会很容易。

搜索使用 inverted index。每个 label name-value pair 对应的 time series ID 列表(posting list)以排序状态存储,因此能在线性时间内求出 job="prometheus"instance="localhost:9090" 的交集。这既是 label selector 速度快的原因,也是 cardinality 增加时该 index 最先变重的原因。

配置方面,考试关注三点。

然后是 staleness。target 消失后,相应 time series 会附加 stale marker(特殊 NaN)。query 会在 lookback delta(默认 5 分钟)内寻找最新 sample,遇到 stale marker 后便从结果中移除该 time series。准确的说法不是“5 分钟后才消失”,而是“遇到 marker 后立即移除”。

实际工作中的表现

曾有一次同时部署了 2,000 条 recording rule。每条 rule 会按 route 数量生成 time series,结果新增了约 100 万条 time series;它们全部进入 Head Block,导致 WAL 暴增。rule 文件看起来像代码,但从成本角度看,等同于添加新 metric。部署前应养成计算“120 条 route × 5 个 window × 50 条 rule”的习惯。

也可以在采集阶段进行阻止。设置 sample_limit,能够防止单个爆炸的 target 拖垮整个 Prometheus。触发后,该 target 的整次 scrape 会失败,所以值应留有充足余量,但务必要设置。没有上限,一个 service 的失误就可能中断全部 monitoring。

还要建立容量直觉。按每条 time series 约 8KB 计算,1,000 万条就是 80GB。对于 home lab 中 4C/14GB mini PC 组成的 control plane,这个数字就是极限线。

下个练习将做什么

从头编写 /root/pca-scrape/prometheus.yml。加入 global block、static_configs job、通过 kubernetes_sd 查找 Pod 的 job、用 relabel 选择 target 并重组 address 的规则、通过 metric_relabel 丢弃无用 metric 的规则,以及 sample_limit guardrail。最后把该文件作为 ConfigMap 放入 cluster,并创建一个会被刚才所写 keep 规则实际保留的 Pod 来确认结果。