概述
凌晨三点,手机震了。你看了一眼——P1 告警,订单服务 5xx 错误率飙升。爬起来,开电脑,拉日志,查 Grafana,定位到是上游数据库连接池打满。重启、扩容、恢复,一看表四点半了。第二天早上你顶着黑眼圈开会,会上有人说"昨晚那个告警其实是误报"。
这种感觉,干过运维的人都懂。
On-Call(值班响应)是 SRE 工作中绕不开的一环。但很多团队的 On-Call 做成了"谁被叫醒谁处理",没有轮值,没有备份,没有交接,更没有疲劳管理。结果是:核心工程师离职,告警群形同虚设,故障响应越来越慢。
这篇文章聊聊 On-Call 排班设计中的 7 个工程决策。不是理论框架,是我这些年从 0 到 1 搭建 SRE 值班体系时踩过的坑、做过的取舍。在之前的事件管理与 On-Call 机制设计中讲过事件响应流程,本文聚焦在"排班本身怎么设计"——轮值周期、主备机制、告警分级、疲劳量化、交接班、新人上岗、补偿与度量。
如果你是刚接手 SRE 团队的技术负责人,或者正在被无序的值班制度折磨,这篇文章应该能帮你少走半年弯路。
一、On-Call 到底在解决什么问题
先说清楚 On-Call 是干嘛的,再说怎么设计。
On-Call 的本质是:在非工作时间,系统出问题时,有人能第一时间响应并恢复。
打个比方:医院急诊科不能晚上关门。医生白天上班,晚上也得有人值班。但值班的医生不是同一个人连值一周不睡觉——那第二天手术手抖就出医疗事故了。所以医院有轮班制度:白班、夜班、备班,轮着来,保证每个班次的医生都是清醒的。
On-Call 的逻辑一样。你的系统 7x24 小时跑着,但工程师不能 7x24 小时盯着。On-Call 排班就是让"正确的人在正确的时间收到告警",而不是"所有人都收到告警"或者"没人收到告警"。
Google SRE 的 On-Call 原则
Google SRE 在《Google 运维解密》里用三个章节讲 On-Call,核心原则就一条:琐事不能超过工作时间的 50%。
什么是"琐事"(Toil)?Google 的定义是:重复的、可自动化的、战术性的、没有持久价值的工作。比如手动重启服务、手动扩容、手动查日志定位问题——这些都是琐事。On-Call 是琐事最大的来源之一。
一个 SRE 至少要花一半时间做工程项目(写代码、做工具、改架构),否则就是在用人力填系统的坑,越填越深。要保证这个比例,团队至少需要 6-8 人轮值——人少了轮不过来,工程时间被值班吃光。
Google SRE 的 on-call 方法和工具 这篇文章里有一个很清晰的分析:Google 通过 Outalator 工具管理告警的全生命周期,包括聚合、标签、分析、交接报告,让 On-Call 不只是"被叫醒",而是"被管理"。Outalator 的核心功能包括:
- 告警聚合:多个相关告警合并成一个"故障",减少重复通知
- 加标签:给故障打标签,方便按维度筛选和统计
- 数据分析:从团队、个人、服务、机房等维度分析告警趋势
- 一键生成交接报告:选择一批故障,自动生成邮件格式的交接文档
国内团队很难完全照搬 Google 的做法——文化、团队规模、补贴机制都不同。但工具和流程可以先学起来。
On-Call 的四个核心问题
一套高效的 On-Call 制度至少要回答四个问题(参考快猫星云的 On-Call 实践):
- 谁负责——当前值班人是谁,备份是谁
- 什么时候负责——轮值周期和时间段怎么划分
- 如何通知——告警通过什么渠道推送到值班人
- 无人响应时怎么办——升级策略和兜底机制
这四个问题对应的就是下面要讲的 7 个工程决策。
二、7 个工程决策
决策1:轮值周期——一周还是一天
排班的第一个问题:多久轮一次?
这个问题看起来简单,但选错了影响很大。轮得太频繁,交接成本高,信息断档;轮得太久,值班人疲劳累积,第二周基本是强撑。
| 轮值周期 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 日轮(每天换人) | 负担分散,没人连续熬夜 | 交接频繁,上下文丢失 | 团队 >15 人 |
| 周轮(每周换人) | 上下文连续,交接成本低 | 周末连续值班,较疲劳 | 团队 6-10 人 |
| 双周轮(两周换人) | 上下文最完整 | 连续两周压力大,疲劳累积 | 团队 8-12 人,系统复杂 |
我推荐周轮。 原因很简单:日轮的交接成本太高。你刚搞清楚昨天那个间歇性超时是什么原因,今天就换人了,明天新人又得从头查。而双周轮对个人压力太大——连续两周随时待命,第二周基本是强撑。
在我之前带的一个 8 人 SRE 团队里,我们试过三种周期。日轮试行了两周就放弃了——每天交接花 20 分钟,信息还经常断档。值班人刚搞清楚一个反复出现的告警的上下文,第二天换人又得从头看。周轮是最终选择:周一早上交接,上周末的遗留问题当周一优先处理项,过渡比较自然。
轮值周期选择的决策框架:
团队人数 < 5 人 → 不建议正式 On-Call,用"谁开发谁负责"模式
团队人数 5-8 人 → 周轮,每人 1-2 周/月
团队人数 8-15 人 → 周轮或日轮,根据告警量决定
团队人数 > 15 人 → 日轮,配合多时区覆盖
踩坑提醒:轮值周期不是一成不变的。业务高峰期(比如电商双十一、物流旺季),可以临时缩短为日轮,让值班负担更分散。高峰期过了再切回周轮。
另一个容易忽略的点:周五到周日这三天是最难扛的。周五晚上出问题,周末两天都在处理,周一还要正常上班。我建议在排班时,周末单独排一个"周末值班人",和工作日值班人分开。这样工作日值班人周五下班就解放,周末值班人周一到周四正常做项目。8 人团队的话,每周 2 人值班(1 个工作日 + 1 个周末),每人两周轮一次,压力可控。
决策2:主备机制——别让一个人扛
“主值班人”(Primary)收到告警后处理,但如果 Primary 没响应呢?必须有"备份值班人"(Secondary)。
这就像飞机的正副驾驶。正驾驶操控,副驾驶监控和备份。正驾驶要是突发状况处理不过来,副驾驶随时接管。只有一个飞行员的飞机不是不能飞,但出了事没人兜底。
主备设计的核心规则:
- Primary 负责所有 P1/P2 告警的首响应
- Secondary 在 Primary 5 分钟内未响应时自动接管
- Secondary 不处理 P3/P4 告警(那些等白天上班处理就行)
- Primary 和 Secondary 不能是同一个人(废话,但真有团队这么干过)
- Primary 和 Secondary 最好不在同一个物理位置(防止同时断网)
用 PagerDuty 或 Opsgenie 配置升级策略时,大概长这样:
# PagerDuty 升级策略示例(YAML 格式,概念性配置)
escalation_policy:
name: "订单服务-生产环境"
levels:
- level: 1 # 第一层:主值班人
targets:
- user: "primary-oncall-user"
delay_minutes: 0 # 立即通知
- level: 2 # 第二层:备值班人(5分钟未响应升级)
targets:
- user: "secondary-oncall-user"
delay_minutes: 5
- level: 3 # 第三层:技术负责人(15分钟仍未响应)
targets:
- user: "tech-lead"
delay_minutes: 15
- level: 4 # 第四层:CTO/运维总监(30分钟灾难级)
targets:
- user: "ops-director"
delay_minutes: 30
每层之间的延迟时间是关键。5 分钟给 Primary 响应时间是合理的——如果在洗澡,5 分钟够擦干手接电话。但如果 Primary 在深睡状态没听到手机响,5 分钟后 Secondary 就该被叫醒了。
实测数据:我们团队推行主备机制后,告警漏响应率从 3.2% 降到 0.1% 以下。之前没有 Secondary 的时候,Primary 如果恰好在上厕所、在洗澡或者手机静音了,告警就石沉大海。加了 Secondary 后,5 分钟内必有人响应。
一个反直觉的发现:Secondary 不是越多越好。我见过一个团队配了 3 个 Secondary,结果 P1 告警一出来,4 个人同时被叫醒,3 个人都在等"其他人先处理"。主备的核心是"明确责任人",不是"人多力量大"。一个 Primary + 一个 Secondary 足够,再多就是浪费。
关于升级策略的更多设计思路,可以参考告警策略设计:从噪声到信号这篇文章,里面讲了告警路由和抑制的完整方案。
决策3:告警分级——不是所有告警都值得叫醒人
这是最容易被忽视的决策,也是影响最大的一个。
我见过一个团队,Prometheus 配了 400 条告警规则,全部 PagerDuty 推送。结果值班工程师一晚上被叫醒 8 次,其中 6 次是"磁盘使用率超 80%“这种不紧急的告警。一个月后,这个工程师提了离职。
告警必须分级。这就像医院的分诊台:心跳骤停的进抢救室,感冒发烧的在候诊区等着。如果把所有病人都送进抢救室,真正的急诊病人反而得不到及时救治。
四级告警体系:
| 级别 | 含义 | 通知方式 | 响应时限 | 示例 |
|---|---|---|---|---|
| P1 | 核心服务不可用 | 电话+短信+IM | 立即 | 订单服务 5xx >10% |
| P2 | 核心服务降级 | 短信+IM | 5 分钟 | 数据库连接池 >80% |
| P3 | 非核心服务异常 | IM 群通知 | 上班处理 | 某测试环境宕机 |
| P4 | 容量预警 | 日报邮件 | 3 天内处理 | 磁盘使用率 75% |
只有 P1 和 P2 才触发 On-Call 告警。 P3 和 P4 走工单或者邮件,不推送电话。
这个分级带来的变化是巨大的。我们之前日均告警量 300+ 条,全部推送到值班手机。做分级后,真正触发电话的 P1/P2 告警日均降到 15-20 条。值班工程师的夜间唤醒次数从平均每晚 4 次降到不到 1 次。
告警分级的实施步骤:
- 盘点现有告警:导出所有告警规则,逐条标注 P1-P4
- 修改通知路由:P1/P2 走电话推送,P3/P4 走邮件或 IM 群
- 设置过渡期:先观察 1 周,看有没有被分错的告警
- 定期复审:每月检查一次,是否有 P3/P4 告警应该升为 P1/P2,或者反过来
一个判断技巧:问自己一个问题——“如果这条告警在凌晨 3 点触发,我愿不愿意被叫醒?“如果不愿意,它就不是 P1/P2。
这背后的逻辑是:告警的价值不取决于数量,取决于信噪比。 300 条告警里如果 280 条是噪音,值班人会在第 10 条开始就忽略所有告警——包括真正重要的那 20 条。这就是"告警疲劳”(Alert Fatigue),PagerDuty 的 Going On-Call 指南专门用了一章讲这个问题。
告警降噪的 3 个实操方法:
聚合相关告警:同一个服务的 CPU、内存、磁盘告警,如果同时触发,聚合为一条"某服务资源异常"通知。Google Outalator 的核心功能之一就是这个。Prometheus 可以用 Alertmanager 的
group_by配置实现。设置告警抑制规则:如果 P1 告警已触发(比如"数据库宕机”),与之相关的下游告警(比如"订单服务报错"“支付服务超时”)自动抑制。因为下游报错是上游宕机的必然结果,不需要重复通知。
基于 SLO 的告警替代基于阈值的告警:与其配"CPU >80% 告警”,不如配"错误预算消耗 >50% 告警"。SLO 告警直接关联用户体验,噪音天然更少。
关于 SLO 告警的设计方法,可以参考之前的 SLO 相关文章。告警治理是一个持续工程,不是一次性配置就完事的。
决策4:疲劳量化——用数据决定什么时候该休息
“我感觉快扛不住了”——这话在复盘会上说了无数次,但管理者很难凭感觉做决策。需要用数据量化疲劳。
为什么需要量化:
管理者的常见误区是"觉得值班没什么大不了"——不就是在家里等电话吗?但研究表明,夜间被中断睡眠后,第二天的认知能力相当于醉酒状态(血液酒精浓度 0.1%)。连续一周被叫醒 3 次以上的工程师,判断力和反应速度会显著下降。这不是"扛一扛就过去"的事,是实打实的生理损耗。
5 个核心度量指标(参考 Google SRE 的 Outalator 设计):
| 指标 | 含义 | 健康阈值 | 异常阈值 | 数据来源 |
|---|---|---|---|---|
| 每班告警量 | 一个值班周期收到的告警总数 | <30 条/周 | >50 条/周 | PagerDuty/Opsgenie 统计 |
| 夜间唤醒次数 | 22:00-08:00 被电话叫醒的次数 | <2 次/周 | >4 次/周 | 通话记录 |
| MTTA | 告警发生到响应的平均时间 | <3 分钟 | >8 分钟 | 告警平台日志 |
| 降噪比 | 聚合后告警数 / 原始告警数 | >5:1 | <2:1 | Alertmanager 统计 |
| 响应比 | 被认领的告警 / 总告警 | >80% | <50% | On-Call 平台 |
怎么用这些数据:
每周复盘会上,看这些指标的趋势。不是看绝对值,看趋势——如果某周的告警量突然比前一周翻了 3 倍,就算绝对值没超阈值,也要引起警觉。
如果某个值班人的夜间唤醒次数连续两周超过 4 次,说明告警质量有问题(噪音太多)或者系统不稳定(频繁出故障),需要立即干预:
- 告警噪音多 → 暂停该值班人的 On-Call,花一周时间治理告警
- 系统不稳定 → 拉开发团队一起排查根因,不能让 SRE 一直当救火队员
一个真实案例:我们团队有个工程师连续两周夜间唤醒 6 次和 7 次。我一看数据,发现问题不在告警——而是某个微服务的内存泄漏导致每天凌晨 2 点准时 OOM 重启。修了那个 bug 后,唤醒次数直接降到 0。如果不看数据,只会以为是"告警配多了"或者"这个人运气差"。
度量看板搭建:
用 Grafana 搭一个 On-Call 健康看板,数据源接 PagerDuty API 或 Alertmanager。看板包含以下面板:
# 每日告警量趋势
sum by (day) (alertmanager_notifications_total{integration="pagerduty"})
# 夜间告警占比(22:00-08:00)
sum(rate(alertmanager_notifications_total{integration="pagerduty"}[1h] offset 2h))
/
sum(rate(alertmanager_notifications_total{integration="pagerduty"}[1h]))
# MTTA 趋势
avg_over_time(pagerduty_incident_acknowledge_seconds[7d])
# 降噪比(聚合前/聚合后)
sum(alertmanager_alerts_firing_total)
/
sum(alertmanager_notifications_total{integration="pagerduty"})
看板每周一早上过一次,花 5 分钟就能判断上周的 On-Call 健康度。如果发现异常趋势,当天的站会上就讨论。
关于 MTTR 优化的更多实战经验,可以看MTTR 从 40 分钟到 8 分钟这篇文章,里面有完整的故障定位提速方案。
决策5:交接班——信息不能断在梦里
交接班是 On-Call 中最容易被忽略的环节。
想象这个场景:周一早上,上一周值班的人休假了,你这周接值班。昨晚凌晨 3 点他处理了一个数据库慢查询的告警,改了一个参数。你不知道。今天下午系统又慢了,你查了半天才发现昨晚改过的参数有问题——改错了方向,临时调大的连接数反而加重了数据库负担。
如果有一份交接文档,你 5 分钟就能知道昨晚改了什么、为什么改、有什么风险。没有交接文档,你可能要花 30 分钟从头排查。
交接班必须做三件事:
- 写交接文档:昨天处理了什么、改了什么配置、有什么遗留问题
- 口头过一遍:周一早上 15 分钟站会,当面交接关键事项
- 更新 Runbook:如果处理过程中发现了新的排障步骤,补到 Runbook 里
交接文档模板:
# On-Call 交接文档 (2026-08-19 ~ 2026-08-25)
## 本周告警统计
- P1 告警: 3 条 (均已恢复)
- P2 告警: 12 条 (均已恢复)
- 夜间唤醒: 2 次
## 重要事件记录
### 2026-08-22 03:15 - 订单服务 5xx 飙升
- 原因: MySQL 连接池打满 (max_connections=500, 实际连接 498)
- 处理: 临时调大 max_connections 到 800, 重启订单服务
- 遗留: 需要排查为什么连接数突增, 已提工单 #2026-0822-001
- 注意: max_connections 调到 800 是临时方案, 周二开发团队会排查根因
### 2026-08-23 14:30 - Redis 集群节点 3 超时
- 原因: 网络抖动, 节点 3 与主节点心跳超时
- 处理: 自动 failover 切换到副本, 业务无感知
- 遗留: 节点 3 恢复后需要手动检查数据一致性
## 遗留问题
1. Redis 集群节点 3 偶发超时 (已开 ticket, 待网络团队排查)
2. 告警规则 "order_service_latency_p99" 阈值偏低, 建议从 200ms 调到 300ms
3. MySQL 连接数突增根因待查 (工单 #2026-0822-001)
## 建议关注
- 本周 P2 告警集中在订单服务, 建议开发团队排查上游调用方
- Grafana "订单服务概览" 看板新增了连接池使用率面板, 值得看看趋势
关键原则:交接文档不是写给别人看的,是写给未来的自己看的。因为两周后你可能又轮到值班,到时候你得靠这份文档回忆"上次那个连接池问题后来怎么样了"。
交接文档的 3 个纪律:
- 时效性:每次处理完 P1/P2 事件,立即写 3 行记录。不要等周末一起写——到那时候你已经忘了细节
- 可操作性:遗留问题必须附带工单号或者 ticket 链接,不能只写"有个问题待查"
- 简洁性:每条记录控制在 5 行以内。交接文档不是故障报告,是备忘录
如果团队用飞书或钉钉协作,交接文档可以直接放在共享文档里,每周一自动提醒值班人查看。用 Slack 的话可以用 PagerDuty 的 Handoff 功能,自动生成交接摘要。
决策6:新人上岗——从影子到独立
新工程师能不能直接上 On-Call?不能。
我见过一个团队,新人入职第二周就被排进值班表。结果第一天值班就遇到了数据库主从切换的故障,新人完全不知道怎么办——不知道主从切换的命令是什么,不知道切换后要检查什么,不知道该找谁帮忙。告警升级到技术负责人时已经过了 20 分钟。那次故障从 P1 变成了 P0。
新人上岗三阶段(参考 Rootly 的 On-Call 指南):
| 阶段 | 时间 | 角色 | 做什么 | 考核标准 |
|---|---|---|---|---|
| 影子期 | 第 1-2 周 | 观察者 | 跟着当前值班人,看告警怎么处理,不直接操作 | 能复述 3 个常见告警的处理流程 |
| 反向影子期 | 第 3-4 周 | 执行者 | 新人主导处理,老值班人监控和兜底 | 独立处理 5 个 P2 告警无失误 |
| 独立期 | 第 5 周起 | 值班人 | 独立值班,遇到搞不定的按升级策略找人 | 通过模拟故障考核 |
影子期就像学开车时坐在副驾看教练操作。新人不用动手,但要跟着值班人一起看告警、一起拉日志、一起查问题。重点是理解"告警来了第一步干什么"——先看 Grafana 哪个面板、先查哪个服务的日志、先问谁了解上下文。
影子期的具体安排:
- 每天 30 分钟跟着值班人回顾当天告警
- 阅读所有 P1/P2 事件的复盘文档
- 熟悉告警平台、日志平台、监控看板的基本操作
- 通读团队 Runbook,标记看不懂的地方
反向影子期是新人开始动手了,但老值班人坐在旁边盯着。新人处理告警、改配置、做回滚,老值班人只在要出事的时候喊停。这个阶段新人会犯错——没关系,在可控范围内犯错是最好的学习方式。
反向影子期的关键规则:
- 新人处理 P2 告警,老值班人处理 P1(P1 风险太高,不能让新人练手)
- 新人做的每个操作(重启、改配置、扩缩容)必须口头汇报,老值班人确认后才执行
- 每次处理完,花 5 分钟复盘:哪里做得好、哪里慢了、哪里可以改进
独立期开始前,新人需要通过一个考核:能独立处理 3 个最常见的告警场景(比如服务重启、数据库切换、流量切换)。考核方式是模拟故障注入——找个测试环境,注入故障,看新人能不能按 Runbook 走完整个流程。
一个踩坑教训:我们团队曾经让一个新人在反向影子期就直接处理 P1 告警。结果新人在重启服务时执行了 kubectl delete pod 而不是 kubectl rollout restart,导致服务短暂中断。虽然有老值班人在旁边盯着,但新人紧张到没听清指令。后来我们改了规则:反向影子期只处理 P2,P1 必须老值班人主导。
决策7:补偿与度量——让 On-Call 可持续
最后一个决策,也是最难推动的:On-Call 补偿。
On-Call 意味着你的个人时间被随时打断。凌晨被叫醒、周末不能出远门、看电影到一半得掏电脑。如果没有合理的补偿,工程师会用脚投票——离职。
三种补偿模型:
| 模型 | 方式 | 优点 | 缺点 | 适合 |
|---|---|---|---|---|
| 固定补贴 | 每月固定金额 | 简单易行,管理成本低 | 与实际工作量无关,忙的人吃亏 | 小团队,告警量低 |
| 按次补贴 | 每次夜间响应给固定金额 | 相对公平,多劳多得 | 可能鼓励不必要的响应 | 中等团队 |
| 调休+补贴 | 夜间响应 1 次换 0.5 天调休 + 固定补贴 | 最人性化,保证休息 | 调休管理复杂 | 成熟团队 |
我推荐第三种。在某出行项目里,我们实行的是"夜间每次 P1/P2 响应换半天调休 + 月度 2000 元 On-Call 补贴"。效果很好:工程师不会觉得"被白嫖",调休也保证了响应后的休息时间。关键是调休要在 30 天内休完,不能攒着——疲劳补偿的时效性很重要,拖一个月就失去意义了。
补偿设计的 3 个原则:
- 覆盖夜间:白天的 On-Call 是正常工作的一部分,不需要额外补偿。夜间(22:00-08:00)的响应才是额外付出
- 按响应次数而非告警次数:一次事件可能触发 10 条告警,但值班人只处理了一次。按告警次数算补贴会导致告警聚合后补贴缩水
- P1 和 P2 区别对待:P1 响应的补偿应该高于 P2,因为 P1 通常意味着更长的处理时间和更大的精神压力
团队健康度量:
除了前面说的 5 个告警指标,还需要跟踪团队层面的健康信号:
| 指标 | 含义 | 健康状态 | 异常状态 |
|---|---|---|---|
| 轮值公平性 | 每个人的年值班次数差异 | <15% | >25% |
| 离职率 | On-Call 工程师 vs 非 On-Call 离职率 | 持平 | On-Call >非 On-Call |
| On-Call 满意度 | 季度匿名问卷(1-5 分) | >3.5 | <3.0 |
| 工程时间占比 | On-Call 工程师的工程时间比例 | >50% | <40% |
| 平均值班周期 | 从开始值班到离职/转岗的时间 | >12 个月 | <6 个月 |
PagerDuty 的研究指出,一个因 On-Call 疲劳离职的工程师,替换成本高达 30 万美元(约 200 万人民币)。这还不包括知识流失和团队士气下降的隐性成本。所以,在补偿上省钱是最短视的决策。
季度 On-Call 满意度调查模板:
1. 过去 3 个月,你平均每周被夜间唤醒几次?
2. 你觉得当前的轮值周期是否合理?
3. 告警质量如何?(1-5 分,5 分最好)
4. 交接文档对你有帮助吗?
5. 你是否曾因 On-Call 考虑过离职?
6. 你对当前补偿方案满意吗?(1-5 分)
7. 你有什么建议改善 On-Call 体验?
问卷每季度发一次,匿名提交。低于 3 分的项目需要制定改进计划。
三、生产环境踩坑实录
讲几个真实踩坑,每个都是血泪教训。
坑1:告警不分级,全员 On-Call
之前在某电商平台,所有 Prometheus 告警都推到钉钉群。群里 20 个人,每次告警弹出来,所有人都看一眼然后等别人处理。心理学上叫"旁观者效应"——人越多,每个人越觉得"总有人会处理的"。
结果:P1 告警平均响应时间 12 分钟。有一次数据库主库挂了,群里 20 个人都在等别人先动,7 分钟后才有第一个工程师开始查。
后来改成只有值班人收到告警,其他人只看周报。告警响应时间从平均 12 分钟降到 2 分钟。
教训:On-Call 的核心是"明确责任人"。告警群不是 On-Call,是甩锅群。
坑2:没有交接文档,同一个问题查两遍
有一次数据库慢查询告警,周一值班人查了 30 分钟找到是某条 SQL 没走索引。他加了索引,恢复了。但没写交接文档。周三另一个值班人又遇到了同样的问题——因为那条 SQL 的执行计划在数据量变化后又变了。又查了 30 分钟。
后来我们强制要求:每次 P1/P2 事件处理完,必须写 3 行交接记录。就 3 行:什么问题、怎么处理的、有什么遗留。执行了一个月,重复排查率降了 70%。
教训:交接文档的 ROI 是所有 On-Call 工程中最高的。3 行字省 30 分钟排查时间,投入产出比 1:600。
坑3:新人直接上值班,遇故障手忙脚乱
上面提过了。后来我们定了规矩:入职 4 周内不排独立值班,必须走完影子→反向影子→独立三阶段。
教训:新人不是资源,是投资。前 4 周的"不值班"不是浪费,是在培养一个能独立值班的工程师。急功近利地把新人扔进值班表,出了事新人背锅,团队背更大的锅。
坑4:周末值班和工作日值班是同一个人
连续值 7 天班的工程师,到周日基本处于"半废"状态。有一次周日傍晚 P1 告警,值班工程师响应了但处理速度明显比平时慢——事后复盘发现他已经连续被叫醒 3 天,判断力下降。
后来我们把工作日值班和周末值班分开,各排一个人。周末值班人周一到周四做项目,周五下班接值班到周一早上交还。工作日值班人周五下班就解放。
教训:连续值班超过 5 天,人的认知能力会显著下降。别考验人性,用制度保护人。
四、工具选型建议
On-Call 排班管理工具,市面上主要有三类:
| 工具 | 特点 | 价格 | 推荐场景 |
|---|---|---|---|
| PagerDuty | 功能最全,生态最好,全球领导者 | $21-$41/人/月 | 预算充足,英文环境 |
| Flashduty | 国内适配好,支持钉钉/飞书/企业微信 | 按需定价 | 国内团队,中文环境 |
| Opsgenie | Atlassian 生态,与 Jira 集成好 | $9-$25/人/月 | 已用 Atlassian 全家桶 |
| 自建 | 完全可控,零许可费 | 开发+维护成本高 | 有开发能力的大型团队 |
我的建议:
- 团队 <5 人:别折腾,用飞书/钉钉群 + 轮值表格就够了。工具的 overhead 比收益还大。
- 团队 5-15 人:上 Flashduty 或 PagerDuty,重点用排班和升级策略功能。这个阶段手动排班的协调成本开始显现。
- 团队 >15 人:必须上专业工具。手动排班的协调成本会吃掉一个人全职工作量。多时区覆盖更是离不开工具。
选型时的 3 个关键问题:
- 告警源兼容性:你的监控系统是 Prometheus、Zabbix、Datadog 还是自研?确保工具能直接接入你现有的告警源
- 通知渠道:团队用钉钉、飞书、企业微信还是 Slack?通知渠道不匹配会导致告警发不出去
- 排班灵活度:能否支持主备轮值、跨时区排班、临时调班?有些工具只支持简单的轮值表
我曾经自研过一套 Go On-Call 排班系统,功能包括轮值日历、告警路由、升级策略、交接报告自动生成。开发花了 3 周,后来发现 Flashduty 的功能覆盖了 90% 的需求。如果你的核心业务不是做 On-Call 工具,别自建——把时间花在治理告警和写 Runbook 上,回报更高。
五、从 0 到 1 搭建 On-Call 体系的行动清单
如果你的团队还没有正式的 On-Call 体系,以下是从 0 到 1 的行动清单:
| 优先级 | 行动项 | 预计耗时 | 完成标志 |
|---|---|---|---|
| P0 | 梳理现有告警,做 P1-P4 分级 | 2-3 天 | 每条告警都有分级标签 |
| P0 | 确定值班人员名单和轮值周期 | 1 天 | 排出未来 4 周值班表 |
| P0 | 配置告警路由(只推 P1/P2 到值班人) | 1 天 | P3/P4 不再触发电话 |
| P1 | 配置主备升级策略 | 半天 | Primary 5 分钟未响应自动转 Secondary |
| P1 | 编写交接文档模板 | 半天 | 模板入库,本周开始使用 |
| P1 | 制定新人上岗流程 | 1 天 | 影子→反向影子→独立三阶段文档 |
| P2 | 搭建告警度量看板 | 1-2 天 | Grafana 展示 5 个核心指标 |
| P2 | 推动 On-Call 补偿政策 | 1-2 周 | 管理层确认补偿方案 |
| P3 | 季度 On-Call 满意度调查 | 半天 | 匿名问卷收回,分析结果 |
| P3 | On-Call 演练(每季度 1 次) | 半天 | 模拟 P1 故障,全流程走通 |
执行节奏:
- 第 1 周:完成 P0 事项。没有告警分级和值班表的 On-Call 就是耍流氓。
- 第 2-3 周:完成 P1 事项。主备机制和交接文档是稳定运行的基础。
- 第 4 周:启动 P2 事项。度量看板和补偿政策并行推进。
- 第 2 个月起:P3 事项按季度执行。满意度调查和演练形成常态化。
On-Call 演练是很多人忽略的环节。每个季度做一次模拟 P1 故障注入:找个测试环境,人为制造一个故障(比如杀掉数据库主节点),让当前值班人按完整流程响应——接告警、拉日志、定位、执行恢复、写交接文档。演练的目的不是考验个人能力,而是验证整个 On-Call 流程是否跑得通。如果演练中发现了"某个 Runbook 步骤过时了"或者"某个工具的权限没配对",正好在真实故障前修掉。
演练结束后花 30 分钟做复盘,重点记录三件事:响应时间是否达标、Runbook 是否可执行、工具链是否顺畅。把演练发现的问题录入改进项跟踪,下季度演练时验证是否修复。
多时区团队的排班补充
如果你的团队分布在多个时区(比如深圳+北京+海外),排班可以做"跟随太阳"(Follow the Sun)模式:每个时区的工程师只值班本时区的工作时间,交接给下一个时区。这样没有人需要在凌晨值班。
但 Follow the Sun 有前提:每个时区至少 3-4 个工程师,且系统复杂度允许跨时区交接。如果团队规模不够,还是得靠夜间 On-Call + 合理补偿。别强行套 Follow the Sun——交接成本可能比夜间值班还高。
总结
On-Call 排班设计不是一个"排个表"就完事的工作。它涉及轮值周期、主备机制、告警分级、疲劳量化、交接班、新人培养和补偿机制 7 个维度的工程决策。
核心原则就三条:
- 只有该被叫醒的人被叫醒——告警分级 + 精准路由
- 被叫醒的人能解决问题——主备机制 + Runbook + 交接文档
- 被叫醒的人不会因此离职——疲劳量化 + 合理补偿 + 轮值公平
Google SRE 的标准(琐事 <50%、团队 6-8 人、Outalator 全生命周期管理)是理想状态。国内大多数团队 SRE 与研发比例接近 1:100,很难完全照搬。但可以先从工具和流程入手:告警分级、排班自动化、交接文档、度量看板——这些不依赖团队规模,今天就能做。
最后说句实在话:On-Call 体系建得好不好,最终看的是人。工具和流程是骨架,工程师的士气和专业度才是血肉。如果工程师觉得"值班就是被白嫖",再好的工具也白搭。如果工程师觉得"值班是保障系统稳定的重要职责,团队尊重我的付出",就算用钉钉群排班也能跑出专业水准。
别等工程师提了离职才开始治理 On-Call。疲劳是累积的,等到爆发时,你失去的不只是一个人,还有他脑子里那套只有他自己懂的故障处理经验。
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- Google SRE 的 on-call 方法和工具 — 快猫星云 Flashcat,详细分析了 Google SRE 的 OnCall 文化、机制、工具和度量指标,本文关于琐事管理、Outalator 和 5 个度量指标的内容参考了此文
- Going On-Call: Best Practices for On Call Teams — PagerDuty,完整的 On-Call 实践指南,涵盖技术准备、团队规范、文化建设和管理建议,本文关于告警疲劳和团队健康的内容参考了此指南
- Building On-Call Schedules for Humans — Rootly,关于人性化 On-Call 排班设计的指南,本文新人上岗三阶段(影子→反向影子→独立)参考了此文的 Shadowing 和 Reverse Shadowing 方法
- Overrides, the Most Human Feature in PagerDuty — PagerDuty Blog,关于 On-Call 工程师疲劳管理和替换机制的文章,本文关于 On-Call 离职成本(30 万美元)的数据来源于此文
- Managing On-Call Rotations & Schedules — Squadcast,关于 On-Call 轮值管理的实践指南,本文关于轮值挑战(疲劳、误报、知识传递)的分类参考了此文
- 高效的 OnCall 机制:从理念到实践 — 快猫星云 Flashcat,关于 OnCall 四个核心问题(谁负责、何时负责、如何通知、无人响应怎么办)的框架,本文的 On-Call 核心问题部分参考了此文
- 《Google 运维解密》(Site Reliability Engineering: How Google Runs Production Systems)— Google SRE 团队,On-Call 章节中关于琐事管理原则和团队规模建议是本文理论框架的重要参考