4、告警路由与通知:告警路由规则设计、通知渠道配置(邮件/钉钉/企微/短信)、值班表与升级策略、告警静默与抑制

告警路由与通知,说白了就是解决两个问题:告警该发给谁?怎么发?

我见过不少团队,告警规则写得挺漂亮,结果一到半夜,所有人手机都被震醒。或者反过来,核心服务挂了,值班同学却浑然不知。嗯,这里面的坑,我踩过不少。

4.1 告警路由规则设计

告警路由,就是给告警找个“对的人”。

我个人习惯,把路由规则分成三层:

  • 第一层:按服务归属 —— 数据库告警走DBA,网络告警走网络组。
  • 第二层:按告警级别 —— P0/P1必须立刻通知人,P3/P4可能只写个日志。
  • 第三层:按业务标签 —— 比如“支付链路”的告警,要同时抄送业务负责人。

举个例子,一个典型的告警路由配置(YAML格式):

routes:
  - match:
      service: "mysql"
      severity: "critical"
    receiver: "dba-oncall"
  - match:
      service: "nginx"
      severity: "warning"
    receiver: "ops-group"
  - match_re:
      service: "payment.*"
    receiver: "payment-team"

核心原则:路由规则要尽量精确,避免“广播式”通知。我曾经见过一个团队,所有告警都发到一个群,结果重要告警被刷屏淹没了。

4.2 通知渠道配置

不同的渠道,有不同的适用场景。我整理了一张表,你一看就明白:

渠道 适用场景 优点 缺点
邮件 非紧急告警、日报、周报 信息完整,可追溯 延迟高,容易被忽略
钉钉/企微 日常告警、团队协作 实时性好,支持交互 消息容易被刷屏
短信 P0/P1 紧急告警 强制提醒,几乎无延迟 成本高,信息量有限
电话 核心服务宕机、严重故障 最高优先级,无法忽略 成本最高,容易疲劳

配置示例(以Prometheus Alertmanager为例):

receivers:
  - name: "ops-group"
    email_configs:
      - to: "ops@company.com"
    webhook_configs:
      - url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
  - name: "dba-oncall"
    pagerduty_configs:
      - routing_key: "xxx"

我的建议:不要把所有渠道都打开。我习惯的做法是:P3/P4走邮件,P2走钉钉群,P0/P1走短信+电话。这样既不会漏告警,也不会过度打扰。

4.3 值班表与升级策略

值班表,就是解决“谁来处理”的问题。升级策略,则是解决“处理不了怎么办”的问题。

我曾经在一个项目里,凌晨3点收到一个P0告警,结果值班同学是新来的,搞不定。等他把问题转给资深工程师,已经过去了20分钟。嗯,这就是升级策略没设计好。

一个典型的升级策略:

  1. 第一级:值班工程师(响应时间 < 5分钟)
  2. 第二级:服务Owner(响应时间 < 15分钟)
  3. 第三级:技术经理(响应时间 < 30分钟)

配置示例(使用PagerDuty或类似工具):

escalation_policies:
  - name: "critical-escalation"
    rules:
      - target: "on-call-engineer"
        delay: 0
      - target: "service-owner"
        delay: 15m
      - target: "tech-manager"
        delay: 30m

注意:升级策略不是越复杂越好。我见过一个团队,升级了5层,结果最后一层是CTO。你想想看,CTO半夜被叫起来,能解决什么问题?

4.4 告警静默与抑制

告警静默,就是主动屏蔽某些告警。告警抑制,则是自动避免重复告警。

静默的场景:

  • 计划内维护(比如凌晨升级数据库)
  • 已知的临时问题(比如某个依赖服务正在重启)
  • 测试环境告警

抑制的规则:

  • 如果某个服务挂了,那么它下游的所有告警都应该被抑制
  • 如果已经有人确认了告警,那么相同告警不再重复发送

举个例子:

inhibit_rules:
  - source_match:
      severity: "critical"
    target_match:
      severity: "warning"
    equal: ["alertname", "instance"]

silences:
  - matchers:
      - alertname = "DiskSpaceLow"
      - instance = "db-01"
    startsAt: "2024-01-01T00:00:00Z"
    endsAt: "2024-01-01T06:00:00Z"
    comment: "计划内维护"

避坑指南:我曾经因为静默配置写错了时间范围,导致一个P0告警被静默了整整一天。所以,静默一定要设置明确的开始和结束时间,并且要有审批流程。

最后说一句:告警路由和通知,不是一锤子买卖。你需要根据实际效果不断调整。比如,某个渠道的告警总是没人响应,那就得考虑升级或者换渠道。说白了,这是一个持续优化的过程。

我的习惯:每个月复盘一次告警通知的响应情况。看看哪些告警被忽略了,哪些渠道效果不好,然后调整路由规则和升级策略。这样,告警系统才能真正帮到你,而不是成为负担。