关于 disaster-recovery-plan
这是一个为工程师、SRE 和值班响应人员编写系统灾难恢复计划的 Skill。它根据提供的服务信息,整理恢复目标、故障场景及逐步操作手册。
主要功能
- 01收集服务与基础设施信息
- 02设定可衡量的 RPO 和 RTO
- 03梳理故障场景
- 04编写包含命令的恢复手册
- 05加入恢复验证步骤
适用场景
- 01为生产服务准备恢复流程
- 02记录区域故障切换步骤
- 03规划数据库损坏后的恢复
- 04协助值班团队响应中断
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mohitagw15856/ pm-claude-skills --skill disaster-recovery-plan安装后在 Claude Code 中输入/disaster-recovery-plan确认已加载。
详细介绍
灾难恢复计划技能
为服务或系统制定完整的灾难恢复计划,让工程师、SRE 和值班响应人员能够在灾难场景中以尽可能短的时间完成恢复。一份优秀的 DR 计划会定期测试,包含精确的命令(而非含糊的说明),并将 RTO/RPO 目标设为可衡量的指标,以便团队判断恢复是否成功。
必要输入
如果尚未提供,请询问以下信息:
- 服务名称及其功能(业务职能和技术角色)
- 关键性等级——长时间停机的业务影响(例如:Tier 1 = 营收关键,Tier 2 = 影响运营,Tier 3 = 仅限内部使用)
- 当前基础设施配置——云服务提供商、区域/可用区、部署模型(Kubernetes、ECS、VM、无服务器)
- RPO/RTO 要求——恢复点目标(可接受的数据丢失量)和恢复时间目标(可停机多长时间)
- 备份策略——备份内容、备份频率、备份存储位置、保留策略
- 值班联系人——响应人员链条中的姓名和联系方式
输出格式
灾难恢复计划:[服务名称]
团队:[团队名称] | 技术负责人:[姓名] 关键性等级:[Tier 1 / Tier 2 / Tier 3] | 上次测试:[日期] 下次 DR 测试:[日期] | 文档负责人:[姓名] 上次更新:[日期] | **评审周期:**每季度
**遇到紧急情况?请跳至第 3 节——故障场景操作手册。**找到与当前情况相符的场景,并严格按照步骤操作。
1. 恢复目标
| 目标 | 值 | 依据 |
|---|---|---|
| RPO(恢复点目标) | [X 分钟/小时] | [例如:“最后一次已提交的事务——数据库复制为同步模式”] |
| RTO(恢复时间目标) | [Y 分钟/小时] | [例如:“30 分钟后开始影响营收;目标是在 15 分钟内恢复”] |
| MTTR 目标(非灾难) | [Z 分钟] | [运营事件,不包括 DR 事件] |
| 数据保留期限(备份) | [N 天/周] | [合规要求或运营策略] |
| 备份频率 | [每 X 小时] | [由 RPO 决定——备份间隔必须 ≤ RPO] |
实际意义:
- 如果数据库损坏,事务丢失量最多为 [X 分钟],超过该范围将造成不可接受的业务影响。
- 宣布发生 DR 事件后,服务必须在 [Y 分钟/小时] 内恢复运行。
- 如果无法达到任一目标,请立即升级给 [工程经理] 处理。
2. 故障场景清单
| 场景 | 可能性 | 影响 | RTO 目标 | RPO 目标 | 操作手册 |
|---|---|---|---|---|---|
| 单个可用区故障 | 中 | [部分 / 完全中断] | [15 分钟] | [0 — 无数据丢失] | 第 3.1 节 |
| 整个区域故障 | 低 | 完全中断 | [60 分钟] | [5 分钟] | 第 3.2 节 |
| 数据库损坏 / 数据丢失 | 低 | 完全中断 | [90 分钟] | [RPO 值] | 第 3.3 节 |
| 关键依赖项中断 | 高 | [部分降级] | [30 分钟] | [不适用] | 第 3.4 节 |
| 安全漏洞 / 勒索软件 | 极低 | 完全中断 + 调查 | [4 小时] | [最近一次干净备份] | 第 3.5 节 |
| 意外批量删除数据 | 低 | 部分或全部数据丢失 | [60 分钟] | [RPO 值] | 第 3.6 节 |
3. 故障场景操作手册
3.1 单个可用区故障
**触发条件:**一个 AZ 无法访问——该区域中的 Pod/实例停止响应。
**检测方式:**PagerDuty 告警 [AlertName] 触发,或云服务提供商状态页面显示 AZ 降级。
预期 RTO:[15 分钟] | **预期 RPO:**零(多 AZ 复制正常工作时不会丢失数据)
步骤 1 — 确认故障
# Check pod/instance health across zones
kubectl get pods -o wide -n [namespace] | grep -v Running
# Check which nodes are affected
kubectl get nodes -o wide | grep -v Ready
# Verify cloud provider AZ status
# AWS: https://health.aws.amazon.com/health/status
# GCP: https://status.cloud.google.com
步骤 2 — 评估是否已自动恢复
# If using auto-scaling, check if replacement instances launched
kubectl get pods -n [namespace] --watch
# Check deployment replica count
kubectl get deployment [service-name] -n [namespace]
# Verify load balancer health checks are passing
[cloud provider CLI command to check target group health]
步骤 3 — 如果自动恢复停滞,则强制重新调度
# Cordon the affected node so no new pods schedule on it
kubectl cordon [node-name]
# Drain the node — moves all pods to healthy nodes
kubectl drain [node-name] --ignore-daemonsets --delete-emptydir-data
# Verify pods have rescheduled successfully
kubectl get pods -o wide -n [namespace]
步骤 4 — 验证服务健康状况
# Smoke test key endpoints
curl -s -o /dev/null -w "%{http_code}" https://[service-url]/health
curl -s -o /dev/null -w "%{http_code}" https://[service-url]/[critical-endpoint]
# Check error rate in monitoring
[dashboard link or query]
**确认恢复的条件:**所有 Pod 均处于 Running 状态,健康检查返回 200,错误率回到基线水平。
3.2 整个区域故障
触发条件: 主区域完全不可用。 检测方式: 所有服务健康检查均失败,云服务提供商状态页面确认发生区域级事件。 预计 RTO: [60 minutes] | 预计 RPO: [5 minutes — 基于跨区域复制延迟]
步骤 1 — 确认区域故障(5 分钟)
# Confirm the primary region is unreachable
ping [primary-region-endpoint] || echo "Primary region unreachable"
# Check replication lag on standby region database
[command to check replica lag — e.g. for RDS: aws rds describe-db-instances --region [dr-region]]
步骤 2 — 宣布 DR 事件并通知相关人员(2 分钟)
在 #incidents 中发布:
🔴 DR EVENT — [Service Name] — Region Failure
Primary region: [region] — UNREACHABLE
Activating failover to: [dr-region]
Incident commander: [Name]
Next update: 15 minutes
通过 PagerDuty 呼叫 [Engineering Manager] 和 [CTO/VP Eng]。
步骤 3 — 提升 DR 数据库(10 分钟)
# AWS RDS — promote read replica to primary
aws rds promote-read-replica \
--db-instance-identifier [dr-replica-identifier] \
--region [dr-region]
# Wait for promotion to complete
aws rds wait db-instance-available \
--db-instance-identifier [dr-replica-identifier] \
--region [dr-region]
# Record the new database endpoint
aws rds describe-db-instances \
--db-instance-identifier [dr-replica-identifier] \
--region [dr-region] \
--query 'DBInstances[0].Endpoint.Address'
步骤 4 — 在 DR 区域部署服务(20 分钟)
# Update service configuration to point at DR database
kubectl set env deployment/[service-name] \
DATABASE_URL=[new-dr-database-url] \
-n [namespace] \
--context [dr-region-context]
# Scale up the DR deployment
kubectl scale deployment/[service-name] --replicas=[N] \
-n [namespace] \
--context [dr-region-context]
# Verify all pods are running
kubectl get pods -n [namespace] --context [dr-region-context]
步骤 5 — 切换 DNS / 负载均衡器(5 分钟)
# Update DNS to point to DR region load balancer
# AWS Route 53:
aws route53 change-resource-record-sets \
--hosted-zone-id [zone-id] \
--change-batch file://dr-failover-dns.json
# Verify DNS propagation (may take up to [TTL] seconds)
dig [service-domain] @8.8.8.8
步骤 6 — 端到端验证
# Full smoke test against DR endpoint
curl -s https://[service-url]/health
[run automated smoke test suite if available]
满足以下条件即可确认恢复: DNS 解析到 DR 区域,冒烟测试通过,错误率恢复到基线水平。
故障切换后的操作(非紧急 — 服务稳定后执行):
- 在确认根本原因已解决之前,不要切回主区域
- 记录数据丢失时间窗口(检查故障发生时的复制延迟)
- 开始进行事后复盘 — 参见 [incident-postmortem skill]
3.3 数据库损坏或数据丢失
触发条件: 由于软件 Bug、操作人员错误或硬件故障,数据库中的数据遭到损坏、删除或出现其他错误。 检测方式: 应用程序报错并提示数据缺失或无效、查询错误率监控告警、用户报告。 预计 RTO: [90 minutes] | 预计 RPO: [备份间隔 — 例如 1 小时]
步骤 1 — 立即止损
# Put the service into maintenance mode to prevent further writes to corrupted data
[command to enable maintenance mode — e.g. kubectl set env deployment/[name] MAINTENANCE_MODE=true]
# Or: scale down the service to zero to prevent writes
kubectl scale deployment/[service-name] --replicas=0 -n [namespace]
步骤 2 — 评估数据损坏范围
# Identify which tables/records are affected
[SQL query to check data integrity — e.g.]
# psql $DATABASE_URL -c "SELECT COUNT(*) FROM [table] WHERE [integrity check condition]"
# Determine when corruption started (cross-reference with deploy times and error logs)
[log query to find earliest error — e.g. in Datadog:]
# service:[service-name] status:error "[corruption error message]" | sort by timestamp asc
步骤 3 — 确定正确的恢复点
# List available backups
[command to list backups — e.g. for RDS:]
aws rds describe-db-snapshots \
--db-instance-identifier [db-identifier] \
--query 'DBSnapshots[*].[SnapshotCreateTime,DBSnapshotIdentifier]' \
--output table
# Choose the most recent backup BEFORE corruption started
# Record the chosen snapshot ID: [snapshot-id]
步骤 4 — 从备份恢复
# Restore to a NEW database instance (never overwrite production directly)
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier [service-name]-restored-[date] \
--db-snapshot-identifier [snapshot-id] \
--region [region]
# Wait for restore to complete
aws rds wait db-instance-available \
--db-instance-identifier [service-name]-restored-[date]
# Get the restored instance endpoint
aws rds describe-db-instances \
--db-instance-identifier [service-name]-restored-[date] \
--query 'DBInstances[0].Endpoint.Address'
步骤 5 — 验证恢复的数据
# Connect to restored database and verify integrity
psql [restored-db-endpoint] -U [user] -d [database] -c "[data integrity query]"
# Confirm record counts match expectations
psql [restored-db-endpoint] -U [user] -d [database] -c "SELECT COUNT(*) FROM [critical-table]"
步骤 6 — 将服务指向恢复后的数据库
kubectl set env deployment/[service-name] \
DATABASE_URL=postgres://[user]:[pass]@[restored-endpoint]/[db] \
-n [namespace]
kubectl scale deployment/[service-name] --replicas=[N] -n [namespace]
满足以下条件即可确认恢复: 服务已使用恢复后的数据库运行,数据完整性检查通过,错误率恢复到基线水平。
3.4 关键依赖项中断
触发条件: [service name] 所依赖的服务不可用或性能下降。 检测方式: 调用 [dependency] 的端点错误率或延迟上升、依赖项所有者发出告警。 预计 RTO: 取决于依赖项 — [30 minutes for mitigation, resolution depends on dependency owner]
依赖关系图:
| 依赖项 | 关键程度 | 降级行为 | 缓解措施 |
|---|---|---|---|
| [Database] | 关键 — 所有写入均失败 | 完全中断 | 启用 DR 数据库(第 3.3 节) |
| [Cache — Redis] | 高 — 延迟上升 | 性能下降 | 绕过缓存,直接从 DB 提供数据 |
| [Auth service] | 关键 — 身份验证失败 | 所有需要身份验证的端点均失败 | 返回缓存的令牌(如果已实现) |
| [Message queue] | 中 — 异步处理延迟 | 写入成功,异步任务排队 | 队列积压 — 参见值班手册 |
| [External API — name] | 低 — 功能 X 不可用 | 平稳降级 | 使用功能标志禁用功能 X |
缓解步骤:
# Enable circuit breaker / fallback for [dependency] if implemented
kubectl set env deployment/[service-name] [DEPENDENCY]_CIRCUIT_BREAKER=open -n [namespace]
# Enable feature flag to disable [dependency-backed feature]
[feature flag CLI command or dashboard link]
# Check if dependency has a status page
# [Dependency status URL]
升级处理: 通过 [PagerDuty / Slack #[channel]] 联系 [dependency] 的值班人员。告知对方你们服务的错误率以及依赖项错误开始出现的时间。
3.5 安全漏洞或勒索软件攻击
触发条件: 有证据表明存在未经授权的访问、数据外泄或服务数据被加密。 检测方式: 安全工具告警、异常访问模式、用户报告数据泄露。 预计 RTO: [4+ hours — prioritise containment over speed] | 预计 RPO: [最后一次验证无问题的备份]
步骤 1 — 立即隔离
# Take the service offline — do not attempt to recover while breach is active
kubectl scale deployment/[service-name] --replicas=0 -n [namespace]
# Revoke all API keys and service account credentials immediately
[command to rotate secrets — e.g. via Vault or cloud provider]
# Block all external access at network level
[firewall/security group command to deny all inbound traffic]
步骤 2 — 立即通知安全团队 通过 PagerDuty 呼叫 [Security lead]。在安全团队参与前,切勿尝试修复问题。
在 #security-incidents 中发布(私有频道,不是 #incidents):
🔴 SECURITY INCIDENT — [Service Name]
Time detected: [Time]
Evidence: [One sentence — what was observed]
Actions taken: Service isolated, credentials revoked
Awaiting: Security team guidance
步骤 3 — 保留证据
# Export current logs before any remediation
[log export command — preserve evidence for forensics]
# Snapshot the current state of all infrastructure
[snapshot/image command]
步骤 4 及后续步骤 — 遵循安全团队的指导。 在安全团队确认攻击途径已关闭之前,不要从备份恢复。
3.6 意外的大规模数据删除
触发条件: 操作人员、脚本或应用程序错误导致记录被大规模删除。 检测方式: 记录数量骤降、用户报告数据丢失、应用程序报错。 预期 RTO: [60 minutes] | 预期 RPO: [Backup interval]
# Step 1 — Stop further writes immediately
kubectl scale deployment/[service-name] --replicas=0 -n [namespace]
# Step 2 — Determine what was deleted and when
psql $DATABASE_URL -c "
SELECT schemaname, tablename,
n_dead_tup, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC LIMIT 10;
"
# Step 3 — Check if deletion is recoverable via MVCC (PostgreSQL)
# Records may still be recoverable if VACUUM has not run
psql $DATABASE_URL -c "
SELECT * FROM [table]
WHERE xmax != 0 -- recently deleted rows
LIMIT 100;
"
# Step 4 — If not recoverable via MVCC, restore from backup
# Follow Section 3.3 (Database Corruption runbook) from Step 3 onward
4. 备份和恢复流程
备份配置
| 数据存储 | 备份类型 | 频率 | 保留期限 | 位置 |
|---|---|---|---|---|
| [Primary database] | 自动快照 | 每 [N] 小时 | [N] 天 | [S3 bucket / cloud storage path] |
| [Primary database] | 事务日志备份 | 持续进行 | [N] 天 | [Location] |
| [Secondary store — e.g. Redis] | RDB 转储 | 每日 | [N] 天 | [Location] |
| [Blob/object storage] | 跨区域复制 | 持续进行 | [N] 天 | [DR region bucket] |
| [Config / secrets] | Terraform 状态 + Vault 备份 | 变更时 | 永久 | [Location] |
备份验证(每周执行)
# Test restore of latest database backup to a throwaway instance
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier [service-name]-backup-test-$(date +%Y%m%d) \
--db-snapshot-identifier $(aws rds describe-db-snapshots \
--db-instance-identifier [db-id] \
--query 'sort_by(DBSnapshots, &SnapshotCreateTime)[-1].DBSnapshotIdentifier' \
--output text)
# Wait for restore, then run integrity checks
psql [test-instance-endpoint] -c "[integrity check query]"
# Confirm row counts match recent production values (allow ≤ RPO difference)
psql [test-instance-endpoint] -c "SELECT COUNT(*) FROM [critical-table]"
# Destroy the test instance
aws rds delete-db-instance \
--db-instance-identifier [service-name]-backup-test-$(date +%Y%m%d) \
--skip-final-snapshot
5. DR 测试频率
必须定期测试。未经测试的 DR 计划不算 DR 计划。
| 测试类型 | 频率 | 执行人员 | 通过标准 |
|---|---|---|---|
| 备份恢复验证 | 每周(自动) | 值班轮班人员 | 恢复完成,完整性检查通过 |
| 可用区故障切换演练 | 每月 | 工程团队 | 达到 RTO 目标,零数据丢失 |
| 区域故障切换演练 | 每季度 | 工程团队 + SRE | 达到 RTO/RPO 目标 |
| 完整 DR 演练日 | 每年 | 工程团队 + 相关方 | 演练所有场景,记录差距 |
| 混沌工程(基础设施故障) | 每周(自动) | 混沌工程工具 | 服务平稳降级并自动恢复 |
演练日流程
- 演练日前(提前 1 周): 通知所有相关方,当天冻结生产环境变更,准备 DR 环境。
- 确定范围: 从第 2 节选择 2–3 个场景。测试前记录预期结果。
- 执行: 一人担任事件指挥官,其他人执行运行手册步骤,另安排一人观察并计时。
- 测量: 针对每个场景,记录实际 RTO 和 RPO,并与目标对比。
- 复盘(当天): 记录差距、运行手册中的错误以及自动化机会。
- 后续事项: 为发现的每项差距创建工单。优先级:P1 项必须在下次演练日前修复。
6. 沟通计划
DR 事件期间的内部沟通
事件指挥官职责:
- 宣布 DR 事件并建立事件频道
- 至少每 15 分钟发布一次更新
- 决定是否进行故障切换(不要让团队通过委员会投票决定)
- 告知业务相关方预计恢复时间
DR 事件开始时通知以下人员:
| 角色 | 姓名 | 联系方式 | 通知时间 |
|---|---|---|---|
| 工程经理 | [Name] | [Slack / Phone] | 立即 |
| CTO / VP Engineering | [Name] | [Phone] | Tier 1 服务:立即 |
| 客户成功负责人 | [Name] | [Slack] | 对客户造成影响时 |
| 安全负责人 | [Name] | [Slack / PagerDuty] | 怀疑发生安全漏洞时 |
| 法务 / 合规 | [Name] | [Email / Phone] | 数据丢失涉及 PII 时 |
沟通模板
宣布 DR 事件:
🔴 DR EVENT — [Service Name]
Time: [HH:MM UTC]
Scenario: [Zone failure / Region failure / Data loss / etc.]
Impact: [Who is affected and how]
RTO target: [X minutes]
Incident commander: [Name]
War room: [Slack channel / call link]
Next update: [Time + 15 min]
状态更新(每 15 分钟):
🔴 DR UPDATE — [Service Name] — [HH:MM UTC]
Status: [Investigating / Executing recovery / Verifying]
Progress: [One sentence on current step]
Blockers: [Any — or "None"]
Updated RTO estimate: [Time]
Next update: [Time + 15 min]
确认恢复:
✅ DR RESOLVED — [Service Name] — [HH:MM UTC]
Total downtime: [X minutes]
Data loss: [None / X minutes of transactions]
RTO target: [X min] — Actual: [Y min] — [MET / MISSED]
RPO target: [X min] — Actual: [Y min] — [MET / MISSED]
Root cause: [One sentence]
Post-incident review: [Scheduled for / Link when created]
7. DR 准备情况检查清单
每季度以及每次重大基础设施变更前运行此检查清单:
备份:
- 自动备份正在运行,且失败时会触发警报
- 最近一次备份恢复已在过去 7 天内完成测试
- 备份保留策略符合 RPO 和合规要求
- 备份存储在与主环境不同的区域/账户中
故障转移基础设施:
- DR 区域/环境已存在并完成配置(而不只是有文档记录)
- DNS 故障转移流程已记录,并包含准确的命令
- DR 数据库副本保持最新(复制延迟在 RPO 范围内)
- 服务可通过单条命令或自动化流水线部署到 DR 区域
运行手册:
- 第 3 节中的所有运行手册都已在上一季度内完成测试
- 已根据当前基础设施验证运行手册中的命令(没有过时的引用)
- 联系人名单是最新的(不包含已离职员工)
访问权限:
- 值班工程师可以访问 DR 区域控制台/CLI
- 已配置并测试 DR 区域的服务账户凭据
- 已设置紧急访问的应急账户,以便 SSO 不可用时使用
监控:
- DR 区域中也配置了监控(而不只是主区域)
- DR 环境出现问题时,警报会正确触发
质量检查
- RPO 和 RTO 目标是具体数值,而非范围,并已与业务部门达成一致
- 每份运行手册中的每条命令都由人工在上一季度内实际运行过,而非未经测试便从文档中复制
- DR 数据库已部署在 DR 区域,并且监控复制延迟
- 已在过去 7 天内完成端到端备份恢复测试
- 游戏日安排已列入团队日历,而不只是记录在此处
- 联系人名单包含当前电话号码,而不只是 Slack 用户名(DR 事件期间 Slack 可能不可用)
- 安全漏洞运行手册(3.5)明确列出安全团队联系人,且不会尝试自行修复
- 监控仪表板中清晰显示所有阈值(RTO/RPO),以便实时衡量实际值与目标值
反模式
- 不要编写未经测试的运行手册命令——在真实灾难期间,认知负荷最高时,运行手册中未经测试的命令会带来直接危险
- 未经业务部门批准,不要设定 RTO/RPO 目标——技术团队经常设定理想化目标,而这些目标并未反映业务对停机成本的实际承受能力
- 不要只写每种故障转移场景的“顺利流程”——运行手册必须明确说明恢复步骤本身失败时该怎么办
- 不要只将 Slack 用户名列为升级联系人的联系方式——区域范围故障期间 Slack 可能不可用;电话号码是必需的
- 不要在未预先承诺修复所发现问题的情况下安排 DR 游戏日——无人负责后续行动项的游戏日只是作秀,并不能提升应急准备程度
示例触发语句
- “编写 DR 计划。”
- “记录故障转移流程。”
- “创建恢复运行手册。”
- “定义 RTO/RPO 目标。”
- “为灾难恢复游戏日做准备。”