云计算百科
云计算领域专业知识百科平台

02|SRE:SLO、SLI、Error Budget 是 AIOps 的地基

面向 ITOps Agent Platform 系列第 2 篇。先学"什么叫系统健康",再学 AI 如何判断系统健康。

1. 为什么这个问题重要

如果 AIOps 不知道"什么是健康",它的一切判断都是空中楼阁。SLO/SLI/Error Budget 提供了可度量的可靠性目标,是 AI 判断系统健康与否的唯一尺度。

2. 前沿技术趋势

Google SRE 将 error budget 用作可靠性与变更速度之间的控制机制。AIOps 的演进方向,是让告警、优先级、自动化策略都围绕 error budget 展开,而非围绕孤立的资源阈值(如 CPU > 80%)。

3. 核心概念

SLI(Service Level Indicator)

用户真正感知的指标:availability、latency、correctness、freshness、durability。

SLO(Service Level Objective)

99.95% availability
P99 latency < 500ms
99.9% successful checkout

Error Budget

error_budget = 1 – SLO

一个 99.9% SLO 的服务,在对应窗口内 error budget 就是 0.1%。AIOps 不应只问"CPU 是否超过 80%“,而应问"当前异常是否正在消耗业务 error budget”。

4. ITOps Agent Platform 中的对应模块

SLO Agent → Budget Calculator → Incident Priority → Automation Policy

5. 架构设计

把可靠性目标下沉到自动化决策:

SLO 定义

Error Budget 实时计算

Incident 优先级映射

自动化权限分级(预算充足→可自动,预算耗尽→强制人工)

下面是一个基于 error budget 剩余量自动调整自动化权限的示例配置:

automation_policy:
service: paymentapi
# 以 30 天窗口的 error budget 剩余比例为决策依据
error_budget_levels:
name: healthy
remaining_budget: ">= 50%"
automation:
enabled: true
allowed_actions:
restart_pod
scale_out
rollback_release
approval: none

name: degraded
remaining_budget: ">= 20%"
automation:
enabled: true
allowed_actions:
restart_pod
scale_out
approval: auto_ticket

name: critical
remaining_budget: "< 20%"
automation:
enabled: false
allowed_actions: []
approval: manual_approval

# 预算耗尽时,直接切换到强制人工审批
budget_exhausted:
action: force_manual
approval_flow: p1_oncall
note: "error budget 耗尽时禁止自动变更,需人工审批后执行"

策略规则说明:

  • healthy:预算充足(≥ 50%),允许自动重启、扩容、回滚,无需人工审批。
  • degraded:预算部分消耗(≥ 20%),仍允许自动重启/扩容,但需自动创建变更单留痕。
  • critical:预算紧张(< 20%),关闭自动化变更,所有动作转人工审批。
  • budget_exhausted:预算耗尽,强制走 P1 值班人工审批流程,避免在系统不稳定时叠加自动变更风险。

6. 实战实验

定义一个服务的 SLO:

service: paymentapi
slos:
name: availability
target: 99.95%
window: 30d
name: latency
target: 99.9%
threshold_ms: 500
window: 30d

7. 代码 / API / 配置

Burn rate 是比"当前错误率"更关键的信号(它衡量消耗预算的速度):

def burn_rate(error_ratio, slo_ratio):
# error_ratio: 实际错误比例; slo_ratio: 允许的错误预算比例
return error_ratio / slo_ratio

# 例:错误率 2%,SLO 允许 0.1%,burn rate = 20 倍

完整 Python 实战示例

下面给出可直接运行的示例,覆盖 SLO 配置、滑动窗口 error budget 计算、多窗口 burn rate 监控与告警级别输出:

from dataclasses import dataclass, field
from datetime import datetime, timedelta
from collections import deque
from typing import Optional

# ———- 1. SLO 配置数据结构 ———-
@dataclass
class SLOConfig:
service: str
slo_name: str
target: float # SLO 目标,如 0.999 表示 99.9%
window_days: int = 30 # 统计窗口
thresholds: dict = field(default_factory=lambda: {
"1h": 14.4,
"6h": 6.0,
"30d": 1.0,
})

@property
def error_budget_ratio(self) > float:
"""SLO 允许的错误比例 = 1 – target"""
return 1 self.target

@dataclass
class Event:
ts: datetime
ok: bool

# ———- 2. 滑动窗口 error budget 计算 ———-
class ErrorBudgetTracker:
def __init__(self, slo: SLOConfig):
self.slo = slo
self.events: deque[Event] = deque()

def record(self, ts: datetime, ok: bool):
"""记录一次请求结果"""
self.events.append(Event(ts, ok))

def error_ratio(self, window: timedelta, now: datetime) > float:
"""计算滑动窗口内的错误率"""
cutoff = now window
window_events = [e for e in self.events if e.ts >= cutoff]
if not window_events:
return 0.0
failed = sum(1 for e in window_events if not e.ok)
return failed / len(window_events)

def remaining_error_budget(self, now: datetime, window_days: Optional[int] = None) > float:
"""剩余 error budget 比例;小于等于 0 表示预算耗尽"""
days = window_days or self.slo.window_days
error_ratio = self.error_ratio(timedelta(days=days), now)
return max(0.0, self.slo.error_budget_ratio error_ratio)

# ———- 3. 多窗口 burn rate 监控与告警级别 ———-
def burn_rate(error_ratio: float, slo_ratio: float) > float:
"""burn rate = 实际错误率 / SLO 允许错误率"""
return error_ratio / slo_ratio if slo_ratio > 0 else float("inf")

def get_severity(window: str, burn_rate_value: float, threshold: float) > str:
if burn_rate_value < threshold:
return "OK"
return {"1h": "P1/critical", "6h": "P2/warning", "30d": "P3/info"}.get(window, "OK")

def multi_window_monitor(tracker: ErrorBudgetTracker, now: datetime) > list[dict]:
"""同时监控 1h / 6h / 30d 三个窗口"""
windows = {
"1h": timedelta(hours=1),
"6h": timedelta(hours=6),
"30d": timedelta(days=30),
}

results = []
for name, window in windows.items():
error_ratio = tracker.error_ratio(window, now)
br = burn_rate(error_ratio, tracker.slo.error_budget_ratio)
threshold = tracker.slo.thresholds[name]
results.append({
"window": name,
"error_ratio": round(error_ratio, 6),
"burn_rate": round(br, 2),
"threshold": threshold,
"severity": get_severity(name, br, threshold),
"budget_remaining": round(tracker.remaining_error_budget(now), 6),
})
return results

if __name__ == "__main__":
slo = SLOConfig(service="payment-api", slo_name="availability", target=0.999)
now = datetime(2026, 9, 3, 13, 0, 0)

# === 场景 1:正常流量,所有窗口 burn rate 均为 0 ===
tracker = ErrorBudgetTracker(slo)
for i in range(100):
tracker.record(now timedelta(minutes=i % 60), ok=True)
for i in range(1000):
tracker.record(now timedelta(minutes=60 + i % 300), ok=True)

print("场景 1:正常流量")
for r in multi_window_monitor(tracker, now):
print(f" window={r['window']}, burn_rate={r['burn_rate']}, "
f"threshold={r['threshold']}, severity={r['severity']}")
# 输出示例:
# window=1h, burn_rate=0.0, threshold=14.4, severity=OK
# window=6h, burn_rate=0.0, threshold=6.0, severity=OK
# window=30d, burn_rate=0.0, threshold=1.0, severity=OK

# === 场景 2:短期故障,1h/6h 超过阈值,30d 仍可控 ===
tracker = ErrorBudgetTracker(slo)
for i in range(100):
tracker.record(now timedelta(minutes=i % 60), ok=(i % 50 != 0)) # 1h 约 2% 失败
for i in range(1000):
tracker.record(now timedelta(minutes=60 + i % 300), ok=(i % 100 != 0)) # 6h 约 1% 失败
for i in range(50000):
tracker.record(now timedelta(hours=10 + i % 700), ok=True) # 30d 历史成功样本稀释

print("场景 2:短期故障")
for r in multi_window_monitor(tracker, now):
print(f" window={r['window']}, burn_rate={r['burn_rate']}, "
f"threshold={r['threshold']}, severity={r['severity']}")
# 输出示例:
# window=1h, burn_rate≈20.0, threshold=14.4, severity=P1/critical
# window=6h, burn_rate≈10.0, threshold=6.0, severity=P2/warning
# window=30d, burn_rate≈0.2, threshold=1.0, severity=OK

# === 场景 3:严重故障,预算耗尽 ===
tracker = ErrorBudgetTracker(slo)
for i in range(100):
tracker.record(now timedelta(minutes=i % 60), ok=(i % 10 < 7)) # 1h 约 30% 失败
for i in range(1000):
tracker.record(now timedelta(minutes=60 + i % 300), ok=(i % 10 < 8)) # 6h 约 20% 失败

print("场景 3:严重故障,预算耗尽")
for r in multi_window_monitor(tracker, now):
print(f" window={r['window']}, burn_rate={r['burn_rate']}, "
f"threshold={r['threshold']}, severity={r['severity']}, "
f"budget_remaining={r['budget_remaining']}")
# 输出示例:
# window=1h, burn_rate≈300.0, threshold=14.4, severity=P1/critical, budget_remaining≈0.0
# window=6h, burn_rate≈200.0, threshold=6.0, severity=P2/warning, budget_remaining≈0.0
# window=30d, burn_rate≈209.0, threshold=1.0, severity=P3/info, budget_remaining=0.0

边界条件与注意事项

在实际落地时,上述示例的简化逻辑会遇到几个边界条件,需要显式处理,否则会产生误报或漏报:

1. 窗口内样本量不足时 error_ratio 的计算偏差

当窗口内样本量很少时,error_ratio 的统计意义会显著下降。例如 1h 窗口内只有 10 个请求,其中 1 个失败,error_ratio = 10%,burn rate 高达 100 倍,但这很可能只是噪声而非真实故障。

def error_ratio(self, window: timedelta, now: datetime, min_samples: int = 100) > float:
"""计算滑动窗口内的错误率;样本不足时返回 None 表示不可信"""
cutoff = now window
window_events = [e for e in self.events if e.ts >= cutoff]
if len(window_events) < min_samples:
return None # 样本不足,不参与 burn rate 判定
failed = sum(1 for e in window_events if not e.ok)
return failed / len(window_events)

处理建议:为每个窗口设置最小样本量阈值(如 1h 窗口至少 100 个样本),样本不足时跳过该窗口的 burn rate 判定,或降级为 observe 而非直接告警。

2. 多个 SLO 同时被击穿时告警优先级如何合并

一个服务通常同时维护多个 SLO(availability、latency、correctness 等)。当多个 SLO 同时被击穿时,不能简单取最高级别,而应合并为一个聚合告警,避免告警风暴:

def merge_slo_alerts(alerts: list[dict]) > dict:
"""合并同一服务的多个 SLO 告警,取最高优先级并聚合上下文"""
if not alerts:
return {}
severity_rank = {"P1": 3, "P2": 2, "P3": 1}
top = max(alerts, key=lambda a: severity_rank.get(a["severity"], 0))
return {
"service": top["service"],
"severity": top["severity"],
"slo_hits": [a["slo_name"] for a in alerts],
"max_burn_rate": max(a["burn_rate"] for a in alerts),
"windows": sorted({a["window"] for a in alerts}),
"action": top["action"],
}

处理建议:按「最高严重级别 + 命中的 SLO 列表 + 最大 burn rate」合并为一条告警;若多个 SLO 指向同一根因(如上游依赖超时同时击穿 availability 与 latency),应合并为一次排查,而非重复触发。

3. burn_rate 为无穷大(slo_ratio=0)时的处理

当 SLO 目标为 100%(slo_ratio = 0)时,burn_rate 会除以 0 得到无穷大。此时任何一次失败都意味着「预算瞬间耗尽」,需要特殊处理:

def burn_rate(error_ratio: float, slo_ratio: float) > float:
"""burn rate = 实际错误率 / SLO 允许错误率;slo_ratio=0 时返回 inf"""
if slo_ratio <= 0:
return float("inf") if error_ratio > 0 else 0.0
return error_ratio / slo_ratio

处理建议:slo_ratio = 0 意味着「零容忍」策略,任何失败都应直接触发最高级别告警并升级人工,不应进入常规的 burn rate 阈值比较逻辑。同时应在 SLO 定义阶段就避免 target = 1.0 的写法,改为 target = 0.9999 等可度量的目标。

4. 滑动窗口与固定窗口在 error budget 计算上的差异

滑动窗口(rolling window)与固定窗口(calendar window)在 error budget 计算上有本质差异:

维度滑动窗口固定窗口
窗口边界 随当前时间滚动,如「最近 30 天」 按日历对齐,如「本月 1 日 0 点至月末」
预算重置 永不重置,旧数据持续滑出 每个周期(月/周)重置
对突发故障的敏感度 高,故障会立即反映在窗口内 低,月初的故障会被整月数据稀释
适合场景 实时监控、burn rate 告警 月度/季度复盘、容量规划

def remaining_error_budget_fixed_window(
slo: SLOConfig, month_start: datetime, now: datetime
) > float:
"""固定窗口(自然月)error budget 剩余量计算"""
elapsed_ratio = (now month_start).total_seconds() / (
(month_start.replace(month=month_start.month % 12 + 1, day=1) month_start).total_seconds()
)
# 已消耗的预算 = 已流逝时间比例 × 总预算
consumed_budget = slo.error_budget_ratio * elapsed_ratio
# 实际错误率
error_ratio = compute_error_ratio(month_start, now)
return max(0.0, consumed_budget error_ratio)

处理建议:生产环境应同时维护两种口径——滑动窗口用于实时 burn rate 告警(快速发现),固定窗口用于周期性复盘与容量规划(宏观视角)。两者结论不一致时(如滑动窗口已告警但固定窗口仍健康),以滑动窗口为准触发响应,固定窗口仅作趋势参考。

当 burn rate 超过阈值时的排查决策流程 burn rate 阈值与时间窗口对照表

以允许错误率为 0.1%(SLO 99.9%,窗口 30d)的服务为例,可按「预算消耗速度」设置多档阈值:

时间窗口burn rate 阈值持续该速率下消耗完 30 天预算的时间建议告警级别简要说明
1h 14.4 约 2.08 天(1 小时消耗约 2% 预算) P1 / critical 故障正在快速消耗预算,需立即响应并拉通排查
6h 6 约 5 天(6 小时消耗约 5% 预算) P2 / warning 持续错误正在累积预算,应进入排查流程
30d 1 约 30 天 P3 / info 整窗预算刚好按计划消耗,用于趋势观察与复盘

说明:同一时刻可以同时维护多个窗口的 burn rate 告警。短期窗口(1h)负责「快速发现」,长期窗口(30d)负责「慢泄漏」发现;当 1h 与 6h 同时超阈值时,通常意味着故障仍在持续,告警优先级应相应上调。

当 SLO Agent 检测到某个 SLI 的 burn rate 超过预设阈值(例如短期窗口 burn rate > 14.4 倍时,意味着 2 小时内消耗完 30 天错误预算),应触发以下决策链路:

  • SLO Agent 检测高 burn rate

    • 输入:实时 SLI 指标(如 availability 当前低于 SLO、latency P99 超标事件流)
    • 输出:一个告警事件,包含 service、slo_name、burn_rate、time_window、severity 示例:

    alert: payment-api / availability / burn_rate=20.0 / window=1h / severity=critical

  • 关联 SLI 指标与维度

    • 输入:告警事件中的 service 标签与 SLO 定义
    • 输出:命中该 SLO 的全部 SLI 指标集合及其当前值 示例:

    service=payment-api
    availability=99.2%(低于 99.95%)
    latency_p99=780ms(超过 500ms)
    error_rate=2.0%

  • 定位异常服务与贡献资源

    • 输入:关联后的 SLI 指标,结合运行时拓扑和 span/trace 数据
    • 输出:疑似异常的服务实例、依赖或基础设施组件 示例:

    suspect_service=payment-api-pod-7f8c9
    root_cause_hint=upstream dependency: inventory-service timeout

  • 判断触发自动修复或升级人工

    • 输入:error budget 剩余量、burn rate 等级、事件可信度、自动化策略
    • 输出:动作决策(自动修复 / 人工升级 / 继续观察) 示例:

    error_budget_remaining=0.03%(即将耗尽)
    burn_rate_level=critical
    confidence=high
    action=escalate_to_human(P1)

  • 下面是上述 4 步决策链路的完整流程图:

    #mermaid-svg-yqE4rw5SmzxSee9V{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yqE4rw5SmzxSee9V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yqE4rw5SmzxSee9V .error-icon{fill:#552222;}#mermaid-svg-yqE4rw5SmzxSee9V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yqE4rw5SmzxSee9V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yqE4rw5SmzxSee9V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yqE4rw5SmzxSee9V .marker.cross{stroke:#333333;}#mermaid-svg-yqE4rw5SmzxSee9V svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yqE4rw5SmzxSee9V p{margin:0;}#mermaid-svg-yqE4rw5SmzxSee9V .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-yqE4rw5SmzxSee9V .cluster-label text{fill:#333;}#mermaid-svg-yqE4rw5SmzxSee9V .cluster-label span{color:#333;}#mermaid-svg-yqE4rw5SmzxSee9V .cluster-label span p{background-color:transparent;}#mermaid-svg-yqE4rw5SmzxSee9V .label text,#mermaid-svg-yqE4rw5SmzxSee9V span{fill:#333;color:#333;}#mermaid-svg-yqE4rw5SmzxSee9V .node rect,#mermaid-svg-yqE4rw5SmzxSee9V .node circle,#mermaid-svg-yqE4rw5SmzxSee9V .node ellipse,#mermaid-svg-yqE4rw5SmzxSee9V .node polygon,#mermaid-svg-yqE4rw5SmzxSee9V .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yqE4rw5SmzxSee9V .rough-node .label text,#mermaid-svg-yqE4rw5SmzxSee9V .node .label text,#mermaid-svg-yqE4rw5SmzxSee9V .image-shape .label,#mermaid-svg-yqE4rw5SmzxSee9V .icon-shape .label{text-anchor:middle;}#mermaid-svg-yqE4rw5SmzxSee9V .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yqE4rw5SmzxSee9V .rough-node .label,#mermaid-svg-yqE4rw5SmzxSee9V .node .label,#mermaid-svg-yqE4rw5SmzxSee9V .image-shape .label,#mermaid-svg-yqE4rw5SmzxSee9V .icon-shape .label{text-align:center;}#mermaid-svg-yqE4rw5SmzxSee9V .node.clickable{cursor:pointer;}#mermaid-svg-yqE4rw5SmzxSee9V .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yqE4rw5SmzxSee9V .arrowheadPath{fill:#333333;}#mermaid-svg-yqE4rw5SmzxSee9V .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yqE4rw5SmzxSee9V .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yqE4rw5SmzxSee9V .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yqE4rw5SmzxSee9V .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yqE4rw5SmzxSee9V .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yqE4rw5SmzxSee9V .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yqE4rw5SmzxSee9V .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yqE4rw5SmzxSee9V .cluster text{fill:#333;}#mermaid-svg-yqE4rw5SmzxSee9V .cluster span{color:#333;}#mermaid-svg-yqE4rw5SmzxSee9V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yqE4rw5SmzxSee9V .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yqE4rw5SmzxSee9V rect.text{fill:none;stroke-width:0;}#mermaid-svg-yqE4rw5SmzxSee9V .icon-shape,#mermaid-svg-yqE4rw5SmzxSee9V .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yqE4rw5SmzxSee9V .icon-shape p,#mermaid-svg-yqE4rw5SmzxSee9V .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yqE4rw5SmzxSee9V .icon-shape .label rect,#mermaid-svg-yqE4rw5SmzxSee9V .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yqE4rw5SmzxSee9V .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yqE4rw5SmzxSee9V .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yqE4rw5SmzxSee9V :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    剩余 >= 20%(预算充足)

    高(>= HIGH_TRUST)

    剩余 < 20%(预算紧张)

    critical

    warning

    剩余 <= 0(预算耗尽)

    SLO Agent 检测高 burn rate

    burn_rate >= 阈值?

    继续观察 observe

    关联 SLI 指标与维度

    定位异常服务与贡献资源

    error budget 剩余量?

    置信度 confidence?

    自动修复 auto_remediate

    继续观察 observe

    burn rate 等级?

    升级人工 escalate_to_human(P1)

    自动创建变更单 + 人工审批

    强制人工审批 force_manual(P1 值班)

    伪代码描述完整链路:

    def troubleshoot_high_burn_rate(alert):
    # Step 1: SLO Agent 输出高 burn rate 告警
    service = alert["service"]
    slo_name = alert["slo_name"]
    burn_rate = alert["burn_rate"]
    if burn_rate < BURN_RATE_THRESHOLD:
    return {"action": "observe", "reason": "burn rate below threshold"}

    # Step 2: 关联 SLI 指标
    sli_metrics = get_sli_metrics(service, slo_name)
    # 返回如:{"availability": 0.992, "latency_p99_ms": 780, "error_rate": 0.02}

    # Step 3: 定位异常服务
    topology = get_service_topology(service)
    suspects = locate_anomaly(topology, sli_metrics)
    # 返回如:["payment-api-pod-7f8c9"],可能通过 trace/日志关联

    # Step 4: 评估预算和置信度,决定动作
    error_budget = get_error_budget(service, slo_name, window="30d")
    confidence = calc_confidence(sli_metrics, suspects)

    if error_budget.burned > BUDGET_CRITICAL_RATIO and confidence >= HIGH_TRUST:
    return {"action": "auto_remediate", "targets": suspects,
    "allowed_actions": ["restart_pod", "scale_out"]}
    elif error_budget.remaining < BUDGET_EXHAUSTED_THRESHOLD:
    return {"action": "escalate_to_human", "priority": "P1",
    "reason": "error budget nearly exhausted, manual control required"}
    else:
    return {"action": "observe", "reason": "collect more evidence"}

    8. 生产环境最佳实践

    不要让 CPU 直接决定"自动修复"。应组合多个信号:

    CPU 95% + request error rate ↑ + latency ↑ + SLO burn rate ↑ = 高可信事件

    9. 常见错误

    • 用资源指标(CPU/内存)代替 SLI 来定义健康。
    • 只设 SLO 不计算 burn rate,无法感知"预算消耗速度"。
    • 把 error budget 当摆设,自动化策略与其脱钩。

    10. 安全注意事项

    Error budget 也是"自动化风险预算":预算耗尽时,应收紧自动化权限,回退到人工,避免在系统不稳定时叠加更多变更风险。

    11. 可观测性

    为每个 SLI 暴露实时采集与 burn rate 指标,并打上 service/environment 标签,供 SLO Agent 消费。

    12. Evaluation

    验证"异常是否真的消耗 error budget",用一个 SLO → Error Budget → Alert Priority 的 Demo 做端到端验收。

    13. 验收标准

    完成一个 SLO → Error Budget → Alert Priority 的可运行 Demo。

    14. 思考题

    • 你团队 Top 3 服务的 SLO 是什么?是否可度量?
    • 一个 CPU 100% 但业务无损的服务,该不该触发 P1 告警?

    15. 延伸阅读

    • Google SRE Workbook
    • Error Budget Policy
    • Eliminating Toil
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 02|SRE:SLO、SLI、Error Budget 是 AIOps 的地基
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!