想象你是一家急诊室的夜班医生。监护仪突然齐声报警:三号床血压骤降、七号床心动过速、走廊里又推进来一位昏迷患者。你不可能一个个床位跑过去问“怎么回事”——你需要分诊护士先判断谁最危急,需要中央白板让所有医护看到全局,需要无线电台喊一声“麻醉科来人”,还需要一张排班表保证今晚有人值夜。这套协作机制,就是医院版的“响应体系”。 当我们把同样的机制搬进软件系统运维,就得到了今天的主角:ChatOps 与 On-Call。如果说可观测性三支柱是看清系统状态的“仪表盘”,那么 ChatOps 就是把仪表盘读数变成行动的“驾驶舱”——聊天工具(Slack、钉钉、飞书)成为运维的中央白板与电台,告警自动涌入对话、机器人在对话里执行命令、值班工程师在对话里协同处置。On-Call 则保证任何时刻都有一位“值班医生”醒着接听告警,并按照排班表与升级策略从容应对。 这套思路听起来迷人,落地却藏在细节中:告警如何路由?值班如何排班?机器人能做什么?复盘如何不变成追责会?本篇文章将以急诊室为镜,从原理到实践,把 ChatOps 与 On-Call 的每个齿轮都拆开看一遍,让云原生团队也能搭建属于自己的“夜间急诊室”。
学会 ChatOps 与 On-Call,你就掌握了把告警、排班、自动化与复盘串成闭环的工程能力——这是云原生时代 SRE 与运维团队的必修课,也是从“救火队”走向“有组织免疫系统”的分水岭。
可视化演示
演示 ChatOps 与 On-Call 告警处置闭环:告警分级路由到正确值班人员,值班排班与升级机制保障响应,机器人自动化处置降低 MTTR,对话中完成高效协作与复盘。
本节配有交互动效(进入视口后自动加载,约 3KB)。
告警分级路由 告警按规则自动分发到正确值班人员 分发给谁→怎么发→何时升级 降低噪声告警,提升响应质量
定义与价值
急诊室的效率,从来不是靠医生跑得快,而是靠信息流动的方式。分诊护士先筛一轮,中央白板让所有人看见床位状态,无线电台喊一声就能调度资源——三件套配合,再混乱的夜班也能稳住阵脚。ChatOps 的理念正是如此:把聊天软件变成运维的“白板+电台”,让告警、协作、操作共享同一条对话流。
2013 年,GitHub 工程师提出 ChatOps 一词,核心主张是“聊天即控制平面”:一切运维行为都发生在聊天线程里。与之孪生的是 On-Call 制度——按排班表 24×7 有人在线待命,随时响应告警,就像急诊室永远有夜班医生。
传统运维模式下,告警走邮件、协作走 IM、操作走命令行,三个孤岛互相割裂:告警到了没人看,处理过程没人知道,事后想复盘翻遍几十个窗口。ChatOps 将它们缝合进一个对话进程:机器人把告警“翻译”成对话消息,把命令“翻译”成系统动作,值班人的每一个判断与操作都留在对话里,天然形成审计日志与知识沉淀。
衡量这套体系好坏,最核心的指标是 MTTR(平均恢复时间),它等于故障总时长除以故障次数:
有了对话式作战室,值班医生不用再满楼奔跑——所有信息、人与动作都在一个频道里流转,这就是 ChatOps 送给团队的“急诊室效率”。
- 分子 T统计周期内所有故障持续时长的总和,单位常为分钟,由监控系统自动累计。
- 分母 N同一周期内发生的故障总次数,只统计真实影响服务的告警。
- 整体除法用总时长除以总次数,得到“平均每起故障恢复要多久”,这是 ChatOps 优化效果的核心标尺。
告警路由
急诊室门口,分诊护士必须在几十秒内做出判断:胸痛者推进抢救室,划伤者送到候诊区。这个动作决定了医疗资源的流向。在 ChatOps 体系里,负责“分诊”的组件就是告警路由——它决定一条告警该进哪个群、该@谁、该以多高的优先级打扰值班人。
告警路由的第一环是告警源接入:Prometheus、Grafana、Zabbix 或自研监控系统通过 Webhook 把告警推送到聊天频道。第二环是路由规则:按服务名、告警标签、环境(生产/测试)匹配目标团队与值班群,例如“订单服务错误率突增”固定进入支付团队的值班群。第三环是去重与抑制:同一告警合并为一条,已知维护窗口内的告警自动静默,避免“告警风暴”把对话刷成雪花屏。
为了让“分诊”有客观标准,常见做法是为告警计算综合优先级分——严重程度、影响范围、紧迫度三路打分后进行加权求和:
分诊做得好,急诊室才不会“全体忙乱”;路由做得好,值班人收到的每一条告警都值得被立刻处理——这是对抗告警疲劳的第一道防线。
- S 严重程度故障破坏力,数据丢失给 10 分,功能缓慢给 3 分,按 1–10 标定。
- I 影响范围波及多少用户或业务线,全站宕机给 10 分,单实例异常给 4 分。
- U 紧迫度若不处理,多久会恶化,正在崩溃给 10 分,趋势平缓给 2 分。
- 权重 ω 与求和按业务特性分配权重,例如交易系统更看重 S;加权求和得到最终优先级 R,高于阈值直接电话呼叫 On-Call。
值班排班
医院的排班表上永远有“今夜值班医生”,科室还备着“二线主任”,一线搞不定就呼叫二线。On-Call 排班把这套制度数字化:主值班与备值班轮流坐庄,周期按团队规模定为每周或每两周,排班结果自动同步到日历,值班人能提前安排生活,手机安上值班 App 随时接收告警。
排班之外,升级策略决定了值班体系的天花板。当告警推送给主值班人后,若 5 分钟内未确认,机器人自动升级:先再次@主值班,接着呼叫备份值班人,最后触发电话语音告警。逐级升级就像“先喊值班医生,不行再叫主任”,避免一次故障把全团队从被窝里挖起来。
交接班是另一个魔鬼细节。交班纪要必须包含三项:未恢复的告警、进行中的处置、待跟进的事项。机器人自动汇总前一天的关键事件,值班人 5 分钟即可完成交接,不让隐患“过夜失忆”。
要验证排班是否满足“任何时刻有人响应”,引入覆盖度指标:
一张滴水不漏的排班表,就是急诊室那盏永远亮着的“值班灯”:只要灯亮着,告警就永远有人回答。
- 分子 t_oncall某段时间内有主值班人待命的小时数,需要两个班次无缝拼接。
- 分母 T统计周期的总时长,一周为 168 小时。
- 百分比化两者相除再乘 100%,C 越接近 100% 覆盖越好;若小于 100%,说明存在无人值守的时间窗口,需要在复盘时补齐。
机器人助手
患者刚推进急诊室,分诊护士已经量好血压、抽好血、连上监护仪——这些“初检”动作不由医生完成,却为医生争取了最宝贵的几分钟。ChatOps 里的机器人就是这位分诊护士:它不做复杂决策,但它能不知疲倦地执行准备动作与标准操作。
现代 ChatOps 机器人一般基于机器人框架搭建,如 Hubot、Bolt、钉钉/飞书自定义机器人,通过 WebSocket 长连接订阅聊天事件。值班人在对话里输入斜杠命令,比如 /incident new 创建故障单、/logs order-api 拉取日志、/rollback v1.2.3 回滚版本;机器人收到命令后调用后端 API,把执行结果(成功、超时、输出片段)回写到对话,形成“命令→动作→反馈”的闭环。
更高级的用法是剧本自动化:把“磁盘使用率超 90% 怎么办”写成剧本,机器人自动执行清理临时文件、滚动重启容器、拉起扩容,只有剧本无法解决时才升级人工。团队因此能把自己的重复劳动交给机器人,其效果用自动化处置率衡量:
分诊护士的初检降低了医生的认知负担,机器人的自动化处置同样把值班人从“按下 F5 刷新”的重复劳动中解放出来——这是 On-Call 体验不再可怕的关键。
- 分子 N 自动处置经过剧本或预设命令完全自动处理、无需人工介入的告警数量。
- 分母 N 告警总数统计周期内进入聊天频道的全部告警,包括自动处理与转人工的部分。
- 百分比除法两者相除得出自动化率,成熟团队通常达到 60%–80%,剩余 20% 才是真正需要人类判断的复杂故障。
对话式响应
急诊室的中央白板,不认识字的人也能看懂:每个床位一张卡片,写着病情、负责医生、下次检查时间。ChatOps 的对话线程就是数字版白板卡片——一个故障开一个线程,机器人把告警上下文、相关日志、时间线自动聚合进来,相关人员加入频道,讨论与操作都沉淀在同一个滚动记录里。
传统 IM 群聊最大的痛点是“信息爆炸”:十个人同时说话,关键结论淹没在表情包里。用线程隔离后,每个故障有自己的频道,人员按需加入,避免“所有群都响”的灾难。透明协作也随之而来:管理者想了解进展,进线程看滚动记录即可,不必反复追问;新接手的同事翻聊天记录就能接上上下文,大幅降低交接成本。
信息同步的成本可以用组合数学来理解:没有统一广播时,一条消息要两两发送才能让所有人对齐;而对话线程只需广播一次:
对话不仅是效率工具,更是天然的审计日志:谁在什么时刻说了什么、执行了什么命令,全部留痕。这为下一节的事后复盘准备了最完整的素材。
- 两两传话的组合数n 个人互相通知,总共需要 C(n,2) 条消息,也就是消息要复制这么多份。
- 线程广播后的数量有了共享白板,每条信息只需写一次,所有人阅读后即可对齐。
- 箭头对比当 n=10 时,45 次两两通知被压缩成 10 次广播,信息损耗大幅下降,这就是 ChatOps 降低协作成本的数学本质。
事后复盘
急诊科每周四下午开病例讨论会,重点不是“小张当时为什么手抖”,而是“监护仪报警为什么没有联动呼叫值班护士”。问题指向系统与流程,而不是个人——这就是无指责复盘的核心精神,也是 ChatOps 实践中最考验团队文化的一环。
复盘的第一步是重建时间线。人工回忆靠不住,但 ChatOps 的对话留痕恰好记录了完整轨迹:几点几分告警进群、机器人执行了什么、谁说了哪句话、操作何时生效。把这些记录按时间排列,就得到一条可信的故障时间线,回答“我们到底在哪里多花了 30 分钟”。
第二步是界定行动项。每个根因必须对应可执行的改进项:补监控、改剧本、修文档、加自动化。行动项要落到具体负责人与截止日期,并定期检查闭环情况:
好的复盘会结束于更好的明天:每一次病例讨论都让流程多一道“防呆”设计,让团队离“永不二次踩坑”更近一步。
- 分子 N 已闭环在截止日期前完成并验收的改进项数量。
- 分母 N 行动项总数每次复盘产出的所有行动项之和,含进行中与逾期项。
- 闭环率计算完成项占比越高,复盘越有效;同时要把改进后的剧本沉淀进知识库,让下一次同类故障直接交给机器人。
落地与度量
新建一家医院,设备采购与动线设计决定未来十年的运转效率。落地 ChatOps 同样需要两件事:选对工具,画好架构。工具层,国内团队常用钉钉/飞书/企业微信,海外常用 Slack;若没有预算采购商业产品,用自定义机器人配合 Webhook 也能在三天内搭出雏形。
架构层可以分四层理解:接入层(监控系统把告警推给机器人)、路由层(按规则分诊到具体群聊)、执行层(机器人调用 API 完成动作)、知识层(剧本与复盘文档沉淀)。四层各司其职,与前面几节一一对应——接入对应告警、路由对应分诊、执行对应机器人、知识对应复盘。
最后,用指标驱动迭代。团队应每周回顾四类指标:响应速度(MTTA/MTTR)、自动化水平(自动化处置率)、值班负荷(人均告警数、夜间被叫醒次数)、协作体验(值班满意度)。其中可用性 SLO 将这一切换算成业务语言:
急诊室的价值,要等半年后的数据出来才算数;ChatOps 落地的价值,同样要用这些数字来证明。但最重要的是——你已经知道该优化哪个环节了。
---
- 停机时长 T统计周期内服务不可用的总时长,通常由监控探针测量,只统计真实用户受影响的时间。
- 停机占比停机时长除以周期时长,表示“坏掉的时间比例”,占比越小越好。
- 1 减去再乘 100%剩余部分即“好用的时间比例”;指标回灌到 ChatOps 流程,若可用性不达标,排查是告警漏报、路由错派还是恢复太慢,形成持续改进的飞轮。
AI 应用场景
大促告警风暴下的值班室
阶段:告警路由与自动处置
解决的问题:电商大促时监控系统每分钟产生上千条告警,人工在邮箱和 IM 之间来回切换,常出现“告警到了没人认领”的真空期。ChatOps 让告警自动汇聚到钉钉群,机器人按服务归属路由到各自值班群,高优告警直接 @ 当前 On-Call 并附上日志链接,使响应从“等人发现”变成“系统自动指派”。
具体案例:某头部电商在双十一前把 Prometheus 告警接入钉钉机器人,配置了“订单服务错误率 >1%”路由到订单值班群、自动创建故障线程、触发日志拉取命令。大促当天自动化处置了 73% 的副本类告警,平均响应时间从 15 分钟降到 3 分钟。
金融故障复盘的“时光机”
阶段:事后复盘与知识沉淀
解决的问题:传统复盘靠人肉翻聊天记录、工单、发布日志拼时间线,一场复盘会光还原事实就要 1 小时,还容易遗漏关键动作。ChatOps 把告警进入、机器人命令、人工发言全部留痕,复盘时一键导出时间线,团队可以把精力聚焦在根因分析而非还原过程上。
具体案例:某支付公司每季度 12 场复盘,引入 ChatOps 时间线自动生成后,平均每场从 2 小时缩短到 40 分钟,行动项闭环率从 52% 提升到 85%,沉淀出 30 多条可复用剧本。
小团队的轻量 ChatOps 起步
阶段:工具链选型与架构落地
解决的问题:20 人小团队没有专职 SRE,买不起商业 On-Call 平台,但同样深受半夜告警骚扰。基于飞书自定义机器人配合 Webhook 与 GitHub Actions,两天即可搭出“发布通知—告警路由—自动重启”的最小闭环。
具体案例:某 SaaS 创业公司用飞书机器人接收 Sentry 错误通知,按错误级别路由到对应服务群,低级错误自动创建 issue,高级错误 10 分钟内无人响应自动电话升级,半年内把夜间被叫醒次数从每周 4 次降到每月 1 次。
Python 演示
# -*- coding: utf-8 -*-"""ChatOps on-call simulator: alert routing + auto response."""import random class Alert: """One alert event from monitoring systems.""" def __init__(self, source, severity, message): self.source = source # e.g. disk, cpu, memory self.severity = severity # 1 fatal, 2 warning, 3 info self.message = message class OnCallRoster: """Rotation schedule: always one primary on-call engineer.""" def __init__(self, engineers): self.engineers = engineers self.week = 0 def current_oncall(self): return self.engineers[self.week % len(self.engineers)] def rotate(self): self.week += 1 class Router: """Route alert to runbook automation or human on-call.""" def __init__(self, roster): self.roster = roster self.auto_count = 0 def route(self, alert): score = alert.severity * 10 if score >= 30: return "assign:" + self.roster.current_oncall() self.auto_count += 1 return "auto" class Bot: """ChatOps bot executes runbook actions in chat.""" def __init__(self): self.runbooks = { "disk": "clean tmp files and restart container", "memory": "rolling restart service instances", "cpu": "scale out replicas by 2", } def auto_handle(self, alert): for key, action in self.runbooks.items(): if key in alert.message: return "bot: " + action return "bot: no runbook matched, escalate to human" class ChatOpsSimulator: """Run a batch of alerts through the ChatOps pipeline.""" def __init__(self, engineers): self.roster = OnCallRoster(engineers) self.router = Router(self.roster) self.bot = Bot() self.history = [] def fire_alert(self, source, severity, message): alert = Alert(source, severity, message) route = self.router.route(alert) if route == "auto": result = self.bot.auto_handle(alert) else: result = route + " acked by human" self.history.append((source, severity, result)) return result def stats(self): total = len(self.history) auto = self.router.auto_count rate = auto / total * 100 if total else 0 return total, auto, rate def main(): sim = ChatOpsSimulator(["alice", "bob", "carol"]) random.seed(42) sources = ["disk", "cpu", "memory", "gpu"] for _ in range(30): src = random.choice(sources) sev = random.choice([1, 2, 3]) msg = src + " usage abnormal" print(sim.fire_alert(src, sev, msg)) total, auto, rate = sim.stats() print("---") print("alerts=%d auto_handled=%d auto_rate=%.1f%% oncall=%s" % (total, auto, rate, sim.roster.current_oncall())) if __name__ == "__main__": main()
def __init__(self, source, severity, message)每条告警封装成对象,包含来源、严重级别和消息正文。score = alert.severity * 10把严重级别(1–3)换算成分数,用于路由分诊。return "assign:" + self.roster.current_oncall()高分告警直接指派给当前值班工程师。self.auto_count += 1低分告警走自动化通道,并记录次数供统计。self.runbooks = {...}剧本库:每种告警关键词对应一段处置动作,像急诊室的“标准操作卡”。if key in alert.message用关键词匹配剧本,决定机器人执行哪个动作。self.history.append((source, severity, result))每条处置结果都留痕,对应 ChatOps 的审计日志,供事后复盘。auto / total * 100 if total else 0计算自动化处置率,即正文中 A = N_自动 / N_总 的实现。
常见误区
误区我们建了个钉钉群,把 Prometheus 告警机器人拉进去,就算落地 ChatOps 了。
正解这只是“告警上墙”,相当于急诊室只有一台会响的电视,没有分诊、没有电台、没有排班。ChatOps 的完整闭环包含路由规则、值班排班、机器人可执行命令、复盘归档四个环节。缺了自动化与流程编排,群聊只是把邮件换了个地方继续吵。
为何常见:ChatOps 最表面的特征确实是“在聊天里看到告警”,而流程编排隐藏在系统内部,初学者很容易把表象当成本质。
误区机器人这么强,以后把剧本写全,就不需要人 24 小时值班了。
正解自动化处理的是“已知问题”,而生产事故的最大特点是“未知且罕见”。没有值班人兜底,未知故障会在深夜被无限放大。好的实践是把自动化率提到 60%–80%,剩余 20% 交给人类判断,同时用疲劳度指标让值班体验可承受。
为何常见:对自动化的期望过高,忽略了“判断”与“决策”很难被穷举成剧本——就像分诊护士无法替代医生做最终诊断。
误区把监控阈值调低,一有风吹草动就告警,这样肯定不会漏报。
正解告警疲劳会让人对告警视而不见,心理学上叫“狼来了”效应。正确做法是分层:低频高优告警直接电话升级,中频告警进值班群,高频低优信息进周报聚合,让每一级通道都保持稀缺与可信。
为何常见:直觉上觉得“多总比少好”,却没意识到人的注意力是一种会被消耗的珍贵资源,急诊室也不会为每个喷嚏拉响警报。
误区复盘会就是要找出“到底谁搞砸了”,给个处分,以儆效尤。
正解无指责复盘把矛头指向系统:流程哪里让好人犯错?工具哪里缺了防呆?监控哪里漏报?只有不惩罚个人,人们才敢说出全部真相;否则复盘会变成甩锅大会,真正的根因永远沉在水底。
为何常见:传统管理思维的惯性,“找到责任人”在直觉上最解气也最简单,但系统性的改进需要更冷静的视角。
误区我们公司用钉钉/飞书,是不是就没法做 ChatOps 了?
正解ChatOps 的本质是“对话驱动协作”,与具体平台无关。钉钉/飞书都提供自定义机器人、Webhook 和开放 API,配合开源监控与脚本,完全能实现告警路由、命令执行、复盘沉淀全流程。小团队用飞书加 Python 脚本三天就能起步。
为何常见:国外文章几乎都以 Slack 为例,容易让读者把“例子”误当成“必要条件”——就像看到国外急诊室用某种对讲机,就以为自家电台全要换掉。
面试题
Q1. ChatOps 最核心的转变是什么?
- A.用聊天工具代替工单系统
- B.一切运维动作沉入对话流← 正确答案
- C.把告警消息发到手机里
- D.所有团队扫码进一个群聊
答案:B。ChatOps 的核心是“聊天即控制平面”,告警、命令、协作全部沉淀在对话流中。A 只是工具替换,C 只是通知渠道变化,D 只是形式上的进群,都没有触及“对话驱动运维”的本质。
Q2. 告警去重抑制的主要目的是什么?
- A.减少监控系统的存储开销
- B.对抗告警风暴与值班疲劳← 正确答案
- C.让告警列表看起来更整洁
- D.提高监控数据采集频率
答案:B。去重抑制的核心价值是降低告警噪音,防止“狼来了”效应让值班人对告警麻木。存储开销与整洁是附带收益,采集频率与去重无关。
Q3. 一次 ChatOps 事故响应通常包含哪些环节?
- A.告警汇聚进入聊天频道← 正确答案
- B.机器人拉取日志执行剧本← 正确答案
- C.值班人员在线对话处置← 正确答案
- D.处置完成后删除全部记录
答案:ABC。标准闭环是“告警进群→机器人准备→人工处置→复盘归档”。D 完全错误,ChatOps 恰恰要完整留痕供复盘与审计,删除记录会让时间线重建失去依据。
Q4. MTTR 指的是哪一项指标?
- A.从故障发生到被发现时间
- B.单次故障平均恢复时长← 正确答案
- C.两次故障之间的间隔
- D.监控探针的轮询周期
答案:B。MTTR 是平均恢复时间,等于故障总时长除以故障次数,衡量“救回来”的速度。A 是 MTTD(平均检测时间),C 是 MTBF(平均故障间隔),D 是采集配置。
Q5. 以下哪些做法能有效降低 MTTR?
- A.告警路由按服务精准派单← 正确答案
- B.机器人自动执行运维剧本← 正确答案
- C.值班排班实现全天候覆盖← 正确答案
- D.每次故障后更换责任人
答案:ABC。精准路由减少派错人的时间,自动化剧本缩短处置时间,全天候覆盖保证故障有人响应,三者分别压缩 MTTR 的不同环节。D 与降低 MTTR 无关,反而破坏复盘连续性。
Q6. 关于值班升级策略,正确的是?
- A.告警到达立即全员电话通知
- B.按主备顺序逐级升级处理← 正确答案
- C.无人确认就静默等待下一班
- D.升级只适用于夜间发生故障
答案:B。逐级升级(主值班→备值班→电话呼叫)平衡了响应速度与打扰面,避免全员轰炸。A 会造成严重告警疲劳,C 会无限延长故障时长,D 错误——白天同样需要升级机制。
Q7. 无指责复盘的核心精神是什么?
- A.找出责任人并给予惩罚
- B.聚焦系统与流程的漏洞← 正确答案
- C.记录工时以便绩效考核
- D.归档聊天记录完成流程
答案:B。无指责复盘把问题指向系统设计、监控盲区与流程缺陷,而非个人操作。只有不追责,团队成员才敢于暴露全部事实,根因分析才可能成立。
Q8. ChatOps 对话留痕的审计价值有哪些?
- A.复盘时快速重建故障时间线← 正确答案
- B.满足合规审计的追溯要求← 正确答案
- C.为新员工提供真实学习材料← 正确答案
- D.自动生成运维成本账单
答案:ABC。对话留痕记录了告警、命令、发言的时间戳,既是复盘时间线的原料,也是合规审计的证据,还能作为新人学习案例。D 属于成本核算,与审计留痕无关。
Q9. 自动化处置率的正确算法是?
- A.自动处理告警数除以告警总数← 正确答案
- B.人工处理告警数乘以告警总数
- C.告警总数减去机器人运行时长
- D.机器人数量除以值班工程师数
答案:A。自动化处置率 = N_自动 ÷ N_总,衡量机器人独立消化告警的比例。B、C、D 在量纲上就不成立——分子分母混入了人数与时长的概念。
Q10. 值班交接纪要最应包含哪项内容?
- A.本周菜单与天气情况
- B.未恢复告警与进行中事项← 正确答案
- C.每位同事的聊天风格
- D.上季度会议全部纪要
答案:B。交接班的唯一目的是让下一班无缝接住“半途中的故障”,所以未恢复告警、进行中处置、待跟进事项是铁三角。A、C、D 与保障服务连续性无关,只会稀释交接效率。