真实事故复盘剧本:从指标抖动到根因的全链路追查
凌晨 02:14(本文时间均为 UTC+8 虚构)。PagerDuty
推送:CheckoutSLOBurnRateCritical1h
firing,slo:checkout:burnrate1h > 14.4
已持续 2 分钟。Grafana SLO 面板:p99 从 120ms 升至
2.3s,错误率 0.05% → 3.2%。
本文是虚构但可复现的排障教材:实验环境、指标名、PromQL/LogQL、kubectl 命令均可在 minikube/docker-compose 演练栈复现。不发明工具行为——命令与面板路径对齐本系列 Prometheus、SLO、告警、Traces、Logs、Events、内核追踪。
一、演练环境与前置条件
1.1 拓扑(虚构 ecommerce 生产)
| 组件 | 版本假设 | 可观测性 |
|---|---|---|
| checkout | Go 1.22, 12 replicas | OTel SDK → Collector |
| redis-cart | Redis 7 | redis_exporter |
| payment | Java 17 | OTel Java agent |
| inventory | Go | OTel |
| Prometheus | 2.51 | scrape + recording |
| Alertmanager | 0.27 | route → PagerDuty |
| Tempo | 2.4 | trace backend |
| Loki | 3.0 | {service="checkout"} |
| Grafana | 11 | SLO + RED dashboards |
1.2 复现仓库结构(建议)
incident-lab/
docker-compose.yml
prometheus/rules/slo-checkout.yaml
alertmanager/alertmanager.yml
otel-collector/config.yaml
apps/checkout/...
1.3 注入故障(与剧本一致)
# 模拟错误配置:将 redis maxclients 从 10000 改为 100 后滚动发布
kubectl patch configmap checkout-redis -n production --type merge -p '
{"data":{"redis.conf":"maxclients 100\ntimeout 300\n"}}'
kubectl rollout restart deployment/checkout-redis -n production
kubectl rollout restart deployment/checkout -n production预期现象:连接池耗尽 → p99 上升 → Burn Rate Page。与主剧本一致。
二、Golden Minute(T+0 — T+5)
T+0:Ack 与确认
- PagerDuty Ack;打开 19-alerting runbook URL。
- Grafana → Dashboard
slo-checkout→ 确认非维护窗口静默。
T+1:RED 定性
| 信号 | 正常基线 | 事故值 | 推断 |
|---|---|---|---|
| Rate | 1.2k rps | 1.15k rps | 流量未跌 |
| Errors | 0.05% | 3.2% | 服务在失败 |
| Duration p99 | 120ms | 2.3s | 尾部恶化 |
参考 指标体系 RED。
T+2:变更审查
并行打开 Events 面板与:
kubectl:events
kubectl get events -n production --sort-by=.lastTimestamp | tail -20输出片段记入 Incident 文档;与 Events 与变更关联 对照。
kubectl:rollout
kubectl rollout history deployment/checkout -n production输出片段记入 Incident 文档;与 Events 与变更关联 对照。
kubectl:diff
kubectl diff -f deploy/checkout.yaml输出片段记入 Incident 文档;与 Events 与变更关联 对照。
kubectl:configmap
kubectl get configmap checkout-redis -n production -o yaml输出片段记入 Incident 文档;与 Events 与变更关联 对照。
kubectl:pods
kubectl get pods -n production -l app=checkout -o wide输出片段记入 Incident 文档;与 Events 与变更关联 对照。
T+3:角色
| 角色 | 职责 |
|---|---|
| Commander | 决策回滚/熔断 |
| Comms | Slack #incidents 状态 |
| Ops | 执行 PromQL/LogQL |
T+5:首次通报
[INC-2026-0618-0214] checkout p99 2.3s, err 3.2%. 疑 redis/连接池.
Investigating. ETA 30m update.
三、Metrics 阶段(T+5 — T+15)
3.1 两问定性
- 全实例还是单实例?
- 仅 checkout 还是下游同步恶化?
步骤 1:基线 p99
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 2:按 instance
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) by (le, instance))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 3:按 endpoint
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout",endpoint="/api/checkout/submit"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 4:错误率
sum(rate(http_requests_total{service="checkout",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="checkout"}[5m]))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 5:Redis 客户端
histogram_quantile(0.99, sum(rate(redis_command_duration_seconds_bucket{service="checkout"}[5m])) by (le, command))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 6:连接池
redis_pool_connections_waiting{service="checkout"}
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 7:Burn Rate 1h
slo:checkout:burnrate1h
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 8:下游 payment
histogram_quantile(0.99, sum(rate(http_client_duration_seconds_bucket{service="checkout",peer="payment"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
3.2 与 SLO Recording Rules
确认 18-slo 规则已部署:
# prometheus/rules/slo-checkout.yaml(节选)
- record: slo:checkout:burnrate1h
expr: |
sum(rate(http_requests_total{service="checkout",status=~"5.."}[1h]))
/ sum(rate(http_requests_total{service="checkout"}[1h]))
/ (1 - 0.999)四、Trace 阶段(T+15 — T+25)
4.1 从 Exemplar 跳转 Tempo
Grafana → checkout RED 面板 → 点击 p99 尖峰 exemplar →
Trace ID
7f3a9c2e4b1d8f0a6e5c4b3a29180716(虚构固定值,实验可种子化)。
4.2 Span 分解(虚构 trace)
| Span | duration |
|---|---|
| checkout.submit | 2300ms |
| redis_get_cart | 850ms |
| payment.authorize | 45ms |
| inventory.reserve | 38ms |
判断:Redis span 占比高 → 下游或连接池。
4.3 采样不足时
按 10-traces 临时调 tail sampling:
# otel-collector tail_sampling 片段
policies:
- name: slow-checkout
type: latency
latency:
threshold_ms: 200等待 3–5 分钟再查 Tempo。
五、Log 阶段(T+20 — T+30)
LogQL:trace 关联
{service="checkout"} | json | trace_id="7f3a9c2e4b1d8f0a6e5c4b3a29180716"
关联 日志管道
的解析规则;确认 trace_id
字段在采集层注入。
LogQL:连接池
{service="checkout"} |= "connection pool exhausted"
关联 日志管道
的解析规则;确认 trace_id
字段在采集层注入。
LogQL:Redis 超时
{service="checkout"} |~ "redis.*timeout|i/o timeout"
关联 日志管道
的解析规则;确认 trace_id
字段在采集层注入。
LogQL:部署标记
{service="checkout"} |= "config reload"
关联 日志管道
的解析规则;确认 trace_id
字段在采集层注入。
LogQL:结构化字段
{service="checkout"} | json | pool_wait_ms > 500
关联 日志管道
的解析规则;确认 trace_id
字段在采集层注入。
期望命中(合成日志行):
{"level":"error","service":"checkout","trace_id":"7f3a9c2e4b1d8f0a6e5c4b3a29180716","msg":"redis: connection pool exhausted","pool_wait_ms":843}若未命中:记为可观测性盲区——补 redis client span event。
六、Profile 与内核(T+30 — T+45)
6.1 Pyroscope/Parca
对照 12-profiling、16 Continuous Profiling:
# 虚构 CLI:拉取 15min CPU profile
parca query --pod=checkout-7d8f9c --range=15m --profile-type=cpu本剧本根因为 I/O 等待,CPU
火焰图不应热点在
json.Marshal——若热点在 GC 则转剧本 C。
6.2 bpftrace(排除内核/network)
bpftrace -e 'kprobe:tcp_connect { @ = hist(nsecs); } interval:s:5 { exit(); }'连接池问题通常在用户态日志已暴露;内核阶段用于剧本 B。
七、Events 与根因确认(并行 T+25 — T+40)
kubectl rollout history 显示 revision 42 在
T-45min 部署。configmap/checkout-redis 中
maxclients 100。根因:配置回滚错误导致
Redis 连接上限骤降。
八、缓解与修复
| 优先级 | 动作 | 命令 |
|---|---|---|
| P0 | 回滚 checkout-redis CM | kubectl rollout undo deployment/checkout-redis |
| P0 | 熔断可选 | 应用层 circuit breaker 开关 |
| P1 | 扩容 | kubectl scale deployment/checkout --replicas=16 |
缓解后观察 18-slo 面板 30 分钟,Burn Rate 回落。
九、主剧本完整时间线(分钟级)
| T | 动作 | 工具 | 系列参考 |
|---|---|---|---|
| 0 | Ack Page | PagerDuty | 19-alerting |
| 5 | RED | Grafana | 03-metrics |
| 12 | 按 instance PromQL | Prometheus | 06-prometheus |
| 18 | Tempo 慢 trace | Grafana | 10-traces |
| 25 | Loki trace_id | Loki | 08-logs |
| 35 | CM 变更 | kubectl | 13-events |
| 42 | 回滚 | kubectl | — |
| 75 | SLO 恢复 | Grafana | 18-slo |
十、剧本 A:MySQL 慢查询(初级)
注入:去掉索引 ALTER 或
chaos 注入延迟。
步骤 1:基线 p99
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 2:按 instance
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) by (le, instance))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 3:按 endpoint
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout",endpoint="/api/checkout/submit"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 4:错误率
sum(rate(http_requests_total{service="checkout",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="checkout"}[5m]))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 5:Redis 客户端
histogram_quantile(0.99, sum(rate(redis_command_duration_seconds_bucket{service="checkout"}[5m])) by (le, command))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 6:连接池
redis_pool_connections_waiting{service="checkout"}
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 7:Burn Rate 1h
slo:checkout:burnrate1h
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
步骤 8:下游 payment
histogram_quantile(0.99, sum(rate(http_client_duration_seconds_bucket{service="checkout",peer="payment"}[5m])) by (le))
在 Grafana Explore
执行上述表达式,时间范围设为告警触发前后 30
分钟。记录中位数与峰值,写入 Incident 时间线(见
incident-timeline.svg)。
Trace:mysql_query span
3s。Log:MySQL server has gone away。Profile:CPU
正常。根因:全表扫描占满连接池。
十一、剧本 B:DNS 超时(中级)
Metric:错误率升、latency 正常。Trace:无 entry span。Log:无应用错误。用 17-kernel-tracing:
bpftrace -e 'uprobe:/usr/lib/x86_64-linux-gnu/libc.so.6:getaddrinfo
/@[comm] = hist(nsecs);/'根因:CoreDNS 上游不可达。教训:用户态”正常”时查内核/DNS。
十二、剧本 C:JVM Full GC(中级)
周期性 p99 尖峰每 30min。16-continuous-profiling 对比 heap:
# 尖峰前 vs 尖峰时 byte[] 持有量(虚构对比表)
正常: 120MB
尖峰前: 890MB
根因:Kafka consumer max.poll.records
过大。
十三、Game Day 演练模板
## Game Day INC-DRILL-001
- 目标:30 分钟内完成主剧本 T+0 到缓解
- 角色:Commander / Ops / Comms
- 注入:redis maxclients patch
- 通过标准:Burn Rate Page < 5min ack; 根因文档化
- 失败项写入 reliability backlog与 22-chaos 对照:混沌实验应触发同等告警。
十四、事故后可观测性审计
| 问题 | 本次 | 改进 |
|---|---|---|
| Page 早于用户投诉? | 是 | — |
| trace_id 贯穿 Logs? | 是 | — |
| 连接池等待可日志化? | 部分 | 加 span event |
| 变更 45min 内关联? | 是 | Events 面板 |
十五、工程坑点
坑点 1
现象:签合同前未确认默认保留期——上线后发现仅 7 天。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 2
现象:未做 Trace 数据量 POC——按数据量计费时账单超预期。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 3
现象:私有化部署内核版本不支持 eBPF——DeepFlow 功能降级。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 4
现象:以为 OTel 兼容等于可无缝迁出——专有 attribute 未映射。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 5
现象:多租户未配 hard limit——单租户打爆共享存储。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 6
现象:Java Agent 与 OTel SDK 双埋点——存储翻倍。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 7
现象:告警直接 Page CPU 阈值——与 SLO 脱节。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 8
现象:未测迁出 API 吞吐——PB 级导出需数月。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 9
现象:信创环境未 POC Agent——麒麟内核 BTF 缺失。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 10
现象:Dashboard 依赖厂商专有查询——锁定查询层。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 11
现象:采样率在控制台改错——0 与 0.01 混淆。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 12
现象:双写 Collector 单实例——下游慢拖垮全局。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 13
现象:未记录计量口径——账单争议无证据。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 14
现象:只用 demo 环境评估——与生产流量模型不符。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
坑点 15
现象:忽略跨 AZ 流量费——对象存储 egress 隐性成本。
根因:选型或治理流程跳过 POC/合同/Runbook 环节。
修复:纳入落地清单;事故后写入 reliability backlog。
十六、工具箱清单
| 阶段 | 工具 | 链接 |
|---|---|---|
| Alert | PagerDuty + AM | 19-alerting |
| Metrics | Grafana RED | 03, 06 |
| Trace | Tempo/Jaeger | 10-traces |
| Log | Loki | 08, 09 |
| Profile | Parca/Pyroscope | 12, 16 |
| Kernel | bpftrace | 17 |
| Events | K8s + 变更 | 13-events |
| 网络 | DeepFlow/Hubble | 15-network-obs |
十七、落地清单
| # | 检查项 | 负责人 | 状态 |
|---|---|---|---|
| 1 | 是否列出数据出境/等保/信创硬约束? | SRE/架构 | 待办 |
| 2 | 是否完成 OTLP 双写 30 天 POC? | SRE/架构 | 待办 |
| 3 | 是否文档化计量口径(探针数/GB/Active Series)? | SRE/架构 | 待办 |
| 4 | 是否测试历史数据迁出吞吐? | SRE/架构 | 待办 |
| 5 | 是否对齐 SLO Burn Rate 告警路由? | SRE/架构 | 待办 |
| 6 | 是否配置多租户 hard limit? | SRE/架构 | 待办 |
| 7 | 是否统一 trace_id 贯穿 Logs/Traces? | SRE/架构 | 待办 |
| 8 | 是否 Runbook 链到稳定 URL? | SRE/架构 | 待办 |
| 9 | 是否 Game Day 演练主剧本? | SRE/架构 | 待办 |
| 10 | 是否记录 TCO 假设(机器/人力/超额)? | SRE/架构 | 待办 |
| 11 | 是否评估 LGTM 与托管曲线交叉点? | SRE/架构 | 待办 |
| 12 | 是否审查高基数 label 治理? | SRE/架构 | 待办 |
| 13 | 是否 Chaos 对照告警盲区? | SRE/架构 | 待办 |
| 14 | 是否 PII 清洗在 Collector? | SRE/架构 | 待办 |
| 15 | 是否 retention 与 SLO 窗口对齐? | SRE/架构 | 待办 |
十八、关键概念回顾
- 五阶递进:Alert → Metrics → Traces → Logs → Profile/Kernel。
- 缓解优先于根因;60–80% 关联变更。
- 每起事故输出可观测性盲区清单。
十九、下一步
排障能力验证后,用 自建 vs 托管 评估平台 TCO。
上一篇:中国厂商对比
下一篇:自建 vs 托管
时间线扩展 1(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 2(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 3(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 4(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 5(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 6(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 7(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 8(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 9(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 10(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 11(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 12(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 13(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 14(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 15(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 16(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 17(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 18(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 19(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 20(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 21(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 22(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 23(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 24(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 25(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 26(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 27(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 28(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 29(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 30(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 31(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 32(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 33(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 34(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 35(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 36(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 37(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 38(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 39(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 40(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 41(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 42(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 43(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 44(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 45(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 46(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 47(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 48(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 49(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 50(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 51(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 52(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 53(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 54(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 55(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 56(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 57(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 58(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 59(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 60(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 61(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 62(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 63(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 64(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 65(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 66(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 67(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 68(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 69(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 70(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 71(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 72(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 73(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 74(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 75(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 76(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 77(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 78(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 79(T+60min)
动作:事后审计
细节:填写可观测性盲区表;链到 22-chaos backlog。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 80(演练复盘)
动作:Game Day 纪要模板
细节:角色、gap、owner、due date。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 81(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 82(T+10min)
动作:检查 redis_exporter
细节:redis_connected_clients
vs maxclients。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 83(T+14min)
动作:Tempo TraceQL
细节:{ resource.service.name = "checkout" && duration > 1s }。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 84(T+22min)
动作:Loki pattern
细节:{service=“checkout”} | json | pool_wait_ms > 500
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 85(T+28min)
动作:Events 面板
细节:关联 ConfigMap rollout 与 13-events。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 86(T+33min)
动作:缓解:scale
细节:kubectl scale deployment/checkout --replicas=16
临时扩容。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 87(T+38min)
动作:回滚 redis CM
细节:kubectl rollout undo deployment/checkout-redis。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 88(T+50min)
动作:SLO 恢复观察
细节:Burn Rate 回落至 < 1× 持续 30min。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
时间线扩展 1(T+8min)
动作:按 endpoint 分解
PromQL
细节:确认是否仅
/api/checkout/submit 异常。
系列交叉:对照 18-slo 错误预算消耗与 19-alerting Page 路由。
参考资料
- Google, Site Reliability Engineering, Ch.14, O’Reilly, 2016
- PagerDuty, Incident Response Guide, https://response.pagerduty.com/
- Google, Site Reliability Workbook, Ch.5, O’Reilly
- Prometheus, Alerting Rules, https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/
- Grafana, Tempo TraceQL, https://grafana.com/docs/tempo/
- 本系列 01–22 各篇
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
可观测性工程
从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。全 25 篇。
【可观测性工程】数据模型:时间序列、日志、Span、Profile 的内部表达
拆解 Metrics、Logs、Traces、Profiles、Events 五大支柱在磁盘和内存中的内部数据模型。字段级对照 Prometheus TSDB block、Loki chunk、Tempo block,给出带假设的存储成本估算公式,并解释索引策略如何决定账单与查询延迟。
【可观测性工程】存储与成本:采样、下采样、冷热分层、对象存储
可观测性数据量持续增长,存储成本常超过计算成本。拆解四大支柱的成本结构、采样与保留期策略、冷热分层架构,以及带显式假设的成本估算 worksheet。
【可观测性工程】可观测性全景:Metrics、Logs、Traces、Profiles、Events 五大支柱
从控制论到云原生:拆解可观测性的五大信号支柱,对比监控与可观测性的本质区别,梳理开源/商业/SaaS 分类,以及国内互联网公司三大支柱落地现状与典型工程坑点。