2026年8月15日 1 分钟阅读

别拿玩具故障验证可观测性:用 RCA-lab 在 Kubernetes 重演锁等待、坏发布与 DNS 延迟

tinyash 0 条评论

可观测性平台、告警规则和根因分析 Agent 往往都在“健康”的测试环境里演示:手动调高一个延迟开关,再确认面板出现一条曲线。这种验证能证明采集链路没有断,却无法回答一个更难的问题:当线上同时有调用链、数据库、发布事件和节点资源等信号时,系统能不能把症状原因分开?

RCA-lab 是一个为这个问题准备的 Kubernetes 故障实验室。它不是导入一份固定的 trace 文件,也不是在业务代码里埋“模拟失败”的 feature flag;仓库部署一组持续有负载的多语言微服务、真实数据库和 Kafka,再用 Kubernetes 自定义资源触发可回滚的故障场景。项目采用 Apache-2.0 许可证,目标是评估人或 AI 使用的根因分析工具。

它特别适合作为上线前的验证台:先让自己的 OTLP 后端接到实验室遥测,再检查告警、查询、Runbook 和 Agent 给出的结论是否经得起真实干扰。

关键不在“有没有报警”,而在“报警指向哪里”

RCA-lab 的服务栈包含 Python、Go、Java、Node.js、Rust、PHP 等组件,后端使用 PostgreSQL、MySQL、MongoDB、Valkey Cluster 和 Kafka。每个服务通过 OpenTelemetry SDK 输出 trace、运行时/HTTP metrics 以及与 trace 关联的日志。仓库自带的 otel-collector 默认会丢弃数据,因此仅完成部署并不会自动产生可在外部平台查看的遥测;需要在部署时显式指定自己的 OTLP 接收端。

这种默认行为值得注意:它避免实验室未经确认就把测试数据发到某个 SaaS,但也意味着“页面没有数据”首先应检查 OTLP_ENDPOINT,而不是直接怀疑故障场景失效。

更有价值的是,场景给出的不是一个模糊的“服务变慢”,而是一组应被验证的鉴别线索。例如:

  • pg-exclusive-lock 会让一个停滞的 schema migration 真正持有 PostgreSQL products 表的 ACCESS EXCLUSIVE 锁。业务查询被阻塞、连接池被占满、网关端点报错,但数据库 CPU 和 I/O 可以保持平稳。若 RCA 工具只把“低 CPU”当作无事发生,就会漏掉锁等待这一类事故。
  • order-service-gc-regression 会部署包含真实分配回归的 Java 服务版本。此时 p99 延迟和 GC 时间上升,而 p50 可能仍然平稳;正确归因应把变化与 rollout 事件关联,而非把数据库当作首要嫌疑。
  • dns-slow-resolution 通过 Chaos Mesh 给到集群 DNS 路径的包加入约 500ms 延迟。多个下游调用都可能出现间歇性长尾,但依赖服务和 CoreDNS 的 CPU 并不一定异常。

因此,RCA-lab 不只适合验证“告警能否响”,还可用来检查根因分析是否能排除貌似合理、实际错误的解释:是锁而非算力,是发布而非数据库,是 DNS 路径而非某一个下游服务。

先把实验室部署成可观察的,而不是直接制造故障

完整实验室要求已经指向集群的 kubectlhelm,集群需要默认 StorageClass;项目建议为完整规模预留约 8 CPU 和 16 GiB 的节点总资源。下面示例将数据发送到自己的 OTLP 后端;端点、认证头与网络策略应替换为实际环境配置。

git clone https://github.com/coroot/rca-lab
cd rca-lab

make deploy OTLP_ENDPOINT=otel-gateway.example.internal:4317

kubectl get pods
kubectl get failurescenarios

如果是在单节点的 kind、k3d 或 minikube 中试验,README 提供了缩减资源布局的开关:

make deploy SINGLE_NODE=1 OTLP_ENDPOINT=otel-gateway.example.internal:4317

部署命令可以重复执行,用于收敛配置。开始前先做一轮无故障基线:确认网关有持续请求、自己的后端能看到 trace/metric/log,并记录正常时的延迟、错误率、数据库等待和节点资源。没有基线,之后即使看见 p99 升高,也难以区分场景引入的变化和测试环境本来的波动。

用一个锁等待场景检验诊断链路

场景由 FailureScenario 自定义资源控制。下面只启用 PostgreSQL 分析查询场景;启用前应先在自己的可丢弃集群中确认名称存在,再观察遥测与数据库诊断信号。命令不是压测生产环境的指令。

kubectl get failurescenarios

kubectl patch failurescenario pg-analytics-queries \
  --type=merge \
  -p '{"spec":{"enabled":true}}'

kubectl get failurescenarios

pg-analytics-queries 会让 analytics-reporting 工作负载对业务 PostgreSQL 运行重型多表关联和聚合查询,并通过与应用共享的 pgBouncer 池访问数据库。一个合格的排查结果不该止步于“product-catalog 变慢”,而应能把服务延迟、PostgreSQL CPU/I/O 饱和、查询指纹和发起工作负载串起来。

随后切换到 pg-exclusive-lock,可以验证另一条完全不同的判断路径:查询阻塞与 API 错误出现时,数据库资源曲线仍可能平坦。此时应检查锁等待、pg_lockspg_blocking_pids 关联出的阻塞关系,而不是因为 CPU 不高就把 PostgreSQL 排除。将两个场景的 Agent 回答、告警归因和人工 Runbook 对照,能暴露“只会根据单指标猜根因”的薄弱环节。

场景结束、禁用或删除时,RCA-lab 的 operator 会尝试恢复正常状态,并且设计上可跨 operator 重启持续处理回滚。不过“可回滚”不等于可以随意放到现有测试集群:项目明确警告 operator 有能力降级其 namespace 内的工作负载。因此应使用独立、非共享、非生产的集群,并在演练结束后清理资源:

make clean

若要保留数据库卷供后续复现实验,可使用项目文档说明的 KEEP_DATA=1;保留数据之前仍应确认测试数据不含敏感信息。

让实验结果能够重复,而不是只留下截图

RCA 的评测最容易被忽略的变量,是测试本身的可重复性。同一故障如果没有固定的开始、结束和证据采集规则,今天的结论可能只是负载偶然更高、采样恰好更完整,或后端查询缓存不同。建议为每次执行记录四类上下文:所用的仓库 commit、集群节点与资源配额、OTLP Collector/后端的采样配置,以及场景启用和关闭的时间。这样,告警延迟或 Agent 判断出现差异时,团队能先判断是产品回归还是实验条件变了。

还应把“通过”拆成三个层次。第一层是采集完整性:在网关、受影响服务、依赖和 Kubernetes 事件中都能找到足够的关联信号。第二层是定位质量:结论能准确指出故障机制,并引用锁等待、发布版本、DNS 延迟等原子证据。第三层才是行动建议:Runbook 是否给出安全的验证步骤、影响范围与回滚方向。把“说对了原因”和“建议直接改生产配置”混为一谈,会让演练的风险重新回到生产环境。

对于需要接入 AI 的平台,可以采用双盲方式:先隐藏场景名称,只提供正常权限范围内可见的 telemetry;让工具提交结论与证据,再与 expectedSymptoms 对照。之后再开放场景定义,分析它遗漏的信号或错误归因。这样既能测检索、关联和推理,也能避免 Agent 仅根据资源名称作答。

把它变成发布门禁,而非一次性演示

一次场景跑通之后,可以为团队建立更可重复的验收表:每个场景先定义预期症状、可接受的检测时间、应出现的证据和不应误报的候选根因。例如锁场景要求输出阻塞链而非“数据库负载高”;坏发布场景要求关联 deploy 事件和延迟变化;DNS 场景要求说明跨服务长尾的共同路径。

对于 AI 根因分析工具,还应保存它引用了哪些 trace、日志、指标和 Kubernetes 事件。结论正确但没有证据链,下一次换一个相似场景就无法判断它是在推理还是碰巧猜中。RCA-lab 的每个场景带有 expectedSymptoms,正好可以作为这类评测的最小 rubric:把期望信号转成自动检查项,而不是仅收集一段自然语言总结。

RCA-lab 的边界也很清楚:它提供的是一组有代表性的真实故障机制,不是对所有生产拓扑、采样策略和业务负载的替代。最合理的用法是先在这里发现盲点,再把同样的验收问题映射到自己的 staging 环境。这样,可观测性建设才能从“仪表盘看起来很全”走向“面对相互干扰的事故信号仍能给出可验证解释”。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。