从运维到 SRE:思维方式的根本转变 原创
很多团队把运维改名叫 SRE,把监控系统换成了 Prometheus,把工单系统换成了 Jira,然后把运维同学改叫 SRE 工程师。
然后该半夜起来处理告警还是半夜起来处理告警,该手工扩容还是手工扩容,该出了事背锅还是出了事背锅。
换了工具不等于换了思维方式。没有思维方式的转变,SRE 就只是一个更高级的运维头衔。
这篇文章不讲 SRE 是什么(Google 那本书已经写得很清楚了),讲的是运维和 SRE 在日常工作中,思维方式到底有哪些根本不同——以及怎么完成这个转变。
一、运维思维 vs SRE 思维:六个维度
先说结论。运维和 SRE 的根本区别,不是工具不同,而是面对同一个问题时,思考的出发点、决策的依据、衡量的标准完全不同。
| 维度 | 传统运维思维 | SRE 思维 |
|---|---|---|
| 目标 | 系统不出故障 | 用错误预算平衡稳定性和迭代速度 |
| 工作方式 | 人肉响应,手动操作 | 消除 toil,用系统替代人力 |
| 故障处理 | 尽快恢复,追查责任人 | 尽快恢复,复盘改进流程 |
| 可靠性 | 越稳定越好(100% 最好) | 够用就好(99.9% 或 99.95%) |
| 与开发的关系 | 运维是开发的"下游" | SRE 和开发共享可靠性责任 |
| 衡量标准 | 出了几次故障 | MTTR、MTBF、错误预算消耗率 |
下面逐一展开。
二、维度一:从"不出故障"到"错误预算"
2.1 运维的困境
传统运维的核心目标是"系统稳定运行"。但"稳定"是一个没有边界的词——多稳定算稳定?99%?99.9%?99.99%?
没有量化目标的结果是:
- 业务方觉得"任何故障都不可接受",要求 100% 可用
- 运维团队为了追求更高可用性,不断收紧变更审批流程
- 开发团队抱怨"发个版要审批三道,耽误迭代速度"
- 运维和开发形成对立,互相指责
2.2 SRE 的破局:错误预算
SRE 的核心创新不是引入了某个工具,而是引入了错误预算这个概念。
逻辑很简单:如果你承诺 99.9% 的可用性,那 0.1% 的不可用时间就是你"可以花掉的预算"。
月度可用性目标:99.9%
月度总分钟数:43200 分钟
允许不可用时间:43200 × 0.1% = 43.2 分钟/月
这 43.2 分钟就是你的错误预算。错误预算的用途:
| 预算状态 | 含义 | 允许的行动 |
|---|---|---|
| 预算充足(剩余 >50%) | 系统比承诺的更稳定 | 可以加速发版、做激进变更 |
| 预算消耗中(剩余 20-50%) | 系统接近承诺水位 | 正常迭代,注意监控 |
| 预算告急(剩余 <20%) | 系统即将突破承诺 | 冻结对稳定性有风险的变更 |
| 预算耗尽(剩余 <0%) | 已突破可用性承诺 | 只允许修复性变更,停止新功能发布 |
这个机制的精妙之处:它让"稳定性"和"迭代速度"不再是零和博弈,而是有共同的量化基础。
- 开发想多发版?可以,只要错误预算没花完
- 运维想冻结发版?可以,但必须拿出错误预算数据说话,而不是凭感觉
2.3 落地措施
用 Sloth 或 Pyrra 自动跟踪错误预算(见系列第 2、3 篇),然后在 CI/CD 流水线里加一道门禁:
# CI/CD 发布前检查错误预算
- name: Check Error Budget
run: |
# 查询 Prometheus 获取当前错误预算剩余比例
REMAINING=$(curl -s 'http://prometheus:9090/api/v1/query' \
--data-urlencode 'query=slo:period_error_budget_remaining:ratio{service="payment-service"}' \
| jq -r '.data.result[0].value[1]')
echo "Error budget remaining: ${REMAINING}"
# 低于 20% 时阻止非紧急发版
if (( $(echo "$REMAINING < 0.2" | bc -l) )); then
echo "❌ 错误预算不足(剩余 ${REMAINING}),非紧急变更已冻结"
echo "如需强制发布,请联系 SRE 负责人审批"
exit 1
fi
echo "✅ 错误预算充足,允许发布"这不是理论,是可以在今天就开始实施的机制。
三、维度二:从"手动操作"到"消除 Toil"
3.1 什么是 Toil
Google 对 Toil 的定义:
Toil 是手工的、重复的、可自动化的、战术性的、没有持久价值的、与服务规模成正比的工作。
典型运维 toil:
- 半夜手动扩容
- 手动清理磁盘空间
- 手工配置新环境的监控
- 逐个排查告警误报
- 手动重启卡死的进程
- 周报里手填监控数据
Toil 的危害不是浪费时间,而是消耗注意力。 每天花 2 小时做重复操作的人,没有精力做系统性的改进。然后 toil 越积越多,陷入恶性循环。
3.2 SRE 的目标:Toil < 50%
Google 的标准是 SRE 的 toil 工作不应超过总工作时间的 50%。剩下 50% 应该用于工程自动化、工具开发、可靠性改进。
怎么衡量 toil:
# 手动操作次数(通过告警触发的手动操作统计)
count_over_time(manual_intervention_total[7d])
# 自动化处理比例
1 - (
count_over_time(manual_intervention_total[7d])
/ count_over_time(alertmanager_notifications_total[7d])
)3.3 消除 Toil 的四个步骤
步骤一:记录。 连续两周记录你做的每一件重复性工作,包括次数和耗时。
| 操作 | 频次 | 单次耗时 | 周耗时 | 可自动化 |
|---|---|---|---|---|
| 手动扩容 | 3 次/周 | 15 分钟 | 45 分钟 | ✅ HPA |
| 清理磁盘 | 2 次/周 | 10 分钟 | 20 分钟 | ✅ 脚本 |
| 配置新服务监控 | 1 次/周 | 60 分钟 | 60 分钟 | ✅ ServiceMonitor |
| 告警误报处理 | 5 次/周 | 5 分钟 | 25 分钟 | ✅ 规则优化 |
| 排查日志 | 7 次/周 | 20 分钟 | 140 分钟 | ⚠️ 需要可观测性 |
步骤二:排序。 按"周耗时 × 可自动化程度"排序,优先消除耗时最多且容易自动化的。
步骤三:自动化。 每周消除排名前 1-2 项。
步骤四:度量。 每月统计 toil 占比,确保持续下降。
3.4 自动化不是目的,减少运维的认知负担才是
一个重要区分:自动化和脚本化是两回事。
写一个 shell 脚本 扩容.sh,每次手动跑一下——这是脚本化,不是自动化。因为人还是需要判断什么时候该跑、跑什么参数。
真正的自动化是:
- HPA 根据 CPU/QPS 自动扩缩容,不需要人判断
- Alertmanager + Webhook 自动处理已知故障模式,不需要人介入
- ArgoCD 根据 Git 仓库自动同步状态,不需要人手动 kubectl apply
自动化的标准是:系统能自己做决策并执行,人只在异常时介入。
四、维度三:从"追责"到"复盘改进"
4.1 传统运维的故障处理
故障发生 → 救火恢复 → 找到"责任人" → 写检讨 → 不了了之
这套流程的致命问题:它鼓励隐瞒问题。 如果每次故障都会被追责,团队的本能反应是"能不报就不报,能瞒就瞒"。小问题积累成大故障,最终不可收拾。
4.2 SRE 的故障处理
故障发生 → 救火恢复 → 无责复盘(Blameless Postmortem) → 找出系统性改进措施 → 跟踪到闭环
无责复盘的核心原则:对事不对人。
- 不问"谁的错",问"哪个环节的防护机制失效了"
- 不问"为什么这个人犯了错",问"为什么系统允许这个人犯错"
- 不追究个人责任,追究流程漏洞
4.3 复盘的衡量标准
一个有效的复盘,必须产出以下资产:
| 产出 | 说明 | 可度量 |
|---|---|---|
| 根因 | 技术层面的原因 | 可复现 |
| 改进措施 | 防止同类问题再次发生 | 有负责人和截止日期 |
| 检测改进 | 更快发现同类问题 | 告警规则或 Dashboard |
| 恢复改进 | 更快恢复服务 | 自动止血或 Runbook |
复盘质量的衡量指标:
# 复盘改进措施数量
count(postmortem_action_items{status="open"})
# 改进措施完成率
count(postmortem_action_items{status="done"})
/ count(postmortem_action_items)
# 平均关闭周期(从创建到完成)
avg(postmortem_action_item_age_days)如果复盘开完会后改进措施没人跟踪、没人完成,那这次复盘就是浪费时间。 系列第 8 篇里有完整的复盘文档模板,可以直接用。
五、维度四:从"越稳定越好"到"够用就好"
5.1 稳定性的成本
100% 的可用性是不存在的,而且追求接近 100% 的成本是指数级增长的。
| 可用性目标 | 年允许宕机 | 成本倍数 | 适合场景 |
|---|---|---|---|
| 99% | 3.65 天 | 1x | 内部工具 |
| 99.9% | 8.76 小时 | 2-3x | 一般业务系统 |
| 99.95% | 4.38 小时 | 5-8x | 核心业务系统 |
| 99.99% | 52.6 分钟 | 10-20x | 支付/交易核心 |
| 99.999% | 5.26 分钟 | 50x+ | 极少系统需要 |
从 99.9% 到 99.99%,可用性提升了 0.09%,但成本可能翻了 5-10 倍。这值得吗?
5.2 SRE 的回答:按用户需求设定 SLO
不同服务的 SLO 应该不同:
| 服务类型 | 推荐 SLO | 理由 |
|---|---|---|
| 核心交易链路 | 99.99% | 任何中断直接导致收入损失 |
| 用户面服务 | 99.95% | 影响用户体验但不直接损失收入 |
| 内部管理后台 | 99.9% | 工作时间可用即可 |
| 数据批处理 | 99% | 延迟几小时不影响业务 |
| 测试环境 | 无 SLO | 不对外承诺 |
运维思维是"所有系统都要高可用"。SRE 思维是"按服务重要性分级投入,把资源花在刀刃上"。
5.3 落地措施:SLO 分级矩阵
把所有服务按重要性分成三级,每级对应不同的投入标准:
# SLO 配置分级
services:
# Tier 1:核心交易链路
- name: payment-service
tier: 1
slo:
availability: 99.99%
latency_p99: 200ms
requirements:
multi_az: true # 多可用区部署
min_replicas: 6 # 最少 6 副本
dr_strategy: active-active # 双活灾备
backup_frequency: 1h # 每小时备份
# Tier 2:用户面服务
- name: user-profile-service
tier: 2
slo:
availability: 99.95%
latency_p99: 500ms
requirements:
multi_az: true
min_replicas: 3
dr_strategy: active-passive # 主备灾备
backup_frequency: 6h
# Tier 3:内部服务
- name: admin-dashboard
tier: 3
slo:
availability: 99.9%
latency_p99: 1s
requirements:
multi_az: false
min_replicas: 2
dr_strategy: backup-only # 仅备份
backup_frequency: 24h这个矩阵的价值:让每个服务的投入和它的重要性匹配。 Tier 3 的服务不需要多 AZ 部署和每小时备份,省下来的资源投入 Tier 1 的可靠性保障。
六、维度五:从"运维是开发的下游"到"共享可靠性"
6.1 传统运维的组织困局
传统组织架构里,开发写代码,运维负责让代码跑起来。这种分工的后果:
- 开发不考虑运维难度,写出难以部署、难以监控的代码
- 运维不理解业务逻辑,出了问题不知道影响范围
- 两边互相甩锅:"代码质量太差" vs "运维能力不行"
6.2 SRE 的解法:共享责任
SRE 的组织原则是可靠性是所有人的责任,不是运维一个部门的事。
具体做法:
| 实践 | 说明 |
|---|---|
| 开发写 Runbook | 开发最懂自己的服务,Runbook 应该由开发写、SRE 审核 |
| 开发参与 on-call | 开发轮流参与值班,亲身感受自己写的代码在凌晨 3 点的表现 |
| SLO 是联合制定 | SRE 和开发一起商定 SLO 目标,不是 SRE 单方面拍板 |
| 运维特性纳入 Definition of Done | 一个功能"做完了"的标准必须包含:有监控、有告警、有 Runbook |
6.3 落地措施:发布就绪检查清单
在 CI/CD 流水线里加一道"发布就绪检查",不通过的服务不允许上生产:
# 发布就绪检查清单
production_readiness_check:
# 必须项:不通过则阻止发布
required:
- name: "有健康检查端点"
check: "curl -f http://service:8080/health returns 200"
- name: "有 Prometheus metrics 端点"
check: "ServiceMonitor exists in namespace"
- name: "有 HPA 配置"
check: "HorizontalPodAutoscaler exists for deployment"
- name: "资源 request/limit 已设置"
check: "all containers have resources.requests and resources.limits"
- name: "日志格式为 JSON 且包含 trace_id"
check: "log sample contains valid JSON with trace_id field"
# 建议项:不阻止发布但记录到看板
recommended:
- name: "有 PodDisruptionBudget"
check: "PDB exists for deployment"
- name: "有 Runbook"
check: "runbook annotation exists in alert rules"
- name: "有压测报告"
check: "load test report exists in last 30 days"
- name: "跨 AZ 部署"
check: "podAntiAffinity configured for multi-AZ"这份清单的潜台词:开发要为自己的服务在生产环境的表现负责。 你写的服务如果不能被监控、不能自动扩缩容、没有健康检查,那它就没有准备好上生产。
七、维度六:从"出了几次故障"到"MTTR 和 MTBF"
7.1 传统运维的衡量方式
传统运维最常用的指标是"故障次数"——这个月出了 3 次故障 vs 上个月出了 1 次故障。
这个指标的问题:它只衡量了频率,没有衡量严重程度和恢复速度。
1 次恢复用了 30 分钟的故障,和 1 次恢复用了 4 小时的故障,对用户的影响天差地别。但在"故障次数"这个指标里,它们是一样的。
7.2 SRE 的核心指标
| 指标 | 全称 | 含义 | 改进方向 |
|---|---|---|---|
| MTTR | Mean Time To Recovery | 平均恢复时间 | 降低(更快恢复) |
| MTBF | Mean Time Between Failures | 平均故障间隔 | 提高(更少故障) |
| MTTD | Mean Time To Detect | 平均发现时间 | 降低(更快发现) |
| MTTA | Mean Time To Acknowledge | 平均响应时间 | 降低(更快响应) |
一次故障的完整时间线:
故障发生 → [MTTD] 发现 → [MTTA] 响应 → [MTTR] 恢复
|----------- 用户感知的故障时长 -----------|7.3 怎么改进每个环节
| 环节 | 改进措施 | 工具/实践 |
|---|---|---|
| MTTD(更快发现) | 优化告警规则、引入 SLO 燃烧率告警 | Sloth / Pyrra |
| MTTA(更快响应) | 告警路由优化、Runbook 内嵌在告警里 | Alertmanager |
| MTTR(更快恢复) | 自动止血、一键回滚脚本、降级开关 | 见系列第 8 篇 |
| MTBF(更少故障) | 渐进式发布、灰度/金丝雀、混沌工程 | Argo Rollouts / ChaosMesh |
7.4 用 PromQL 度量
# MTTR(分钟)—— 从告警触发到 resolved 的平均时间
avg(
alertmanager_resolved_time_seconds - alertmanager_fired_time_seconds
) / 60
# MTTD(分钟)—— 从异常开始到告警触发的平均时间
# 需要在应用侧记录异常开始时间,和告警触发时间做差
# 每月故障次数
count_over_time(alertmanager_resolved_total{severity="page"}[30d])
# 错误预算消耗率
1 - slo:period_error_budget_remaining:ratio八、转变路线图:从运维到 SRE 的四个阶段
这不是一蹴而就的。以下是一个 12 个月分阶段推进的路线图。
阶段一:可观测性先行(第 1-3 月)
目标:让你能看到系统在发生什么。
- 部署 kube-prometheus-stack,建立基础监控
- 所有核心服务暴露 RED 指标(Rate/Errors/Duration)
- 部署 Loki,统一日志收集
- 搭建 Grafana 统一面板
验收标准:在 Grafana 上能看到任意服务的 QPS、延迟、错误率。
阶段二:SLO 落地(第 4-6 月)
目标:用量化目标替代"感觉"。
- 为 Tier 1/2 服务定义 SLO
- 部署 Sloth 或 Pyrra 自动跟踪错误预算
- 把 SLO 燃烧率告警替换掉旧的阈值告警
- 在 CI/CD 中加入错误预算检查
验收标准:每次发版前能看到错误预算剩余比例,预算耗尽时自动冻结非紧急变更。
阶段三:自动化(第 7-9 月)
目标:用系统替代人力,消除 toil。
- 所有服务配置 HPA
- 配置存活/就绪探针
- 建设 Alertmanager + Webhook 自动止血
- 推行 GitOps(ArgoCD/Flux),禁止手动 kubectl
- toil 占比降到 50% 以下
验收标准:常规扩缩容和故障恢复不需要人工介入。
阶段四:文化转变(第 10-12 月)
目标:让 SRE 思维成为团队共识。
- 推行无责复盘制度
- 开发参与 on-call 轮值
- 建立发布就绪检查清单
- 每月发布可靠性报告(MTTR、MTBF、错误预算趋势)
- 引入混沌工程,主动验证系统韧性
验收标准:复盘改进措施完成率 >80%,开发团队主动关注 SLO 达成情况。
九、六个常见误区
在转变过程中,以下误区是最常见的:
误区一:"SRE 就是高级运维"
错。 SRE 是软件工程师,核心能力是用代码解决运维问题。如果一个"SRE"每天的工作是手动操作而不是写代码、建系统,那他做的事情还是运维。
误区二:"有了 SRE 就不需要运维了"
错。 SRE 解决的是规模化和自动化的问题。日常的基础设施维护、容量管理、工单处理仍然需要运维角色。SRE 和运维是互补的,不是替代的。
误区三:"SLO 是 SRE 定的"
错。 SLO 是产品和业务方共同制定的承诺。SRE 的角色是提供数据支撑和技术可行性评估,但 SLO 的目标值必须由业务方拍板——因为他们要为承诺的可用性向用户负责。
误区四:"上了 Prometheus 就是 SRE 了"
错。 工具是 SRE 实践的载体,不是 SRE 本身。用 Prometheus 做监控但没有 SLO、没有错误预算、没有自动化,那只是"用新工具做老事情"。
误区五:"SRE 就是 DevOps"
不完全对。 DevOps 是一种文化和理念(开发运维协作),SRE 是一套具体的实践方法论(有明确的原则和工具链)。DevOps 是"做什么",SRE 是"怎么做"。Google 自己的说法是:"SRE 是 DevOps 的一种具体实现。"
误区六:"错误预算就是 SLO"
不完全对。 SLO 是目标(比如 99.9% 可用),错误预算是管理工具(那 0.1% 怎么花)。很多团队定义了 SLO 但没有利用错误预算做决策,那 SLO 就只是一个挂在墙上的数字。
十、怎么衡量转变是否成功
最后,用一组指标来衡量你的团队是否真正完成了从运维到 SRE 的转变:
| 指标 | 运维状态 | 过渡状态 | SRE 状态 |
|---|---|---|---|
| SLO 覆盖率 | 0% | 核心服务有 | >80% 服务有 SLO |
| 错误预算使用 | 不知道有多少 | 知道但不用来决策 | CI/CD 门禁 + 决策依据 |
| toil 占比 | >70% | 50-70% | <50% |
| MTTR | >60 分钟 | 15-60 分钟 | <15 分钟 |
| 自动扩缩容覆盖率 | 0% | 部分服务 | >90% |
| 复盘改进完成率 | 不复盘 | 开会但不跟踪 | >80% 措施闭环 |
| 发布就绪检查 | 无 | 人工 checklist | CI/CD 自动化检查 |
| 开发参与 on-call | 否 | 极少数 | 是,轮值制度 |
不要试图一夜之间把所有指标从左列变成右列。 按阶段路线图逐步推进,每个季度推进 2-3 项,12 个月后回头看,你会发现自己团队的运作方式已经完全不同了。
写在最后
从运维到 SRE 的转变,本质上是从经验驱动到数据驱动、从人力驱动到系统驱动、从被动响应到主动工程的转变。
这个转变的核心不是更换工具——虽然工具确实会换。核心是思维方式的转变:
- 不再问"出了故障谁负责",而是问"系统哪里有漏洞"
- 不再追求"绝对不宕机",而是追求"可控的、有预算的可靠性"
- 不再靠"加班加点"保证稳定,而是靠"自动化和工程化"保证稳定
- 不再把运维当"开发的下游",而是共享可靠性责任
工具可以买,流程可以抄,但思维方式的转变只能靠自己。
从今天开始,做一件事:为你负责的最重要的服务定义一个 SLO。不需要完美,先定义出来,然后开始用错误预算做决策。这就是 SRE 转变的第一步。
本文是 SRE 实战系列第 9 篇,也是系列的方法论总纲。系列前 8 篇覆盖了 SLO 落地、Sloth/Pyrra 工具实战、告警治理、监控存储选型、K8s 可观测性全景图、云成本优化、on-call 生存指南。本文把这些散落的实践串成一条线——它们都是同一种思维方式的不同切面。