从零给存算分离 Doris 建观测:两级分诊与 12 条告警
英文版:English
起点:什么都没有,而且这个平台是悄悄坏的
我接手时,存算分离 Doris 没有大盘,也没有告警。对一个还没上线的平台这很正常,但这个平台的故障模式大多是静默的:计算组能缩到零,元数据放在一个独立服务里、底下是分布式 KV,副本数由一个控制面组件决定。这套东西大部分坏法不会报错,只会让某个池子悄悄停止干活。
建设过程中的三次真实事故定下了设计目标,因为每一次都拖了很久才被发现:
- 预热任务指向一个已被删除的计算组,持续失败 35 小时。
- 平台 CI 覆盖了计算平台的状态,反复 5 次,才有人把这几次连起来。
- 元数据存储唯一的健康信号冻结了 16 天,面板上一直是绿的。
这三件事在延迟或错误率面板上都看不出来,这个观察决定了后面所有设计。
大盘:两级分诊,而不是一整面墙
三份大盘,共 115 个面板,每份只回答一个问题。
| 大盘 | 面板数 | 回答的问题 |
|---|---|---|
| Summary | 31 | 有没有坏?坏在哪一层? |
| Details | 60,分 13 个分区 | 这一层里具体是哪、为什么? |
| Autoscaler 健康 | 24 | 控制面还活着吗?有没有在决策、在动作? |
组织原则是两级分诊。Summary 的读法是:被叫醒、什么上下文都没有的人一分钟内能看完。它按层排,第一屏就已经缩小了搜索范围。Details 沿同样的思路分成 13 个分区,从 Summary 下钻,落到的是一个有名字的分区,而不是在 60 张图里翻。Autoscaler 单独一份,因为它的故障性质不同:它坏的时候,其他面板可以全绿,容量却已经不再跟随需求。
代价是面板数量比谁都不想读的多。我接受这个代价,因为 Details 是查表用的,不是拿来盯的,事故中少一个面板的代价远大于多一个。
要说清的边界:大盘已部署,每个面板的查询都与源 JSON 逐条核对过,但数据来自 preprod 和 sandbox 环境,也没有逐个面板做目视渲染检查。它们没经过生产流量形态的检验。
告警:27 条候选,留 12 条
我先写了 27 条候选规则,每条表达式都在 VictoriaMetrics 里用真实指标验证过,然后砍掉 15 条。筛选标准只有一句:只保留能抓住「静默失效」或「不可逆」故障的规则。 人几分钟内本来就会发现的、或者只是已被覆盖问题的症状,一律推迟。
留下的 12 条分三组:
- 可用性(4 条)。 各池常驻的头部 backend、frontend 和元数据服务,以及一条查询错误率规则,它被前三条抑制,一次故障只出一条告警,而不是一场风暴。
- 控制面(4 条)。 autoscaler tick 停摆、tick 序列整个消失、做了扩缩决策却没有动作、副本写入失败。5 次覆盖和 35 小时那两件事,本该由这组规则抓住。
- 元数据安全(4 条)。 分布式存储容错余量耗尽、协调器不可达、指标消失、delete bitmap 失败计数。「指标消失」这条是为那 16 天写的。
每条规则都配了对自身静默的对冲。「指标消失」和「tick 序列消失」是关于监控本身失明的规则:依赖一个已经消失的序列的告警永远不会触发。这是冻结的健康信号教给我的:一条永远绿的线,不是健康的证据。
目前这些规则不会 page 任何人,只路由到一个没有 oncall 的测试频道,上生产时再升级成 page。路由用一个小模拟器验证:把 9 组非 Doris 标签在改动前后各回放一遍,确认原有路由没有移动。
这件事不是什么
标题写的是观测,读者容易默认更多,所以把范围说准:
- 12 条规则是设计,不是已部署。变更还在评审。生产上触发过的告警数:按构造就是 0。
- 它们不是 SLO burn-rate 告警。它们防的是静默失效和不可逆故障,这个集合比延迟目标窄,但我认为更要紧。查询延迟的 SLI/SLO 层还没建,我宁愿直说,也不把这些规则改名去凑数。
- 没跑
amtool check-config,也没做变异测试(故意把东西弄坏、看规则会不会响)。表达式用真实数据验证过,触发行为没有端到端验证。
我能辩护的部分
从 27 砍到 12 才是有价值的工作。写 27 条告警一个下午就够,判断其中 15 条只会教大家无视这个频道,花的时间更长,也是能迁移的部分。「对静默和不可逆报警,并让每条规则带一个对自身失明的检查」这条设计原则,是把三次事故倒着读出来的,不是套模板得来的。