告警系统搭建起来之后,真正的考验才刚刚开始。一个中等规模的Kubernetes集群加上周边的中间件,每天产生几百条告警并不罕见,但其中真正需要人介入处理的可能不到百分之五。如果所有告警都塞进同一个群里,用不了两周,大家就会对群消息免疫,等真正的生产事故发生时,反而没人第一时间响应。反过来,如果告警阈值卡得太死,又会漏掉一些隐患,等业务受损才被发现。本文围绕告警分级和值班响应流程这两个核心环节,给出一套可以直接落地的设计方案。

一、告警分级的核心:按影响面和紧急度划分,而不是按组件划分
很多团队在制定告警级别时容易犯一个错误:按被监控对象来分级,比如数据库的告警都算高级别,主机的告警都算低级别。这种方式看似清晰,实际上站不住脚。同样是数据库告警,主库宕机和一条慢查询统计波动,影响面完全不同;同样的主机CPU飙高,如果是承载核心交易的服务,情况就严重得多。
正确的分级维度应该是两个:影响面(影响多少用户、多少业务)和紧急度(还能撑多久)。业界通用的P0到P3四级划分可以直接沿用,关键是把每一级的判定标准写清楚、写具体,而不是停留在“严重”“一般”这种模糊描述上。一个可参考的定义方式如下。
- P0(灾难级):核心业务不可用,或数据面临丢失风险。例如生产集群API Server全部失联、主数据库主从同时异常、支付链路整体中断。要求立即电话呼叫值班人。
- P1(严重级):核心业务部分受损或有明确受损风险。例如某个可用区节点批量NotReady、主从切换失败进入单点状态、延迟显著超出SLO但仍可用。要求15分钟内响应。
- P2(一般级):非核心业务异常,或核心业务出现需关注的劣化趋势。例如某个非核心服务Pod频繁重启、磁盘使用率超过80%。要求工作时间处理,当日闭环。
- P3(提示级):不影响业务的运行状况提示。例如证书还有30天过期、镜像仓库存储缓慢增长。进入工单系统按周清理即可。
分级标准确定后,要落到监控系统里去执行。以Prometheus为例,可以在告警规则的labels中标注severity,后续Alertmanager按标签路由到不同的通知渠道。示例如下:
groups:
- name: kubernetes-alerts
rules:
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="false"} == 1
for: 2m
labels:
severity: P1
team: infra
annotations:
summary: "节点 {{ $labels.node }} 已处于 NotReady 状态超过2分钟"
runbook: "https://runbook.ipipp.com/node-not-ready"
- alert: DiskUsageHigh
expr: (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 > 80
for: 10m
labels:
severity: P2
team: infra
annotations:
summary: "节点 {{ $labels.instance }} 磁盘使用率超过80%"
这里有一个容易被忽视的细节:for字段的作用不只是降噪,它实际上参与了级别的判定。同样是节点NotReady,持续2分钟可能是P1,持续30秒就恢复则是P3级别的抖动记录。分级的粒度要结合业务容忍度来定,没有统一答案。
二、通知渠道与升级机制:让每条告警找到对的人
分级之后紧跟着的问题是:告警发给谁、通过什么渠道发、发了没人理怎么办。这三个问题缺一不可。渠道的选择要和级别强绑定,一个简单的原则是:级别越高,通知方式越具有强制性。P0用电话加短信加群消息三管齐下,P1用即时通讯工具的加急通知,P2发到值班群@值班人,P3汇总成日报。如果P2也打电话,值班人很快就会被骚扰到麻木,真正的高级别告警反而失去了电话的威慑力。
Alertmanager的路由配置可以直接体现这套策略,通过severity标签分流到不同的receiver:
route:
receiver: default
group_by: ["alertname", "cluster"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- match:
severity: P0
receiver: oncall-phone
repeat_interval: 5m
- match:
severity: P1
receiver: oncall-urgent
repeat_interval: 30m
- match:
severity: P2
receiver: team-chat
- match:
severity: P3
receiver: daily-report
receivers:
- name: oncall-phone
webhook_configs:
- url: "http://callcenter.ipipp.com/api/dial"
- name: oncall-urgent
webhook_configs:
- url: "http://alert-gateway.ipipp.com/api/urgent"
升级机制(Escalation)是通知环节的安全网。P0和P1告警必须在通知系统中配置多级升级:第一级通知当值工程师,超过指定时限未确认,自动升级到值班经理;再超时,升级到技术负责人甚至CTO。时限的设定建议是P0五分钟未确认即升级,P1十五分钟未确认即升级。升级不是追责,而是承认一个现实:值班人可能在睡觉、在通勤、在处理另一个故障,单点依赖任何一个人都是不可靠的。
此外要重视告警抑制和静默规则。发布窗口、计划内维护期间,应该提前配置silence规则,避免已知变更触发告警冲垮值班群。关联告警要做好抑制,比如宿主机宕机时,上面几十个Pod的告警应该被节点告警抑制掉,只报根因,否则一次故障就是一场告警风暴。
三、值班制度与响应流程:从接警到复盘的完整闭环
通知送达之后,事情才完成一半。值班响应流程要回答的是:值班人接到告警后按什么步骤行动、处理到什么程度算结束、事后如何沉淀。这套流程需要一份值班手册(Runbook)来承载。手册不要求大而全,但每类高频告警至少要包含四项内容:告警含义、影响判断方法、处置步骤、升级条件。以节点NotReady为例,Runbook应该写清楚先执行kubectl get nodes确认状态,再检查kubelet进程和宿主机资源,若确认硬件故障则走踢节点、迁移Pod、报修的三步流程,若十分钟内无法定位原因则升级求助。
轮班安排上,建议按周轮值,每周设置主值班和副值班两人。主值班负责一线响应,副值班在主值班处理超过时限或遇到不熟悉的领域时介入。轮值表要提前一个月公布,交接班时有固定的交接清单:当前未关闭的P1/P2告警、进行中的变更、已知风险项。交接不是发个消息了事,最好有十分钟的口头同步,把“为什么这条告警还没关”这类背景信息传下去,这类信息写进系统往往丢失严重。
响应的时效性要有明确数字并纳入度量。常见的SLA设定是:P0五分钟内确认、三十分钟内给出初步定位;P1十五分钟内确认、两小时内给出处置结论;P2当日处理完毕。确认(Ack)和处理(Resolve)是两个动作,值班人在群里回复“收到,正在看”就算确认,但只有故障恢复且根因有了初步结论才算处理完毕。这个区分能有效避免“点了确认就没下文”的常见问题。
最后是复盘环节。所有P0和P1事件必须在恢复后48小时内出复盘报告,重点不是追责,而是回答三个问题:监控为什么没更早发现(或为什么误报)、响应流程哪一步卡住了、同类问题如何避免。复盘产出的改进项要有责任人和截止时间,并在下次值班交接时回顾进度。如果一次故障暴露的监控盲区补上了对应的告警规则,那这次故障的价值就被兑现了;反之,同样的故障重复发生而告警体系毫无变化,说明复盘流于形式。
总结一下,告警分级解决的是“什么算重要”的判断问题,值班响应流程解决的是“重要的事如何被及时处理”的执行问题。两者合在一起,加上定期的告警有效性回顾(建议每月统计一次各级告警量、确认率、误报率,清理三个月内从未被处理过的告警),才能让监控体系持续保持可信,让值班不再是苦差事,而是团队守护系统稳定性的常规动作。