技术博客

K8s 可观测性黄金法则:RED/USE 方法与 SLO 实战

系统讲解生产可观测性体系的方法论与实践:RED 方法(Rate/Error/Duration)面向用户服务监控、USE 方法(Utilization/Saturation/Error)面向基础设施资源监控、SLO(服务等级目标)设计与错误预算计算、Prometheus 中的 SLI 指标配置、AlertManager 基于错误预算的告警策略,帮助从"指标收集"升级到"面向 SLO 的可观测性体系"。

SLO可观测性REDUSEPrometheusKubernetes监控告警

很多团队有 Prometheus + Grafana,却仍然靠用户报障发现问题。原因在于:指标收集了很多,但没有方法论指导“监控什么、告什么警、怎么定义服务健康”。本文讲解 RED/USE 两个方法论,以及如何用 SLO(服务等级目标)让告警真正面向用户体验。

可观测性的三个层次

Level 1:收集指标(大多数团队在这里)
  Prometheus 收集 CPU、内存、QPS
  问题:指标太多,不知道该看哪个;CPU 高不代表用户有问题

Level 2:方法论驱动监控(RED + USE)
  用 RED 方法监控服务;用 USE 方法监控资源
  优点:清晰的分层,知道该看什么

Level 3:面向 SLO 的可观测性(目标导向)
  用 SLO 定义"服务正常"的标准;用错误预算决定告警优先级
  优点:告警和用户体验直接挂钩,避免告警疲劳

一、RED 方法(面向服务)

RED 方法由 Weaveworks 的 Tom Wilkie 提出,专门用于监控微服务健康状态。每个服务必须监控三个维度:

R - Rate(请求速率):
  每秒有多少请求进入这个服务?
  下降可能意味着流量切走了或服务宕机

E - Error(错误率):
  每秒有多少请求失败?
  包括:HTTP 5xx、超时、业务逻辑错误

D - Duration(响应时长):
  请求需要多长时间才能完成?
  通常关注 P50/P90/P99(Histogram)

RED PromQL 实战

# === 订单服务(order-service)的 RED 指标 ===

# R - Rate(QPS)
sum(
  rate(http_requests_total{service="order-service"}[5m])
)

# 细分(by status_code 看流量分布)
sum by (status_code) (
  rate(http_requests_total{service="order-service"}[5m])
)

# E - Error Rate(错误率)
sum(rate(http_requests_total{service="order-service", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="order-service"}[5m]))
* 100

# E - Error Count(每分钟错误数,用于告警)
sum(increase(http_requests_total{service="order-service", status=~"5.."}[1m]))

# D - Duration P50/P95/P99
histogram_quantile(0.99,
  sum by (le) (
    rate(http_request_duration_seconds_bucket{service="order-service"}[5m])
  )
)

# D - Duration 均值(对比 P99 判断长尾问题)
sum(rate(http_request_duration_seconds_sum{service="order-service"}[5m]))
/
sum(rate(http_request_duration_seconds_count{service="order-service"}[5m]))

RED Dashboard 布局

Grafana 订单服务 RED Dashboard:

第一行(概览 Stat):
  [当前 QPS] [错误率 %] [P99 延迟 ms] [P50 延迟 ms]
  
第二行(时序趋势):
  [QPS 趋势 - by status_code(200/5xx/4xx 分色)]
  [延迟趋势 - P50/P90/P99 三条线]
  
第三行(详细分解):
  [Top 10 最慢接口(Table)] [错误类型分布(Bar)]
  
第四行(下钻):
  [按实例的 QPS(判断负载是否均匀)]
  [按接口的错误率(找到出错的 API)]

二、USE 方法(面向基础设施)

USE 方法由 Brendan Gregg 提出,专门用于监控系统资源(CPU、内存、磁盘、网络等):

U - Utilization(利用率):
  资源被使用的比例(0-100%)
  例:CPU 使用率 75%,磁盘 IO 利用率 60%

S - Saturation(饱和度):
  资源是否超出容量,是否在排队等待
  例:CPU run queue 长度 > 1(有进程在等待 CPU)
      磁盘 IO 等待时间增加(IO 排队)

E - Error(错误):
  资源级别的错误
  例:网络丢包率、磁盘读写错误数、内存 ECC 纠错次数

USE PromQL 实战

# === Kubernetes 节点 USE 指标 ===

# CPU - Utilization(利用率)
1 - avg by (node) (
  rate(node_cpu_seconds_total{mode="idle"}[5m])
)

# CPU - Saturation(饱和度:运行队列长度)
# 运行队列 > CPU 核数 说明 CPU 有排队
node_load1{} > on(instance) count by (instance) (
  node_cpu_seconds_total{mode="idle"}
)

# Memory - Utilization
1 - (
  node_memory_MemAvailable_bytes
  /
  node_memory_MemTotal_bytes
)

# Memory - Saturation(page fault 率,内存压力大时增加)
rate(node_vmstat_pgmajfault[5m])  # major page fault(换页次数)

# Disk - Utilization(IO 利用率)
rate(node_disk_io_time_seconds_total{device!~"sr.*"}[5m])

# Disk - Saturation(IO 等待时间)
rate(node_disk_io_time_weighted_seconds_total[5m])  # 越大越饱和

# Network - Utilization(带宽使用)
rate(node_network_receive_bytes_total{device!="lo"}[5m]) * 8  # 转换为 bps

# Network - Error(丢包率)
rate(node_network_receive_errs_total[5m])
+
rate(node_network_transmit_errs_total[5m])
# === Kubernetes Pod / Container USE ===

# CPU - Utilization
rate(container_cpu_usage_seconds_total{container!=""}[5m])
/
container_spec_cpu_quota{container!=""} * container_spec_cpu_period{container!=""}

# Memory - Utilization
container_memory_working_set_bytes{container!=""}
/
container_spec_memory_limit_bytes{container!=""} > 0

# Memory - Saturation(OOM Kill 次数)
increase(container_oom_events_total[1h]) > 0

三、SLO 体系设计

SLO(Service Level Objective,服务等级目标)是团队承诺的服务质量标准。SLO 是告警的依据,而不是随意设定的阈值。

概念层次:
  SLA(Service Level Agreement):
    与客户签订的合同(例如:月可用率 99.9%,违约赔偿)

  SLO(Service Level Objective):
    内部目标(比 SLA 更严,为 SLA 留 buffer)
    例:内部目标 99.95%,SLA 承诺 99.9%

  SLI(Service Level Indicator):
    度量 SLO 的具体指标(PromQL 表达式)
    例:SLO 是"可用率 99.95%",SLI 是"成功请求 / 总请求"

  错误预算(Error Budget):
    1 - SLO = 允许失败的比例
    99.9% SLO → 0.1% 错误预算 → 30 天内允许失败 43.2 分钟
    
  错误预算耗尽速率(Burn Rate):
    当前错误率与 SLO 允许错误率的比值
    Burn Rate = 1 → 预算刚好用完
    Burn Rate = 14.4 → 1 小时内烧完 1 个月的预算(紧急告警)

SLI 设计

# 不同类型服务的 SLI 选择:

# HTTP 服务(可用性):
SLI = 成功请求数 / 总请求数
成功定义:HTTP 200-499(5xx 是失败,4xx 是客户端问题,通常不计入 SLO)

# HTTP 服务(延迟):
SLI = P99 < 500ms 的请求比例
成功定义:响应时间 < 500ms 的请求

# 数据管道(新鲜度):
SLI = 数据延迟 < 5min 的比例
成功定义:上游数据到达时间 - 预期时间 < 5min

# 批处理作业(成功率):
SLI = 成功完成的作业数 / 总作业数

Prometheus SLI 配置

# prometheus-slo-rules.yml
groups:
  - name: slo.sli
    interval: 30s
    rules:
      # === 订单服务 SLI:可用性 ===
      
      # 30 天窗口内的成功请求总数
      - record: sli:order_service_availability:ratio_rate30d
        expr: |
          sum(rate(http_requests_total{service="order-service", status!~"5.."}[30d]))
          /
          sum(rate(http_requests_total{service="order-service"}[30d]))
      
      # 短窗口 SLI(用于 Burn Rate 计算)
      - record: sli:order_service_availability:ratio_rate5m
        expr: |
          sum(rate(http_requests_total{service="order-service", status!~"5.."}[5m]))
          /
          sum(rate(http_requests_total{service="order-service"}[5m]))

      - record: sli:order_service_availability:ratio_rate1h
        expr: |
          sum(rate(http_requests_total{service="order-service", status!~"5.."}[1h]))
          /
          sum(rate(http_requests_total{service="order-service"}[1h]))

      # === 延迟 SLI(P99 < 500ms 的请求比例)===
      - record: sli:order_service_latency:ratio_rate5m
        expr: |
          sum(rate(http_request_duration_seconds_bucket{service="order-service", le="0.5"}[5m]))
          /
          sum(rate(http_request_duration_seconds_count{service="order-service"}[5m]))

基于错误预算的告警

# SLO 告警规则(Google SRE 推荐的多窗口多 Burn Rate 方法)
# SLO = 99.9%(错误预算 = 0.1% = 43.2 min/月)

groups:
  - name: slo.alerts
    rules:
      # === 紧急告警:1 小时内烧掉 2% 错误预算(30 天预算 × 14.4 倍速度)===
      # 含义:如果保持现在的错误率,5 小时内耗尽整月预算
      - alert: SLOBurnRateCritical
        expr: |
          (
            sli:order_service_availability:ratio_rate1h < bool (1 - 14.4 * 0.001)
          ) and (
            sli:order_service_availability:ratio_rate5m < bool (1 - 14.4 * 0.001)
          )
        labels:
          severity: critical
          service: order-service
        annotations:
          summary: "订单服务 SLO Burn Rate 过高(Critical)"
          description: |
            当前错误率是 SLO 允许值的 14.4 倍。
            如持续,将在 ~1 小时内耗尽本月错误预算。
            当前 1h SLI: {{ $value | humanizePercentage }}
            SLO 目标: 99.9%

      # === 警告告警:6 小时内烧掉 5% 错误预算(6 倍速度)===
      # 含义:如果持续,36 小时内耗尽整月预算
      - alert: SLOBurnRateWarning
        expr: |
          (
            sli:order_service_availability:ratio_rate1h < bool (1 - 6 * 0.001)
          ) and (
            sli:order_service_availability:ratio_rate5m < bool (1 - 6 * 0.001)
          )
        for: 30m     # 持续 30 分钟才告警
        labels:
          severity: warning
          service: order-service
        annotations:
          summary: "订单服务 SLO Burn Rate 升高(Warning)"
          description: |
            当前错误率是 SLO 允许值的 6 倍。
            如持续,将在 ~36 小时内耗尽本月错误预算。

      # === 信息:当前月度 SLO 消耗进度 ===
      - alert: SLOErrorBudgetExhausted
        expr: |
          sli:order_service_availability:ratio_rate30d < 0.999
        for: 5m
        labels:
          severity: info
        annotations:
          summary: "订单服务月度 SLO 已被突破"
          description: "30 天内的可用率 {{ $value | humanizePercentage }} 低于 SLO 99.9%"

四、错误预算 Dashboard

# 错误预算剩余量(0-100%)
# 100% = 全部预算还在;0% = 预算用完;负数 = SLO 已被突破

(
  sli:order_service_availability:ratio_rate30d - (1 - 0.999)
)
/
0.001 * 100

# 当前月度错误预算消耗速率(Burn Rate)
(1 - sli:order_service_availability:ratio_rate1h) / 0.001

# 按当前速率,预算还能撑多少天
(
  sli:order_service_availability:ratio_rate30d - (1 - 0.999)
)
/
(1 - sli:order_service_availability:ratio_rate1h - 0.001)
* 30   # 换算成天

五、可观测性成熟度路线图

Level 1(基础):
  ✅ Prometheus + Grafana 部署完成
  ✅ 基础指标(CPU/内存/磁盘/网络)采集
  ✅ 业务 HTTP 指标采集(RED)

Level 2(进阶):
  ✅ Recording Rules 优化查询性能
  ✅ RED 方法:每个服务有标准 Dashboard
  ✅ USE 方法:每个节点有资源监控 Dashboard
  ✅ Alertmanager 告警路由和分组

Level 3(高级):
  ✅ 分布式追踪(Jaeger/OTEL)
  ✅ 日志聚合(Loki + LogQL)
  ✅ SLO 定义和错误预算告警
  ✅ Thanos 长期存储

Level 4(卓越):
  ✅ Trace → Metrics 关联(OTEL 生成 RED 指标)
  ✅ 全局 SLO Dashboard(多服务错误预算看板)
  ✅ Incident 响应流程和 Runbook 自动化
  ✅ SLO Review 文化(按周/月复盘错误预算消耗)

小结

RED + USE 是监控思维转变:不是所有指标都重要,服务监控聚焦 Rate/Error/Duration,资源监控聚焦 Utilization/Saturation/Error。SLO 是从“监控指标”到“衡量用户体验”的跨越:SLI 是 PromQL 表达式,SLO 是目标阈值,错误预算是团队的“安全余量”。Burn Rate 告警是最关键的实践:不是“错误率 > 1% 就告警”(阈值告警,误报多),而是“按当前速度,N 小时内错误预算用完”(面向预算的告警,更有价值)。可观测性体系是迭代的:从 Level 1 开始,逐步引入方法论和工具,每次提升都有实际价值。