K8s 可观测性黄金法则:RED/USE 方法与 SLO 实战
系统讲解生产可观测性体系的方法论与实践:RED 方法(Rate/Error/Duration)面向用户服务监控、USE 方法(Utilization/Saturation/Error)面向基础设施资源监控、SLO(服务等级目标)设计与错误预算计算、Prometheus 中的 SLI 指标配置、AlertManager 基于错误预算的告警策略,帮助从"指标收集"升级到"面向 SLO 的可观测性体系"。
很多团队有 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 开始,逐步引入方法论和工具,每次提升都有实际价值。
