Kubernetes集群灾难恢复方法论:RTO/RPO、备份分层、演练与跨区域切换
灾难恢复(Disaster Recovery,DR) 回答的不是「怎么备份」,而是「出事之后多久能恢复、能丢多少数据、谁来决定切换」。备份只是 DR 的一个输入 —— 有备份但没有恢复流程、没有演练记录、没有决策人,等于没有 DR。
一个常见的误解是把 DR 当成「运维的事」。实际上 DR 是业务连续性的一部分:业务方定义 RTO/RPO,运维实现它,双方一起验收。技术手段只是最后一步。
两个指标决定了整套架构的成本,必须在动手之前先定下来:
RTO(Recovery Time Objective) 恢复时间目标 —— 业务能容忍中断多久
RPO(Recovery Point Objective) 恢复点目标 —— 业务能容忍丢多少数据
例:
内部工具 RTO 24h / RPO 24h 每天一次备份足矣
一般业务系统 RTO 4h / RPO 1h 定时备份 + 自动化恢复脚本
核心交易 RTO 15m / RPO 0 需要同步复制 + 多活,成本指数级上升
关键约束:RPO 越接近 0,成本越接近无穷。RPO=0 意味着同步复制,而跨可用区的同步复制受物理延迟限制(同城两中心往返通常 1-3 ms,跨城 30 ms 以上),跨区域做到 RPO=0 在工程上基本不成立。
不同级别的故障,恢复手段完全不同。「灾难恢复」这个词通常只指第 4 级及以下:
1. 单 Pod 故障 kubelet/Deployment 自动重建,不需要 DR
2. 单节点故障 工作负载自动漂移,不需要 DR(要保证副本数与 PDB)
3. 命名空间/资源误删 从备份恢复该命名空间,分钟级
4. 控制面损坏 etcd 快照恢复,或重建控制面,小时级
5. 整个集群/区域故障 从备份在新集群重建,或切换到异地集群,小时到天级
6. 数据被污染/加密 需要多版本备份 + 不可变存储,能回到污染前的时间点
第 6 级最容易被低估:勒索软件不会立刻发作,它先潜伏数周把备份一起加密。这时候「只保留最近一份备份」的策略是致命的。
集群里需要保护的东西远不止 etcd。分层看:
L1 声明层 Deployment/Service/ConfigMap/Secret/CRD/CR 等 API 对象
L2 数据层 PersistentVolume 里的实际数据
L3 控制面 etcd 数据、控制面证书与密钥、加密配置
L4 集群外 镜像仓库、DNS 记录、负载均衡配置、IaC 代码、CI/CD 流水线
L5 凭据 对象存储 AK/SK、云厂商账号、备份加密密钥、kubeconfig
绝大多数「恢复失败」的案例,问题出在 L4 和 L5:集群恢复出来了,但镜像仓库没同步、DNS 没切、备份存储的密钥在离职同事的密码管理器里。
| 形态 | 做法 | 典型 RTO | 成本 |
|---|---|---|---|
| 冷备(Backup & Restore) | 备份放对象存储,出事时新建集群恢复 | 数小时到数天 | 低 |
| 温备(Pilot Light) | 异地常驻最小集群,出事时扩容 | 30 分钟到数小时 | 中 |
| 多活(Active-Active) | 多集群同时承载流量 | 接近 0 | 高 |
冷备的 RTO 里,新建集群 + 拉起控制面 + 恢复声明 + 恢复数据 + 改 DNS 每一步都要算时间。很多团队估的 RTO 只算了 velero restore 那一步,真实耗时是它的 5-10 倍。
跨区域切换不只是「把流量切过去」,至少要覆盖:
1. 镜像 目标区域仓库里有同版本镜像(建议做镜像同步,而不是切过去再拉)
2. 声明 集群资源能在目标集群重建(注意 StorageClass/IngressClass 名字差异)
3. 数据 状态化服务的数据如何过去(存储层复制 / 应用级复制)
4. 证书 TLS 证书、ServiceAccount 密钥、webhook CA 是否在目标可用
5. 网络 Service CIDR、Pod CIDR 不能与本区域其他网络冲突
6. 流量 DNS TTL 要提前调小,否则切了也要等 TTL 到期
7. 回切 切换失败怎么切回来,回切时原区域的数据是否已经落后
DNS 的 TTL 是一个具体的坑:平时把 TTL 设成 3600 秒,出事时切换要等一小时才全量生效。做 DR 的域名 TTL 应在切换前至少一天调到 60 秒。
以一个命名空间级恢复为例,完整链路是:
# 1. 异地集群上先装好 Velero,并指向同一个备份存储位置
velero backup-location get
# 2. 确认备份存在且状态为 Completed
velero backup get
velero backup describe dev-backup --details
# 3. 恢复到新集群(排除节点、事件等集群相关对象)
velero restore create --from-backup dev-backup \
--exclude-resources nodes,events,events.events.k8s.io \
--namespace-mappings dev:dev
# 4. 盯住恢复过程,重点看 PartiallyFailed
velero restore get
velero restore describe dev-backup-20260918020000
velero restore logs dev-backup-20260918020000
Velero 负责 L1;L2 要看卷数据是否随备份一起走了(见 cluster-backup),L3 要用 etcd 快照单独恢复。
演练是 DR 里唯一不能被省略的环节。 做法:
1. 隔离环境 新建一个独立集群/命名空间,绝不直接在生产的备份上试
2. 定期执行 核心业务每季度一次,一般业务每半年一次
3. 记录耗时 从「决定恢复」到「业务可用」的真实分钟数,而不是命令执行时间
4. 验收标准 由业务方定义:能登录、能下单、数据条数对得上
5. 演练后修正 把演练中踩的坑写回文档,更新 RTO 估算
演练要真的跑过一遍。只在文档里写了步骤、没实际执行过的恢复流程,第一次执行时几乎一定会在某个环节卡住 —— 通常是证书、权限或某个被忘掉的依赖。
灾难现场最忌讳「按清单从上往下恢复」。正确的顺序由依赖关系决定,而不是由重要性决定:
1. 控制面 apiserver / etcd / 控制器可用,否则一切操作都无从谈起
2. 基础依赖 CNI、CSI、DNS、证书签发、镜像仓库可达
3. 身份与密钥 Namespace、ServiceAccount、Secret、RBAC
4. 数据层 数据库、消息队列、存储,先于依赖它的业务
5. 无状态业务 前端、API 层
6. 入口与策略 Ingress/Gateway、NetworkPolicy、准入 Webhook
7. 观测与审计 监控、日志,最后恢复即可
把第 7 步放在最后是有意的:监控很重要,但它在恢复过程中不产生业务价值,却常常因为「先恢复监控才能看到进展」的心理被优先处理,白白消耗宝贵的恢复窗口。恢复期间应直接看组件日志与命令行探测结果。
三个最常见的场景,处置路径差别很大:
场景一:误删命名空间
影响面 单个或几个命名空间
处置 不要尝试手工重建资源,直接从最近一次备份恢复该命名空间
注意 恢复前先确认「误删之后是否已经有新对象写入同名命名空间」,
否则会出现新旧对象混在一起;必要时先恢复到一个临时命名空间做比对
场景二:etcd 损坏或数据被污染
影响面 整个控制面,所有 API 对象
处置 停 apiserver 与 etcd → 用最近一份可用快照恢复 → 校准证书与 sa.key
注意 恢复到哪个时间点需要业务判断:恢复得太早会丢最近的操作,
恢复得太晚可能把污染一起带回来;快照必须先做完整性校验再使用
场景三:区域不可用
影响面 整个集群或大部分节点
处置 在备用区域新建/扩容集群 → 恢复声明与数据 → 调小过的 DNS TTL 生效
注意 数据能否追上取决于复制方式,异步复制必然有 RPO;
切过去之前要确认目标区域有足够的配额与镜像
三种场景的共同点是:真正的恢复动作只占全部工作量的一小部分,剩下的是判断、验证与切换协调。
sa.key/sa.pub 决定 SA token 能否被验证,集群 CA 决定 kubelet 客户端证书是否被接受。跨集群恢复时如果 CA 不同,原节点的证书全部作废,必须重新签发。VolumeSnapshot 通常与原卷在同一存储系统、同一账号下,误删 PV、误删存储池或账号被盗时快照会一起消失。快照适合快速回滚,异地副本才叫备份。backup-strategy),而不是只看任务是否退出码为 0。velero — 集群资源与卷数据的备份恢复工具cluster-backup — 具体要备份哪些东西、各自怎么做backup-strategy — 备份频率、保留、不可变与演练策略etcd — 控制面数据存储与快照操作kubeadm — 集群重建与证书管理volume-snapshot — CSI 卷快照机制karmada — 多集群编排,多活架构的基础组件之一cert-manager — 证书签发与轮换,灾备集群的证书供给