LabHub
学习 学习路径 课程

PCA — Prometheus 认证助理

指标、日志、追踪回答的是不同的问题

在 LabHub 中继续学习

一句话总结

指标回答何时、多少,日志回答为什么,追踪回答在哪里。三者并非彼此的高级替代品,而是能够回答的问题类型不同。一旦给指标加上请求 ID,它就已经不再是指标,而是压缩率很差的事件存储。

概念图: 何时、多少 · 为什么 · 在哪里 · 指标的极限由基数决定。

为什么需要它

故障响应时打开仪表板,里面有 40 个面板:CPU、内存、线程数、GC 次数、连接池大小、堆使用量、每秒请求数。每一项都有图表。但现在真正想知道的只有一个问题:“用户是否正在遭遇失败?如果是,比例是多少?”40 个面板里没有一个能回答。

指标设计的问题不在于数据不足,而在于已收集数据能够回答的问题,与真正需要回答的问题彼此错位。因此,起点不应是指标清单,而应是问题清单。先写下值班人员凌晨 3 点会提出的五个问题,再只创建能够回答这五个问题的指标。

工作原理

问题 指标 日志 追踪
从什么时候开始恶化 能回答 很困难 无法回答
多少比例的请求受到影响 能回答 成本高 无法回答
这个请求为什么失败 无法回答 能回答 无法回答
慢请求在哪个服务中耗时 无法回答 无法回答 能回答

指标无法回答的格子很重要。一旦试图增加标签来填补这些格子,成本就会爆炸。指标的极限由基数决定。

考试最常出现的概念则是百分位数。假设 10,000 个请求中,9,900 个耗时 50ms,100 个耗时 3,000ms,平均值是 79.5ms。实际上没有任何请求在 79.5ms 得到响应。更糟的是它的敏感度:即使 100 个慢请求从 3,000ms 恶化一倍到 6,000ms,平均值也只从 79.5 移到 109.5;上升 30ms 不会越过任何告警阈值。

由此得到两点。

第一,p99 并不代表“1% 的用户”。 它意味着每 100 个请求中有 1 个。如果一个页面调用 20 个 API,该页面遇到 p99 的概率是 18.2%;每天发起 200 次请求的用户,有 86.6% 的概率每天至少一次遇到最差区间。

第二,百分位数不能合并。 假设服务器 A 的 9,900 个请求全部为 50ms,服务器 B 的 100 个请求全部为 3,000ms,那么 p99 的平均值为 1,525ms,按请求数加权的平均值为 79.5ms,而把两台服务器的请求排成一列后得到的真实 p99 是 3,000ms。三个数字完全不同,前两个毫无意义。计数器可以相加,百分位数不能相加——这正是直方图存在的原因。

SLI 是测量指标,SLO 是其目标值,SLA 是法律合同。若 30 天目标为 99.9%,错误预算就是 0.1%,即 43,200 分钟的 0.1%——43.2 分钟。燃烧率是消耗预算速度的倍数;如果一直以 14.4 倍燃烧,只需 50 小时就会耗尽 30 天的预算。

现场会遇到的情况

作者的 7 节点家庭实验室(3 个控制平面 + 4 个 GPU 工作节点)部署了 kube-prometheus-stack,Grafana 使用 MetalLB 地址池 10.0.0.200–215 中的 10.0.0.203。计算一下这里一张直方图的成本,就能形成直观认识。

http_request_duration_seconds_bucket
  route 120 × method 5 × le 11 × pod 40 = 264,000 시계열
  여기에 _sum 과 _count: 120 × 5 × 40 × 2  = 48,000
  ------------------------------------------------
  합계 약 312,000 시계열 — 메트릭 하나에서

仅仅一个指标就占用 30 多万条时间序列。按每条时间序列约 8KB 计算,1,000 万条序列就是 80GB。为什么“先全部加入,以后再减少”很危险,用这一个乘法就足以说明。

再补充一条从同一集群学到的经验:安装 KubeVirt 时,组件状态全都显示 AllComponentsReady,虚拟机却无法启动。“状态为 Ready”和“实际可用”是两个不同命题。 可观测性应以用户遭遇的症状为材料,而不是 Ready 标签。

Prometheus 看待世界的方式

使用 Prometheus 时,有些行为会让人疑惑“为什么会这样”,但大多源自拉取(pull)模型和时间序列存储结构。理解这两点,其余现象就都能解释。

目标消失,指标也随之消失。 Pod 死亡后,该时间序列不再进入系统。因此,up == 0 无法捕获已经消失的目标,因为 up 本身也不存在。要捕获消失事件,需要使用 absent(),或与服务发现中预期的目标数量比较。

数值是抓取时刻的快照。 如果每 15 秒抓取一次,中间的瞬时激增就看不到。计数器会累积,因此不会遗漏;而仪表只保留抓取瞬间的值。如果必须知道瞬时最大值,应用应自行将最大值记录为计数器或直方图。

rate() 只用于计数器。 用在仪表上没有意义;反过来,直接绘制计数器只会看到不断上升的曲线。计数器因重启归零,rate 会自动校正。

范围向量窗口至少应为抓取间隔的 4 倍。 如果使用 rate(x[1m]),而抓取间隔为 30 秒,窗口里只有两个点,结果很不稳定;漏掉其中任何一个,结果就会为空。[5m] 左右是安全的默认值。

只要有一个标签不同,就是另一条时间序列。 因此,改变标签的部署会让图表出现断点。旧序列在该时刻结束,新序列从此开始。在仪表板中查看总量时,用 sum by () 聚合,可以减弱这种断点的可见性。

存储位于本地,长期保存需要其他设施。 Prometheus 本身并不以长期留存和高可用为目标,这些职责由远程写入和独立的长期存储承担。

下一项检查要看什么

本模块是概念模块,没有实验。完成测验、确认三种信号的边界和百分位数的性质后,下一模块会让你亲自编写 prometheus.yml,并亲手决定“哪些目标保留下来、哪些指标被丢弃”。