路线图

06 自动化工程

星辉 2026-07-02 阅读 4 min 732 字 路线图
06 自动化工程 封面

概述#

SRE 把 50% 以上的工作时间投入"工程"——不是写业务代码,而是构建让运维工作自动化的软件系统。本章讲清楚自动化工程的演进路径、核心原则,以及如何避免"自动化本身变成新的 toil"。

自动化工程的本质是把 SRE 的时间从"做操作"转向"写做操作的代码"。这不是"偷懒",是把人力从重复劳动中解放出来,投入到只有人能做的创造性工作——架构设计、根因分析、可靠性工程。

一、自动化演进阶梯#

自动化不是"要么有要么无",而是几个渐进的层次:

text
Level 0  手动操作         ← 纯人工,依赖经验和记忆力
Level 1  文档化操作        ← 有 Runbook,但操作还是人手做
Level 2  脚本化            ← 有一次性脚本,但参数硬编码
Level 3  自动化工具        ← 可复用工具,参数化、可审计
Level 4  自愈系统          ← 系统检测到异常自动修复,无需人工介入

每一层的特征#

Level操作者可重复性审计典型形态出错概率
L0 手动每次不同SSH 上去 kubectl delete pod高(凭记忆)
L1 文档化人(按 runbook)基本一致Wiki 里的操作手册中(可能漏步骤)
L2 脚本化人触发脚本一致有限bash 脚本 restart-service.sh低(脚本是固定的)
L3 自动化系统/人触发一致完整CI/CD 流水线、GitOps极低(有 review)
L4 自愈系统自动一致完整HPA 自动扩缩、Pod 自动重建极低(但需监控)

目标不是让所有人都到 L4——L4 只在合适的场景下做。但至少要让重复频率高的操作达到 L3。

每一层的过渡难点#

L0 → L1:需要把"默会知识"显性化。老员工的"直觉"必须变成可写的步骤。难点在于有经验的人没时间写文档。

L1 → L2:需要把文档变成代码。难点是脚本维护——环境变了脚本就坏了,没人修就废了。

L2 → L3:需要从"个人脚本"变成"团队工具"。难点是规范化:参数化、错误处理、日志、审计。很多脚本卡在 L2 是因为"只有作者能跑"。

L3 → L4:需要从"人触发"变成"系统触发"。难点是判断逻辑——什么时候该自动执行、什么时候该升级到人。这是最难的一步,需要大量数据积累和调优。

哪些应该到 L4(自愈)#

  • 服务进程 crash → K8s 自动重启(liveness probe + restartPolicy)
  • 流量突增 → HPA / KEDA 自动扩容
  • 节点不可用 → Cluster Autoscaler / Karpenter 自动替换
  • 证书过期 → cert-manager 自动续签
  • 磁盘满 → 自动清理日志或扩容 PVC
  • 数据库主库故障 → 自动 failover(如 Orchestrator、Patroni)

哪些 L3 就够了#

  • 服务发布 → CI/CD 流水线触发,有人确认
  • 配置变更 → GitOps PR + approve + sync
  • 数据库迁移 → 自动化执行但有审批关卡
  • 紧急回滚 → 一键脚本但需要人决策

哪些应该留在 L1/L2#

  • 季度容量规划 review → 需要人判断
  • 跨团队协调的迁移 → 复杂决策
  • 新服务的架构设计 → 创造性工作
  • Postmortem 复盘 → 需要人分析

二、自动化工程的核心原则#

1. Automation over Operation#

Google SRE 的核心理念:宁可花 10 小时写自动化工具,也不花 5 分钟手做第 10 次同样的操作

判断标准:一个操作如果预计未来一年要做超过 10 次,自动化就值得。公式:

text
自动化 ROI = (单次手动耗时 × 预计操作次数) / 开发时间

如果 ROI > 3,优先级高
如果 ROI > 10,立刻做
如果 ROI < 1,不做(手动更划算)

举例:每次手动扩容 15 分钟,预计一年要做 50 次,写自动化脚本要 4 小时。

text
ROI = (15min × 50) / (4h × 60min) = 750 / 240 ≈ 3.1

ROI > 3,应该做。但还要考虑隐性收益:自动化后误操作概率降低、可以夜间执行、可以并行多服务。

2. 自动化是软件工程,不是写脚本#

自动化代码需要:

  • Code Review:和业务代码一样的审查流程
  • 测试:不只是在测试环境跑一次,要有回归测试
  • 版本管理:进 Git,可回滚
  • 文档:为什么这样设计、边界条件是什么
  • 告警:自动化工具自己挂了要知道
  • SLO:自动化工具也是服务,有自己的可靠性目标

很多团队的自动化脚本"能跑就行",没有 review 没有测试。结果是脚本越积越多,每个都有 bug,没人敢动——自动化变成了新的 tech debt。

3. 工具化思维#

不要为每个任务写独立脚本,要构建可复用的工具平台。比如:

  • ❌ 为 A 服务写扩容脚本,为 B 服务又写一个类似的
  • ✅ 构建一个扩容框架,A 和 B 通过参数配置接入

工具化的核心是关注点分离

text
通用框架(处理流程、错误、日志、审计)
   +
具体配置(每个服务的参数)
   =
可复用工具

4. 渐进式自动化#

不要试图一次性自动化所有事情。按优先级队列:

text
1. 最频繁的 toil(每天多次)→ 立刻自动化
2. 高风险的人为误操作(生产误删除)→ 加安全护栏 + 自动化
3. 复杂但稳定(发布流程)→ 逐步自动化
4. 低频简单操作(季度清理)→ 有个 Runbook 就好,不用自动化

5. 自动化优先于流程#

很多团队遇到"频繁出错"的反应是"加审批流程"——增加 review 节点、加审批人、加 sign-off。这是错误的方向。

text
频繁出错 → 加流程 → 操作变慢 → toil 增加 → 没时间做自动化 → 继续出错

正确方向:

text
频繁出错 → 自动化 → 操作标准化 → 出错概率下降 → 释放时间做更多自动化

流程不能消除错误,自动化才能。流程只让错误"更慢地发生"。

三、自愈系统设计模式#

模式 1:观测-决策-执行闭环#

text
Sensor(传感器) → Analyzer(分析器) → Actuator(执行器)
      ↑                                        |
      └──────────── 反馈验证 ──────────────────┘
  • Sensor:Prometheus 指标、日志异常检测
  • Analyzer:告警规则、SLO burn rate 条件
  • Actuator:K8s operator、自动化脚本

关键:执行器动作后,Sensor 必须验证效果。如果执行了没效果,要降级到人工介入。

举例:HPA 自动扩容流程

text
Sensor: CPU 使用率 > 70%
Analyzer: HPA 判断需要扩容
Actuator: 创建新 Pod
Sensor: 5 分钟后 CPU 是否下降?
  ↓ 是 → 扩容成功,记录
  ↓ 否 → 继续扩容 + 告警人工介入

模式 2:渐进式自治#

text
Step 1: 检测 + 建议("检测到问题,建议执行 X")
Step 2: 检测 + 自动执行(但保留人工撤销能力)
Step 3: 检测 + 自动执行 + 自动验证(全自动)

不要一步跳到全自动。先在非生产环境跑 Step 1 至少一个月,确认建议都是正确的,再逐步放开。

Google SRE Book 推荐的"自动化成熟度"演进:

  • 第 1 个月:系统检测到问题,发通知给人,人处理
  • 第 2-3 个月:系统检测到问题,给出建议操作,人确认后系统执行
  • 第 4-6 个月:系统自动执行,但每次都通知人
  • 第 7 个月+:系统自动执行,只在异常时通知人

模式 3:安全护栏#

任何自动执行操作必须满足:

  • 爆炸半径限制:一次只影响最小范围(如 HPA 一次最多扩 N 个 pod)
  • 回滚能力:自动化操作可撤销
  • 熔断机制:连续失败 N 次自动停止
  • 审计日志:谁/什么/何时/做了什么操作
  • 速率限制:单位时间内操作次数上限(避免雪崩)
  • 干运行模式:可以先 dry-run 看会做什么,不真执行

模式 4:分层自治#

不同层级的故障用不同层级的自愈:

text
应用层(业务 bug)        → 重启 pod / 回滚版本
基础设施层(节点故障)     → 重新调度 pod / 替换节点
网络层(连接异常)        → 重试 / 切换备用
数据层(DB 慢)           → 限流 / 降级 / 读副本
依赖层(下游挂)          → 熔断 / 降级

每层自治能力独立设计,避免"一个层级的故障触发其他层级的错误自愈"。

四、自动化工具的工程实践#

自动化工具的代码结构#

一个合格的自动化工具应该有:

python
# 伪代码示例
def autoscale_service(service_name, target_replicas):
    # 1. 前置检查
    if not validate_service_exists(service_name):
        raise ServiceNotFoundError(service_name)
    
    current = get_current_replicas(service_name)
    
    # 2. 安全护栏
    if target_replicas > MAX_REPLICAS:
        raise SafetyViolationError(f"超过最大副本数 {MAX_REPLICAS}")
    
    if target_replicas > current * MAX_SCALE_UP_RATIO:
        logger.warning(f"扩容比例过大,需要人工确认")
        notify_human_for_approval(service_name, target_replicas)
        return
    
    # 3. 执行
    try:
        scale_service(service_name, target_replicas)
    except Exception as e:
        # 4. 失败处理
        logger.error(f"扩容失败: {e}")
        emit_alert(f"autoscale_failed: {service_name}")
        return
    
    # 5. 验证
    wait_for_ready(service_name, target_replicas, timeout=300)
    
    # 6. 审计
    audit_log(
        action="autoscale",
        service=service_name,
        from_replicas=current,
        to_replicas=target_replicas,
        timestamp=now(),
        trigger="automatic"
    )

自动化工具的测试#

自动化工具必须有测试,否则就是"用 bug 修 bug":

  • 单元测试:每个函数的行为
  • 集成测试:和真实系统的交互(在测试环境)
  • 混沌测试:故意注入故障,看工具是否正确处理
  • 回归测试:每次改动后跑全量测试

测试覆盖率建议:核心逻辑 > 80%,辅助代码 > 50%。

自动化工具的监控#

自动化工具自己也是服务,需要:

  • 健康检查(liveness/readiness)
  • 执行成功率监控
  • 执行时长监控
  • 失败告警
  • 自身的 SLO(如"扩容成功率 > 99%")

一个挂了的自动化工具比没有自动化更危险——它会让你以为问题被处理了,实际没有。

五、常见陷阱#

陷阱 1:自动化过度#

自动化了"每月操作一次、每次 5 分钟"的任务,但维护这个自动化每月要花 2 小时。投入产出倒挂。

判断标准:自动化 ROI = 节省的 toil 时间 / (开发时间 + 维护时间 × 12)。如果 ROI < 1,不要自动化。

陷阱 2:自动化没有告警#

自动化工具自己挂了没人知道。任何自动化组件都需要监控——和业务服务一样配健康检查和告警。

更糟糕的情况:自动化工具"半挂"——没完全死但行为异常。这种问题最难发现。需要监控的不仅是"工具是否运行",还有"工具的输出是否正常"。

陷阱 3:自动化 = 自愈的错觉#

"我配了 HPA"不等于"容量问题是自愈的"。HPA 扩容需要时间(pod 启动、JIT 预热),在扩容窗口内流量仍然可能打挂服务。真正的自愈需要预热机制、连接池预热、限流兜底。

陷阱 4:把流程变成了自动化#

手动审批流程 + 自动执行 ≠ 自动化。正确做法是:如果这个操作足够安全,把审批去掉;如果不安全,先加安全护栏再加自动化。

陷阱 5:自动化脚本变成"只有作者能跑"#

很多团队的自动化脚本卡在 L2,原因是脚本没有规范化:

  • 参数硬编码
  • 依赖特定环境变量
  • 没有错误处理
  • 没有日志
  • 没有文档

作者离职后脚本就废了。规范化要求:所有自动化脚本必须满足团队级的代码标准,进 Git,有 README,有测试。

陷阱 6:自动化加剧了单点故障#

"自动化了 = 这个人不用做了"——但如果只有这个人懂自动化工具的工作原理,工具本身就是单点。需要让多人理解工具,文档完整,能接手维护。

陷阱 7:自动化绕过了变更管理#

自动化执行的操作如果不在变更管理系统里记录,等于"看不见的变更"。所有自动化操作必须写审计日志,并接入变更管理流程。

六、自动化的组织维度#

谁来写自动化#

三种模式:

  1. SRE 自己写:SRE 团队既做运维也做自动化工程。优点:贴近实际需求;缺点:人少时优先级被运维挤掉。
  2. 工具团队写:有专门的工具/平台团队,SRE 提需求。优点:工程能力强;缺点:离实际运维远,需求理解偏差。
  3. 混合模式:通用工具由工具团队做,业务特定的自动化由 SRE 写。这是 Google 的模式,也是大多数成熟团队的模式。

自动化的接受度#

写了自动化工具,但团队不用——这是常见问题。原因:

  • 工具不好用(UI 差、文档烂)
  • 团队习惯了手动操作("老方法更可靠")
  • 工具出过 bug,失去信任
  • 没有强制使用的规定

解决:

  • 让团队参与工具设计(不是 SRE 自己拍)
  • 工具先在 SRE 内部用,稳定后推给开发
  • 出 bug 要快速修复,重建信任
  • 把"使用自动化工具"写进团队规范

实战要点#

  1. 统计 Toil 频率是自动化规划的前提。不知道哪些操作最频繁,就无法排优先级。每月做一次 toil 来源分析。
  2. 写自动化代码的生产标准 = 写业务代码的标准。Code Review、测试、文档一个不能少。
  3. 自愈系统从建议模式开始。先让系统"告诉你该做什么",确认无误再让它"帮你做"。
  4. 自动化工具也是服务,需要监控、告警、SLO。自动化工具挂了的风险等同于业务服务挂了。
  5. 渐进式上 Level。不要直接从 L1 跳到 L4——每跳一级都要充分验证。
  6. 每个自动化操作都要有审计日志。谁/什么/何时/做了什么,必须可追溯。
  7. 自动化优先于流程。流程不能减少错误,只能让错误更慢发生。自动化才能从根本上减少错误。
  8. ROI 低于 1 的不要自动化。低频简单操作有 Runbook 就好,过度自动化是浪费。
  9. 保留人工介入路径。任何自动化都必须有"我需要人来看"的升级机制——不能让自动化"自己一路走到黑"。

小结#

自动化工程的本质是把 SRE 的时间从"做操作"转向"写做操作的代码"。演进阶梯(手动→文档→脚本→自动化→自愈)是规划蓝图。

记住核心等式:自动化 ROI = 节省的 Toil 时间 / 开发时间。ROI 高的优先做,ROI 低的留 Runbook。

判断一个团队的自动化成熟度,看三件事:高频操作是否都到 L3+、自动化工具是否被监控、自愈系统是否从建议模式演进到执行模式。三件事都做到是成熟团队;只做到一两件是在路上;一件都没做,那 50% toil 上限就是空话。

下一章进入可观测性——有了工程时间,怎么用指标和告警做可靠性决策。