跳过正文
SRE 实践心得:从运维到 SRE 的思维转变

SRE 实践心得:从运维到 SRE 的思维转变

·531 字·3 分钟·
目录
SRE 实战手册 - 这篇文章属于一个选集。
§ : 本文

运维 vs SRE:不是换个名字
#

我见过很多团队把运维部门改名叫 SRE,然后继续干一样的事。这不是 SRE。

传统运维的核心关注点是"系统现在还活着吗",被动响应告警,追求零停机,害怕变更。SRE 的核心关注点是"我们能在多大程度上接受不可靠,换来更快的交付速度",主动设计可靠性,把停机当成正常的事情来管理。

最根本的差异在于两件事:

1. SRE 用数据说话:不是"感觉稳定性还不错",而是"过去 30 天 P99 延迟 < 200ms 的时间占比是 99.8%"。

2. SRE 把可靠性当成功能来交付:就像开发要交付业务功能,SRE 要交付可靠性功能——监控、告警、自动恢复、灾难演练。


SLI/SLO/SLA:从模糊到量化
#

三个概念的关系
#

  • SLI(Service Level Indicator):衡量服务质量的具体指标。比如"成功请求比例"、“P99 延迟”。
  • SLO(Service Level Objective):对 SLI 设定的目标。比如"成功率 ≥ 99.9%"、“P99 延迟 ≤ 500ms”。
  • SLA(Service Level Agreement):对外承诺的协议,通常比 SLO 宽松,违反了有赔偿。

关系:SLI 是测量,SLO 是内部目标,SLA 是外部承诺。先有 SLO,才能谈 SLA。

如何定义你的服务 SLO
#

步骤一:找到用户最在意的体验,转化为 SLI。

用户在意:页面打开快不快
→ SLI:HTTP 请求成功率 & P95/P99 延迟

用户在意:数据准不准
→ SLI:数据处理任务的成功率

用户在意:功能能不能用
→ SLI:核心功能的可用率(用探针定期检测)

步骤二:基于历史数据设定合理目标,不要拍脑袋。

# 用 Prometheus 查过去 30 天的实际 P99 延迟
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket{job="api-server"}[30d])) by (le)
)

# 查历史成功率
sum(rate(http_requests_total{status!~"5.."}[30d]))
/
sum(rate(http_requests_total[30d]))

步骤三:SLO 要比当前实际情况稍微严一点,但不能太严。

如果历史成功率是 99.95%,SLO 设 99.99% 是在给自己挖坑。SLO 应该是"用户开始不满意的临界点",不是"我们技术上能做到的极限"。

Prometheus 告警规则示例
#

# 基于 SLO 的告警(而不是简单阈值)
groups:
  - name: slo-alerts
    rules:
      # 错误率告警(1小时窗口,快速告警)
      - alert: HighErrorRateFast
        expr: |
          (
            sum(rate(http_requests_total{status=~"5..",job="api-server"}[1h]))
            /
            sum(rate(http_requests_total{job="api-server"}[1h]))
          ) > 0.01
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "API 错误率超过 1%(1小时窗口)"
          description: "当前错误率 {{ $value | humanizePercentage }},SLO 目标 0.1%"

      # 延迟告警
      - alert: HighLatencyP99
        expr: |
          histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket{job="api-server"}[5m])) by (le)
          ) > 0.5
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "P99 延迟超过 500ms"

错误预算:用数据说服业务方
#

什么是错误预算
#

SLO 是 99.9%,那错误预算就是 0.1%。一个月(43800 分钟)里,允许不可用 43.8 分钟。

错误预算的妙处在于:它把可靠性从"工程问题"变成了"资源分配问题"

发布新功能有风险,可能消耗错误预算。如果预算还很充裕,发!如果预算快耗完了,先稳定再迭代。这个决策不再是"运维说不能发",而是"数据说我们还有多少余量"。

错误预算燃尽率告警(Burn Rate)
#

单纯看错误率不够,还要看消耗速度。如果按当前速度继续,30 天的预算在 3 天内就会耗尽,那必须立刻处理,即使当前错误率看起来不高。

# 错误预算消耗速率告警
- alert: ErrorBudgetBurnRate
  expr: |
    (
      # 1小时窗口的消耗速率
      (1 - sum(rate(http_requests_total{status!~"5.."}[1h])) / sum(rate(http_requests_total[1h])))
      /
      0.001  # SLO 是 99.9%,错误预算是 0.1%
    ) > 14.4  # 14.4x 意味着 1小时内消耗了72小时的预算
  for: 2m
  labels:
    severity: critical
  annotations:
    summary: "错误预算消耗速率过高"
    description: "按当前速率,30天错误预算将在 {{ 30 / $value | humanizeDuration }} 内耗尽"

这个 14.4 怎么来的:如果 1 小时内消耗速率是正常的 14.4 倍,意味着 30 天的预算在 30/14.4 ≈ 2 天内耗尽,属于紧急情况。


Toil:识别并消除重复劳动
#

什么是 Toil
#

Google SRE 对 Toil 的定义很精确:

  • 手动的:需要人工触发或干预
  • 重复的:同样的事情反复做
  • 可自动化的:理论上可以用代码替代
  • 没有持久价值的:做完不留下改进,下次还要做同样的事

不是所有繁琐工作都是 Toil。设计新的监控告警规则是有价值的工程工作,不是 Toil。每次发布手动去检查 10 个 Dashboard 确认健康,是 Toil。

量化 Toil
#

# 简单但有效:让团队每周记录花在 Toil 上的时间
# Toil 时间 / 总工作时间,SRE 建议不超过 50%

# 常见 Toil 类型统计(示例)
# 手动扩容:每次 10-15 分钟,每周 3-5 次
# 日志手动查询:每次 20 分钟,每天 2-3 次
# 证书手动续期:每次 30 分钟,每季度 10+ 次
# 数据库慢查询手动分析:每次 1 小时,每周 1-2 次

消除 Toil 的优先级
#

高频 + 高时间成本 = 立刻自动化。

# 示例:手动扩容 → HPA 自动扩容
kubectl autoscale deployment api-server \
  --cpu-percent=70 \
  --min=3 \
  --max=50

# 示例:证书手动续期 → cert-manager 自动续期
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

Blameless Postmortem 文化
#

这是 SRE 实践中落地最难的部分,因为它要改变组织文化,而不只是技术流程。

为什么 Blameless 这么难
#

人类天然倾向于找替罪羊。故障后问"谁干的",比问"系统为什么允许这件事发生"容易得多,也更有情绪宣泄感。

但追责文化的后果是灾难性的:

  • 人们开始隐瞒问题,避免被追责
  • 本可以早发现的问题被压着,直到爆发成更大故障
  • 团队失去心理安全感,没人愿意承担有风险的改进工作

实践 Blameless 的关键
#

1. 把"人为错误"当成症状,不是根因

“工程师执行了错误的命令” 不是根因。根因是"为什么系统允许这个命令被执行而没有任何保护"。

2. 区分个人能力问题和系统设计问题

极少数情况下是纯粹的个人能力问题。大多数故障是系统设计给人挖的坑(文档不清、没有二次确认、缺少防护机制)。

3. 复盘会议的话术

❌ "你为什么没有检查这个配置?"
✓  "这个检查步骤是否应该加入自动化流程或 Checklist?"

❌ "这个人不适合干这个工作"
✓  "我们的 Runbook 是否清晰到让任何人都能正确执行这个操作?"

可靠性与速度的平衡
#

这是 SRE 存在的根本张力:开发想快速发布,SRE 想保持稳定,怎么协调?

错误预算是最好的协调工具(前文已述)。但还有几个实践值得提:

渐进式发布(Progressive Delivery)
#

# 用 Argo Rollouts 做金丝雀发布
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
  strategy:
    canary:
      steps:
        - setWeight: 5      # 先放 5% 流量
        - pause: {duration: 10m}
        - setWeight: 20
        - pause: {duration: 10m}
        - setWeight: 50
        - pause: {duration: 10m}
        - setWeight: 100
      analysis:
        templates:
          - templateName: success-rate
        startingStep: 2
        args:
          - name: service-name
            value: api-server

功能开关(Feature Flag)
#

# 用 LaunchDarkly 或自己实现简单的功能开关
def process_payment(user_id: str, amount: float):
    if feature_flag.is_enabled("new_payment_flow", user_id):
        return new_payment_processor.process(user_id, amount)
    else:
        return legacy_payment_processor.process(user_id, amount)

功能开关让发布和功能上线解耦——代码发出去了,功能还没打开,有问题可以立刻关掉,不需要回滚。


实践建议:从哪里开始
#

很多团队说"我们要做 SRE",然后不知道从哪下手。我的建议是从最痛的地方开始,而不是从最"SRE"的地方开始:

第一步:定义一个 SLO,哪怕只有一个
#

找到你们最核心的服务,定义一个 SLI,设一个 SLO。用 Prometheus + Grafana 把它可视化出来。

这一步看起来简单,但它逼着团队回答"用户最在意什么"这个问题,往往会引发很有价值的讨论。

第二步:记录 Toil,量化它
#

让团队在下周开始记录自己花在 Toil 上的时间。不需要 100% 精确,大概就行。

拿到数据后,选最耗时的一项 Toil,两周内把它自动化掉。让团队感受到"原来减少 Toil 是真的可以做到的"。

第三步:做一次认真的故障复盘
#

找一个最近的、有代表性的故障(不需要是 P0),严格按照 Blameless 原则做一次复盘,输出清晰的行动项,并跟踪完成。

关键是跟踪完成。很多团队开复盘会、写报告,然后行动项在任务系统里尘封。跟踪落实才是建立可靠性改进文化的核心。

不要一步到位
#

SRE 转型是一个 2-3 年的过程,不是一个季度就能完成的事。先把 Toil 降下来,让团队有时间做有价值的工作;先把 SLO 建起来,让可靠性有了度量;先有一次好的复盘,让团队感受到 Blameless 文化的价值。

工具和流程是次要的,文化和思维方式才是核心。一个有 SRE 文化的团队,用烂工具也能做好可靠性;一个没有 SRE 文化的团队,用最好的工具也是徒劳。

Wenzhuo Huang
作者
Wenzhuo Huang
搞运维的工程师,写代码的运维人。专注 Kubernetes、AWS、GitOps 与基础设施可靠性。这个博客既是我的技术笔记本,也是我踩过的坑的受害者档案。
SRE 实战手册 - 这篇文章属于一个选集。
§ : 本文

相关文章

可观测性建设:从 Prometheus 采集到 Grafana 告警联动

·861 字·5 分钟
可观测性不是装几个监控工具,而是让系统在出问题时能快速定位根因。这篇文章从采集架构到 PromQL 到告警路由,覆盖我们在生产环境中实际遇到的 cardinality 爆炸、告警噪音等问题。

Python 自动化运维:从脚本到完整工具的工程化实践

·1559 字·8 分钟
系统梳理 Python 运维自动化的工程化方法:boto3 操作 AWS 资源、Kubernetes Python SDK 使用、Click/Typer CLI 框架选型、数据库批量运维脚本、钉钉 Webhook 集成,以及类型注解与错误处理的实践经验。