别再让运维当“背锅侠”了:一个40人团队从救火队到防火队的组织改造
Nov 13, 2026 · @Echo_Wish
凌晨三点,那通电话让我想明白了一件事
凌晨三点十五,手机震了。订单接口超时,数据库慢查询把 CPU 打满了。我一边骂一边爬起来,两个小时后总算修好——根因是研发上线的新功能,忘了加索引。
早上复盘会,领导开口第一句:“运维怎么没提前发现?”
那一刻我特别清醒:运维团队的痛,十有八九不是技术问题,而是组织问题。 谁该管、谁来管、管好了算谁的功劳、管砸了算谁的锅,这几件事没理顺,你招再多大牛、上再贵的监控,也只是在给一艘漏水的船换更好的桶。
这篇文章,我把这几年见过的几个企业级运维团队揉成一个 40 人团队的案例(细节已脱敏),聊聊它是怎么从“人人救火”改成“有人防火”的:岗位怎么拆、职责怎么划、KPI 怎么设计才不会反噬自己。 里面有踩过的坑,也有我的一些偏见,咱们边聊边看。
先看病根:一个人,同时当五个人用
这个团队改造前是什么样?40 个人,名义上分“系统组”“网络组”“DBA 组”,实际上谁有空谁上。今天你帮研发发版,明天帮行政开账号,后天半夜起来处理告警,周末还要配合审计。
我让一个同事把一周的工作记录导出来,随手写了段脚本数了数:
from collections import Counter
# 改造前:一个“全能运维”一周的 20 条工作记录(脱敏)
week = ["发布", "账号开通", "告警处理", "发布", "审计配合", "扩容", "告警处理", "VPN故障",
"发布", "写脚本", "告警处理", "权限申请", "审计配合", "告警处理", "打印机", "扩容",
"发布", "告警处理", "账号开通", "写脚本"]
cnt = Counter(week)
print(cnt.most_common())
switches = sum(1 for a, b in zip(week, week[1:]) if a != b)
print(f"一周 {len(week)} 件事,涉及 {len(cnt)} 种类型,上下文切换 {switches} 次")
跑出来的结果是:
一周 20 件事,涉及 9 种类型,上下文切换 19 次
20 件事,换了 19 次“频道”。这哪是工程师,这是人肉路由器。
更要命的是,这种状态会产生三个连锁反应:
- 没人有整块时间做长期的事。 自动化、容量规划、架构治理,永远排在“先把眼前的火灭了”后面。
- 能力被压成了“最大公约数”。 每个人什么都会一点,什么都不精,真遇到疑难杂症还得靠那两三个老员工。
- 功劳和锅都模糊。 出了事大家一起上,复盘时没人说得清到底该谁改进。
所以我的第一个观点很直白:运维的“忙”不等于“有价值”,岗位设计的第一原则是让人有整块时间做同一类事。
岗位怎么拆:按“价值流”拆,别按“技术栈”拆
传统做法是按技术栈分组:系统、网络、数据库、中间件。听起来合理,问题是用户的故障不会按技术栈发生。一个下单超时,可能是网络、数据库、缓存、代码一起造成的,四个组各扫门前雪,就没人对“下单能不能用”负责。
我们后来改成按“价值流”拆成四条线:
| 岗位线 | 核心使命 | 典型工作 | 人数(共 40) |
|---|---|---|---|
| 稳定性(SRE) | 对“服务能不能用”负责 | SLO 制定、故障指挥、复盘、容量规划 | 10 |
| 平台工程 | 让研发自己能把事办了 | 发布平台、CI/CD、基础设施即代码、自助工具 | 14 |
| 运营保障 | 把日常事务做稳、做快 | 7×24 值班、变更执行、账号权限、资源交付 | 10 |
| 安全合规 | 守住底线 | 漏洞治理、审计、基线检查、权限审批 | 6 |
这四条线我习惯用一份 YAML 写清楚,贴在团队 Wiki 首页,新人入职第一天就能看懂:
teams:
sre:
mission: "对线上服务的可用性与用户体验负责"
owns: [SLO, incident_command, postmortem, capacity_planning]
not_owns: [日常账号开通, 办公网络] # 写清楚“不管什么”,比写“管什么”更重要
platform:
mission: "把重复劳动变成自助服务"
owns: [release_pipeline, iac, self_service_portal]
success_signal: "研发不再为发布提工单"
ops_support:
mission: "稳定、快速地完成标准化事务"
owns: [oncall_l1, change_execution, resource_delivery]
security:
mission: "风险可见、可控、可审计"
owns: [vuln_mgmt, audit, baseline, access_approval]
这里我想特别强调两点个人体会:
not_owns比owns更值钱。 运维团队的边界被一点点吃掉,往往不是被抢走的,而是自己不好意思说“不”。白纸黑字写着“这不归我们”,拒绝的时候才有底气。- 平台工程的占比要敢给。 很多公司舍不得,觉得“不如多招几个人接工单”。可是 14 个人做出来的自助平台,能让几百个研发不再提工单——这是杠杆,不是成本。
职责怎么划:每件事,有且只有一个“A”
岗位分好了,下一个坑是灰色地带。比如开头那个慢查询:研发说“数据库的事归运维”,DBA 说“SQL 是你们写的”,最后谁也没管,直到凌晨三点爆炸。
解法不新鲜,就是 RACI 矩阵:R(Responsible,动手干)、A(Accountable,最终负责)、C(Consulted,被咨询)、I(Informed,被告知)。关键规则只有一条:每件事有且只有一个 A,而且至少有一个 R。
光画表没用,表放半年就没人看了。我的习惯是把它写成代码,丢进 CI 里天天校验:
RACI = {
"生产发布": {
"平台": "R", "SRE": "C", "研发": "A", "安全": "I"},
"故障响应": {
"SRE": "A", "运营保障": "R", "研发": "R", "平台": "C"},
"容量规划": {
"SRE": "A", "平台": "R", "研发": "C"},
"账号权限开通": {
"运营保障": "R", "安全": "A"},
"漏洞修复": {
"研发": "R", "安全": "A", "SRE": "I"},
"慢查询治理": {
"研发": "A", "SRE": "C"}, # 故意留个坑:没人 R
}
def check(raci):
problems = []
for task, roles in raci.items():
a = [r for r, v in roles.items() if v == "A"]
r = [r for r, v in roles.items() if v == "R"]
if len(a) != 1:
problems.append(f"【{task}】必须有且仅有 1 个 A,现在是 {len(a)} 个")
if not r:
problems.append(f"【{task}】没人 R,没人真正动手")
return problems
for p in check(RACI) or ["全部通过"]:
print(p)
运行结果:
【慢查询治理】没人 R,没人真正动手
你看,这个“故意留的坑”正是现实中最常见的状态:有人签字负责,却没人真正干活。把它变成一条会报红的检查,比开十次“明确职责”的会管用得多。
我的第二个观点:职责不清不是态度问题,是设计缺陷。 别指望靠“大家多担待”去补,能被校验的规则才是真规则。
KPI 怎么设:考核“结果”,别考核“忙碌”
这是整个改造里最容易翻车的地方。我们改造前的 KPI 是:工单处理数、告警响应时长、变更完成数。 看起来很客观,结果呢?
people = {
"小王": {
"closed": 300, "repeat_incidents": 45, "saved_hours": 0},
"小李": {
"closed": 80, "repeat_incidents": 5, "saved_hours": 120},
}
for name, d in people.items():
print(f"{name}: 工单数={d['closed']} 重复故障={d['repeat_incidents']} 自动化节省={d['saved_hours']}h")
print("按工单数排名:", sorted(people, key=lambda n: -people[n]["closed"]))
小王: 工单数=300 重复故障=45 自动化节省=0h
小李: 工单数=80 重复故障=5 自动化节省=120h
按工单数排名: ['小王', '小李']
小王一个季度处理 300 张工单,天天加班,年终稳拿第一;小李只处理了 80 张,因为他把最常见的几类工单做成了自助工具,工单自己就消失了,还让同样的故障少发生了 40 次。按旧 KPI,小李是倒数。
这就是我反复吐槽的事:工单数越高,代表系统越烂、流程越差,却被当成“功劳”。 你奖励什么,团队就生产什么——奖励救火,就会有人天天“制造”火。
后来我们把 KPI 全部换成“结果导向”,并且拆成四类:稳定、效率、质量、成长。示例如下:
KPI = {
"可用性 SLO (%)": {
"actual": 99.95, "target": 99.95, "higher_better": True, "weight": 0.25},
"MTTR (分钟)": {
"actual": 38, "target": 30, "higher_better": False, "weight": 0.20},
"重复故障占比 (%)": {
"actual": 12, "target": 10, "higher_better": False, "weight": 0.20},
"自助完成率 (%)": {
"actual": 58, "target": 70, "higher_better": True, "weight": 0.20},
"变更失败率 (%)": {
"actual": 4.0, "target": 5.0, "higher_better": False, "weight": 0.15},
}
def score(m):
a, t = m["actual"], m["target"]
ratio = a / t if m["higher_better"] else t / a
return min(ratio, 1.2) * 100 # 封顶 120 分,防止靠单项堆分
def total(kpi, p0_without_postmortem=0):
s = sum(score(m) * m["weight"] for m in kpi.values())
return min(s, 80) if p0_without_postmortem else s # 红线:P0 不复盘,总分封顶 80
for k, m in KPI.items():
print(f"{k:<14} {score(m):6.1f}")
print(f"总分: {total(KPI):.1f}")
print(f"有 P0 未复盘: {total(KPI, 1):.1f}")
可用性 SLO (%) 100.0
MTTR (分钟) 78.9
重复故障占比 (%) 83.3
自助完成率 (%) 82.9
变更失败率 (%) 120.0
总分: 92.0
有 P0 未复盘: 80.0
这套设计里我最得意的是三个小机关:
- 单项封顶 120 分。 防止某一项刷到离谱、拉高总分,掩盖其他短板。
- “重复故障占比”权重不低。 同一个坑掉进去第二次,才是真正的失职,这一项逼着大家做根因治理。
- 红线机制。 P0 故障不复盘,总分直接封顶 80。再漂亮的数字,也不能抵消“不总结教训”。
另外,KPI 要按岗位线分别设计,不能一刀切。 SRE 看 SLO 和 MTTR,平台看自助完成率和研发满意度,运营保障看变更失败率和交付时效,安全看漏洞修复周期。一个指标卡 40 个人,必然有人被冤枉。
踩过的坑:KPI 一定会被“玩坏”,提前想好怎么防
古德哈特定律说得好:当一个指标变成目标,它就不再是好指标。我们落地第一个季度就见识了:
- MTTR 变短了,但故障“被降级”了。 有人为了让数字好看,把 P1 故障改成 P2 记录。后来我们加了一条:故障等级由 SRE 之外的人(业务方)确认,不能由处理人自己定。
- 重复故障变少了,但新故障变多了。 因为大家怕背“重复”的锅,宁愿每次都换个说法登记。解决办法是按根因分类归并,而不是按现象。
- 自助完成率冲得很高,研发却骂声一片。 原来自助工具难用,大家绕道了。于是平台线加了一个配对指标:研发满意度,每季度抽样问卷,低于 80 分一票否决。
这几次翻车让我总结出一条原则:每个“进攻型指标”,都要配一个“防守型指标”。比如效率配质量,速度配稳定,自助率配满意度。单独一个数字,迟早被人钻空子。
再说两个落地的小经验:
- 先试运行一个季度,不挂钩奖金。 让大家先熟悉、先吐槽、先修正,指标改三轮再上真刀真枪。
- KPI 谁定的,谁来对数据负责。 数据口径尽量自动采集(监控、工单、CI 系统),别靠人手填,人手填的数字,天然不可信。
写在最后:运维的体面,是设计出来的
这个团队改造了大概三个季度。效果不算惊天动地,但很实在:夜里的告警电话少了将近一半,研发提的发布工单几乎归零,团队里第一次有人主动说“我想去做平台”。
回头看,我想说几句掏心窝子的话:
- 别再把运维当“背锅侠”。 背锅是组织设计的失败,不是运维人的宿命。岗位、职责、KPI 这三件事想清楚,大部分锅根本不会落下来。
- 别迷信工具,先理顺人。 我见过太多团队,监控平台换了三套,故障该怎么复盘还是一团乱。工具放大的是组织,而不是替代组织。
- 给人成长的通道。 一个运维的价值,不应该只体现在“半夜爬起来修好了”,更应该体现在“让半夜不用再爬起来”。
如果你正好在带运维团队,不妨从最小的一步开始:这周把你们团队 20 条工作记录拉出来数一数,看看上下文切换了多少次,再看看你们现在的 KPI 到底在奖励谁。只要这一步做了,你就已经比大多数人走得更远。
我是 Echo_Wish,咱们下篇文章见。