TT Lab
开始
学习 学习路径 课程

CNPE — 云原生平台工程师

从保存规则到实际执行规则

在 TT Lab 中继续学习

一句话总结

创建了 PrometheusRule,只意味着规则已经存储到 Kubernetes 中。 这条规则是否被选中、是否被加载到 Prometheus、是否在真实的时间序列上被评估,必须分别确认。

为什么需要它

虚构的发放平台团队添加了故障告警规则。终端里打印了 created, 代码评审中也确认表达式是对的。几天之后,发放 API 返回了 503,却没有 收到电话。搜索规则名称,在 Kubernetes 中可以看到,但在 Prometheus 的 rules API 中却没有。团队说“把告警表达式改得更灵敏一些”,然而修改一个根本没有被读取的表达式的 阈值,并不能修复这次的失败。

问题在于把两种不同的成功当成了同一件事。API 服务器负责 对象的存储,而 Operator 则挑选出要放入它所管理的 Prometheus 的对象,并生成配置。 即使应用团队有存储规则的权限,如果设计成所有 Prometheus 都读取这条规则, 多个团队的规则就会被不加区分地混在一起。选择范围不是不便的壁垒, 而是表达所有权和运维范围的机制。

工作原理

观测对象 所确认的问题 尚无法证明的内容
Kubernetes 中的 PrometheusRule 规则对象是否已存储 Operator 的选择、实际评估
Namespace 和规则的标签 是否落入指定的选择范围 配置是否已经反映到实际进程中
Prometheus rules API 规则组是否已加载到运行中的实例 条件是否满足、告警是否送达
targets API 以什么结果采集哪些地址 该业务是否成功

选择要缩小两次。首先由 ruleNamespaceSelector 选出要查找规则的命名空间。 在这个范围内,由 ruleSelector 检查 PrometheusRule 的标签。 默认值和空选择器的含义可能因字段而异,所以不要猜测“什么都没写, 应该是全部选中”。确切的行为要在 Operator 规则选择指南中确认。

举个例子,假设有一个实例,只读取 monitoring=yes 的命名空间中 owner=payments 的规则。 即使在规则里写了 owner=payments,如果命名空间在范围之外,也不会 读取。只修改了命名空间,但规则是 owner=orders,仍然不会读取。 如果同时把两者都改成全选,虽然眼下也许能看到,但也会读取其他团队的规则, 造成重复告警或成本增加。只修改需要的那一个条件,再重新观测。

指标采集也是另外一条选择路径。ServiceMonitor 通过 Service 的标签和端口名称 来寻找采集目标,Prometheus 则选择 ServiceMonitor 的命名空间和标签。 把端口号写成字符串,与使用 Service 的端口名称,并不是一回事。 权限不足也可能像标签不匹配一样,表现为看不到目标这样的症状,所以 要按照官方故障排查顺序, 依次确认被选中的对象、生成的配置,以及服务和发现权限。

在现场相遇的样子

在本单元的准备实验中,目标指标是 up,而规则组是空的。 只修改了命名空间标签,观察 75 秒,规则也没有出现。把规则标签 对上之后,大约 80 秒后加载了。这是一次观测值,并不是建议把等待时间固定下来。 因为 API 变更、配置文件投射、重新加载和评估发生在不同的时刻, 所以这是提醒不要把终端里的 configured 当作最终证据的案例。

失败响应的形态也很重要。最初创建的 exporter 输出了正确的指标正文, 但 Content-Type 为空,导致 Prometheus 3 的 scrape 失败。 找到目标成功了,而读取内容失败了。重新修改标签也无法解决这个问题。 读取 target 的 lastError,然后修复了生产者的 HTTP 头。这一差别 可以与 Prometheus 3 变更说明对照。

采集成功的 up,是应用返回了指标这一观测。即使发放功能的外部 依赖出了故障,exporter 进程也可能持续正常响应。反过来,没有指标 也并不意味着业务一定失败了。要把业务状态和观测状态分开记录, 如果其中一个不知道,就应该把那个空白原样保留。

下一课要做什么

在下一篇阅读中,我们来看规则被加载之后,通知仍然没有送达的边界。 之后的实验中,不修改已准备好的规则的表达式,而是分别修改命名空间标签和规则标签。同时查看已存储的对象与 真实的 rules 和 targets API。修复一条边界之后,请记录什么变了、什么保持不变。 实验使用个人 VM 中真实的 k3s,并不是应用到生产集群的流程。