灾难恢复演练
用 RTO/RPO 对齐业务承诺;Runbook 写明顺序、验证与中止条件。本页提供决策流示意,以及按目标 RTO(分钟)自动生成带时间盒的检查清单,便于桌面推演与实战对照。
SKILL 应定义演练场景(单 AZ、整区域、供应商 API 大面积不可用)、参与角色、成功标准与中止条件,避免演练本身造成生产事故。
技术清单包括:DNS / 流量入口切换、数据库提升只读副本或冷备、密钥与配置在灾备区可用、批处理与消息队列的积压处理策略。
演练后须产出:实际耗时与目标差距、发现的单点故障、文档与自动化缺口、责任人及修复截止日期,并由 Agent 协助整理为可跟踪条目。
RTO / RPO 定义与对齐
RTO(Recovery Time Objective)
从「宣告事件」到「关键业务在约定范围内恢复可用」的目标最长时间。需写明测量起点(故障发现 / 正式宣战 / Runbook 第一步)与终点(哪条 SLO、哪些流量或哪些租户算恢复)。
RPO(Recovery Point Objective)
可接受的最大数据丢失时间窗口,通常用「最后一次一致备份 / 复制位点」表达。异步复制、批同步与人工补数都会抬高实际 RPO;须在 Runbook 中写清「以哪一刻为准」及对账方式。
- 按系统分层声明 RTO/RPO(入口、应用、数据、消息、批处理),避免「全站一个数」掩盖短板。
- 与客户或监管有承诺时,演练频率与实测结果须可追溯到合规矩阵或合同条款。
- 恢复路径必须经过验证(含定期还原演练),而非仅纸面 Runbook。
#!/bin/bash
# RTO/RPO 演练时间线记录脚本(在演练期间运行)
# 用法:记录每个里程碑时间戳,演练后计算实际 RTO/RPO
LOG_FILE="dr-drill-$(date +%Y%m%d-%H%M).log"
log_event() {
local label="$1"
echo "$(date -Iseconds) | $label" | tee -a "$LOG_FILE"
}
# T0:演练/事件宣告时间(手动记录)
log_event "T0_INCIDENT_DECLARED"
# 等待执行切换...
read -p "按 Enter 记录 T1(DNS/流量切换开始)..."
log_event "T1_TRAFFIC_SWITCH_START"
read -p "按 Enter 记录 T2(数据库副本提升完成)..."
log_event "T2_DB_FAILOVER_COMPLETE"
read -p "按 Enter 记录 T3(健康探针全绿)..."
log_event "T3_HEALTH_CHECKS_PASS"
read -p "按 Enter 记录 T4(业务验证完成,宣告恢复)..."
log_event "T4_RECOVERY_DECLARED"
# 计算实际 RTO
echo "=== 演练时间线分析 ==="
cat "$LOG_FILE"
# 实际 RTO = T4 - T0(与目标 RTO 对比)
# 实际 RPO = T2 时数据库最后一致备份时间与 T0 之差
Runbook 结构要点
Runbook 是演练与真实切换的共用文档:每一步写清执行者、前置条件、命令或控制台路径、预期输出、失败时回退或升级路径。Agent 生成草稿时,应要求引用监控链接、工单模板与负责人 on-call。
- 触发与分级:何种症状升级到灾备、谁有权宣战、与事件管理的接口(Incident ID)。
- 依赖拓扑:按切换顺序列出 DNS、LB、计算、数据、密钥、第三方 API;标注只读依赖与可延迟项。
- 执行步骤:编号步骤、每步预计耗时、并行边界;明确「不可自动执行」的人工审批点。
- 验证:探针、金丝雀、抽样业务交易、数据一致性检查;与 RTO 时间盒对齐。
- 通信:状态页、大客户话术、内部 war room 渠道与更新节奏。
- 中止与回滚:何时停止切换、如何回到原区域或已知良好状态。
- 复盘:实际 RTO/RPO、差距原因、改进项与截止日期。
灾备决策与执行流
[ 监控 / 人工发现异常 ]
│
▼
┌─────────────┐ 对齐:影响面、是否误报、是否需宣战
│ 事件分级 │──── 输出:Incident owner、通信节奏初稿
└─────────────┘
│
▼
┌─────────────┐ 对照 Runbook:RTO/RPO、中止条件、审批点
│ War room │──── 记录:每步执行人、时间戳、命令/工单链接
└─────────────┘
│
▼
┌─────────────┐ DNS / 流量 / 计算 / 数据按序或并行(预定义)
│ 执行切换 │──── 密钥与配置在目标区可用;队列与批任务策略就绪
└─────────────┘
│
▼
┌─────────────┐ 探针 + 业务抽样 + 数据对账(相对 RPO)
│ 技术验证 │──── 未达标则中止或回滚,不得静默「差不多」
└─────────────┘
│
▼
┌─────────────┐ 状态页 / 客户通知 / 内部同步
│ 对外沟通 │──── 与法务、大客户流程一致(若适用)
└─────────────┘
│
▼
┌─────────────┐ 差距、单点、文档与自动化缺口 → 可跟踪项
│ 演练复盘 │
└─────────────┘
与备份技能一致:恢复必须可重复演练;时间盒仅作辅助,真实 Runbook 中的审批与第三方依赖可能显著拉长某一段,须在模板中显式列出。
演练场景与成功标准
- 单 AZ、整区域、关键供应商 API 大面积不可用等场景分别定义成功标准与资源消耗上限。
- 通信预案:状态页、大客户通知话术、内部 war room 渠道;避免演练期间对外误发「真实灾难」文案(使用约定测试标识)。
- 演练后登记改进项:自动化缺口、文档歧义、on-call 盲区,并设责任人与截止日期。
# 常见灾难场景恢复手册
# === 场景 1:主数据库宕机 ===
# 预期 RTO: 15 min | RPO: 30s(同步副本)
echo "Step 1: 确认主库宕机(非误报)"
pg_isready -h primary-db.internal -U postgres || echo "主库不可达"
echo "Step 2: 提升只读副本为主库(PostgreSQL)"
pg_ctl promote -D /var/lib/postgresql/data
# 或 AWS RDS:
aws rds failover-db-cluster --db-cluster-identifier myapp-cluster
echo "Step 3: 更新连接字符串指向新主库"
kubectl set env deployment/myapp \
DATABASE_URL="postgresql://new-primary.internal:5432/myapp"
echo "Step 4: 验证数据完整性(对账)"
psql $NEW_DB_URL -c "SELECT COUNT(*) FROM orders WHERE created_at > NOW()-INTERVAL '1h';"
# === 场景 2:区域故障(Region Failover)===
# 预期 RTO: 60 min | RPO: 5 min(异步复制)
echo "Step 1: 切换 DNS 到备用区域入口"
aws route53 change-resource-record-sets \
--hosted-zone-id Z123456 \
--change-batch file://dns-failover-to-us-west.json
# === 场景 3:数据误删恢复 ===
echo "Step 1: 停止写入(关闭特性开关或限流)"
echo "Step 2: 找到误删前最近一次备份时间点"
aws rds describe-db-snapshots --db-instance-identifier myapp-db \
--query 'sort_by(DBSnapshots, &SnapshotCreateTime)[-1]'
echo "Step 3: 恢复到 PITR 时间点(需人工审批)"
# 演练后复盘模板(5 Whys 格式)
# 演练日期:YYYY-MM-DD | 场景:DB 主库宕机 | 目标 RTO:15 min | 实际:23 min
## 时间线回顾
# T+00: 监控告警触发(DB 连接失败)
# T+05: On-call 确认非误报,宣告 DR 演练
# T+12: 副本提升操作完成(慢了 7 min,原因见下)
# T+18: 应用连接字符串更新并重启
# T+23: 健康探针全绿,宣告恢复(超目标 8 min)
## 5 Whys 分析
# 为什么实际 RTO 超出目标 8 分钟?
# → 副本提升脚本执行失败(缺少 pg_ctl 权限)
# 为什么缺少权限?
# → 上次权限变更未同步到 DR 账号
# 为什么未同步?
# → 权限变更流程不包含 DR 环境检查
# 为什么流程不包含?
# → Runbook 未要求变更同步到 DR
# 根本原因:Runbook 与 DR 环境维护流程脱节
## 改进项
# 1. [Owner: @ops-alice] [Due: 2024-05-01] 修复 DR 账号权限
# 2. [Owner: @sre-bob] [Due: 2024-05-15] 更新 Runbook 含 DR 环境检查步骤
# 3. [Owner: @sre-team] [Due: 2024-06-01] 添加 DR 账号权限自动化验证 CI
RTO 分钟时间盒检查清单
输入目标 RTO(分钟),按预设阶段比例生成「累计截止时间」与可勾选步骤,用于桌面推演计时或打印对照。比例可按组织习惯在 Runbook 中改写;此处为通用模板。
各阶段截止时间与生成的检查项
阶段比例:宣告 8% · 评估 12% · 切换 42% · 技术验证 22% · 业务确认 10% · 沟通收尾 6%(总和 100%)。各段分钟数先按比例取整再按余数补齐,保证各段之和严格等于目标 RTO;极短 RTO 下可能出现某段为 0,可与邻段合并演练。
---
name: disaster-recovery
description: DR 演练脚本、RTO/RPO 测量、场景手册与 5 Whys 复盘
version: 2.0
---
# 演练场景定义
- 场景 A:主数据库宕机(RTO ≤ 15 min,RPO ≤ 30s)
- 场景 B:整区域故障(RTO ≤ 60 min,RPO ≤ 5 min)
- 场景 C:关键供应商 API 大面积不可用(降级策略)
- 场景 D:数据误删恢复(PITR + 人工审批)
# RTO/RPO 测量方法
- T0:宣告/演练开始时间戳
- T_switch:流量/DNS 切换完成
- T_data:数据库副本提升完成
- T_health:健康探针全绿
- T_biz:业务验证完成(宣告恢复)
- 实际 RTO = T_biz - T0;与目标对比并记录差距
# Runbook 关键步骤
- DB 故障:pg_ctl promote 或 aws rds failover-db-cluster
- 区域故障:aws route53 change-resource-record-sets
- 数据误删:aws rds restore-db-instance-to-point-in-time
- 验证:对账查询 + 业务抽样 + 错误率监控
# 复盘格式(5 Whys)
- 时间线:各阶段实际耗时 vs 目标
- 根本原因:逐层追问「为什么」(≥5 层)
- 改进项:Owner + Due Date + 验证方式