
很多公司做灾备,嘴上说的是“异地双活、两地三中心、跨云容灾”。
听起来都挺猛。
但我经常会想一个问题:
如果真到了“第三次世界大战”级别的灾难,你这套灾备还能不能活?
这里当然不是说真的要发生世界大战,而是故意把灾难等级拉到最大。
机房没了。
一个区域没了。
整个云厂商的某个 Region 没了。
甚至供应商、网络、电力、DNS、证书、身份系统、对象存储一起出问题。
这时候你会发现,很多所谓的“灾备”,其实只是在解决:
服务器坏了怎么办。
而不是:
这个世界突然少了一块怎么办。
这两者,完全不是一个量级。
先说一个特别常见的架构。
比如:
用户
|
DNS
|
┌────▼────┐
│ 云厂商A │
│ Region 1 │
└────┬────┘
|
主数据库
|
对象存储然后我们告诉老板:
“数据库每天备份一次。”
“备份存到了另外一个存储桶。”
“服务器全部做了镜像。”
“出现故障可以快速恢复。”
听起来没毛病。
但如果灾难是:
Region 1 整体不可用。
你会发现一个很尴尬的问题:
备份可能也在那里。
更进一步:
如果你的备份依赖同一个云账号、同一个身份系统、同一个网络、同一个 DNS、同一个 KMS……
那么所谓的“灾备”,可能只是:
把鸡蛋从一个篮子,搬到了这个篮子的另一个隔层。
真正的灾备,第一原则其实特别简单:
灾难发生的时候,恢复系统不能依赖正在被灾难影响的系统。
平时我们做灾备,通常是这么想的:
服务器挂了。
数据库挂了。
磁盘坏了。
机房断电。
这些都属于比较常规的故障。
再往上一级:
单机故障
↓
单 AZ 故障
↓
单 Region 故障
↓
整个云厂商故障
↓
区域性网络故障
↓
多个供应商同时异常
↓
大范围基础设施灾难到了最后,你就不能只考虑:
“我的服务怎么恢复?”
而要考虑:
“我还有什么东西可以用?”
这就是我认为灾备设计最容易被忽略的一点。
很多人理解的跨云是:
阿里云
↓
AWS然后把 Kubernetes、数据库、Redis、对象存储全部复制一份。
这当然比单云强。
但还不够。
因为你还要问:
DNS 在谁家?
域名注册商是谁?
证书在哪里?
镜像仓库在哪里?
Terraform State 在哪里?
密钥在哪里?
CI/CD 在哪里?
监控系统在哪里?
告警平台在哪里?
人员登录权限在哪里?
如果这些全部依赖同一个供应商,那么你的“跨云架构”可能只是:
计算资源跨云了,控制面没有跨云。
真正发生灾难的时候,最先让你崩溃的可能根本不是 Kubernetes。
而是:
你发现没人能登录服务器。
一个生产系统真正要恢复,至少要考虑这条链:
DNS
↓
网络
↓
身份认证
↓
KMS / 密钥
↓
基础设施
↓
Kubernetes / VM
↓
数据库
↓
缓存
↓
对象存储
↓
应用
↓
监控
↓
告警
↓
业务验证这里面任何一个环节挂掉,都可能导致:
系统无法恢复。
例如数据库已经恢复了。
结果应用启动需要读取 Secret。
Secret 在云 A 的 KMS 里。
但是云 A 现在挂了。
于是:
数据库:我活了
应用:我也能启动
Secret:拿不到
应用:那我还是起不来这就是灾备里面特别经典的:
局部恢复成功,整体恢复失败。
所以我一直觉得:
灾备不是备份多少 TB 的数据,而是备份一条完整的“活路”。
假设我们设计一个稍微靠谱一点的架构:
Global DNS
|
┌───────┴───────┐
↓ ↓
Cloud A Cloud B
Region A1 Region B1
| |
Kubernetes Kubernetes
| |
DB Primary DB Replica
| |
└───────┬───────┘
↓
Independent
Backup Storage这里有三个核心思想。
第一:
计算跨区域。
第二:
数据跨区域。
第三:
备份不能和生产系统绑定在一起。
尤其第三个非常重要。
比如:
生产:
Cloud A
灾备:
Cloud B
备份:
独立存储供应商
DNS:
独立 DNS 服务
代码:
Git 多副本
基础设施:
IaC + 离线备份
密钥:
独立恢复方案这样才开始接近真正意义上的:
跨区域、跨云、跨供应商灾备。
这个问题特别现实。
很多公司会说:
“我们的 Kubernetes YAML 都在 Git 里面。”
“换个云重新部署就行。”
理论上可以。
现实通常是:
apiVersion: v1
kind: Service
metadata:
name: api
spec:
type: LoadBalancer你以为:
换一个 Kubernetes 集群,直接 apply。
实际上:
A 云的 LoadBalancer 配置和 B 云完全不同。
存储类不同。
网络插件不同。
Ingress 不同。
IAM 不同。
负载均衡器不同。
磁盘不同。
对象存储 API 也可能不同。
所以真正的跨云灾备,不应该只是:
“代码能部署。”
而应该是:
“代码能在另一朵云上恢复业务。”
这两个标准差得非常远。
例如 Terraform:
module "network" {
source = "./modules/network"
region = var.region
}
module "kubernetes" {
source = "./modules/kubernetes"
cluster_name = var.cluster_name
}
module "database" {
source = "./modules/database"
engine = "postgres"
}真正重要的不是 Terraform 写得多漂亮。
而是:
灾难发生的时候,你还能不能拿到它。
所以我甚至建议:
Git
├── 主仓库
├── 镜像仓库
└── 离线归档
Terraform
├── Git
└── 离线备份
数据库备份
├── 云A
├── 云B
└── 独立存储
恢复文档
├── 在线
└── PDF / 离线介质注意最后那个:
离线介质。
很多人看到这里可能觉得有点“老土”。
但灾难恢复的时候,老土有时候就是最可靠的技术。
服务器没了,可以重新创建。
容器没了,可以重新部署。
数据库数据没了……
那就不是“恢复服务”这么简单了。
所以数据库必须单独设计。
比如:
Primary DB
|
| WAL / Log Replication
↓
Region B Replica
|
↓
Independent Backup
|
↓
Object Storage然后一定要明确三个指标:
RPO:最多允许丢多少数据。
RTO:最多允许多久恢复。
恢复后的数据是否可信。
尤其第三个,我认为经常被忽略。
数据库恢复出来了,不代表业务恢复了。
例如:
订单表
库存表
支付表
物流表数据库都恢复了。
但是订单已经支付,库存却没有扣减。
这时候系统虽然“UP”了。
业务实际上已经“DOWN”了。
所以灾备演练不能只做:
SELECT 1;应该做:
创建订单
↓
扣减库存
↓
支付状态确认
↓
订单查询
↓
数据一致性检查只有业务链路跑通,才叫真正恢复。
灾难发生以后,千万别想着:
“所有东西一起启动。”
这是很容易把自己玩死的。
正确思路应该是分层恢复。
例如:
第一阶段
DNS / 网络 / IAM
↓
第二阶段
数据库 / 对象存储
↓
第三阶段
基础服务
↓
第四阶段
核心业务
↓
第五阶段
非核心业务
↓
第六阶段
监控 / 日志 / 分析为什么?
因为资源有限。
假设灾难发生以后,只剩下 30% 的计算资源。
你应该先让:
登录
订单
支付
库存活下来。
而不是先恢复:
BI
报表
推荐系统
测试环境所以灾备一定要有:
业务优先级。
例如:
services:
payment:
priority: P0
rto: 15m
rpo: 1m
order:
priority: P0
rto: 15m
rpo: 1m
inventory:
priority: P0
rto: 30m
rpo: 5m
report:
priority: P2
rto: 24h
rpo: 24h这样灾难发生的时候,系统不是“全部恢复”。
而是:
先恢复最重要的东西。
这其实也是我理解的灾备成熟度。
很多公司的灾备文档写得非常漂亮。
几十页。
流程图一大堆。
但是问一句:
“你上次真正切过吗?”
现场突然安静。
这就很尴尬。
灾备最大的敌人不是灾难。
而是:
从来没有真正演练过。
你可以每个月做一些小规模实验:
Kill Pod
↓
Kill Node
↓
Disable AZ
↓
切换数据库
↓
切换 Region
↓
切换 Cloud甚至可以做:
DNS 故障
证书故障
镜像仓库故障
KMS 故障
IAM 故障
对象存储故障慢慢把故障半径扩大。
这其实就是混沌工程真正有价值的地方。
不是为了“搞破坏”。
而是提前知道:
如果世界真的塌了,我们还能不能站起来。
如果让我设计一次最高级别的灾备演练,我会直接提出一个有点疯狂的要求:
假设 Cloud A 完全不存在。
不是服务器挂了。
不是 Region 挂了。
而是:
Cloud A = 0然后开始计时。
看看能不能做到:
人员联系
↓
获取灾备凭证
↓
DNS 切换
↓
启动 Cloud B
↓
恢复数据库
↓
恢复核心应用
↓
业务验证
↓
恢复核心流量最后记录:
RTO = 实际恢复时间
RPO = 实际数据丢失量
Success Rate = 核心业务成功率如果跑不通,别觉得丢人。
跑不通才是演练最大的价值。
因为你至少知道:
真正出事的时候,哪里会死人。
这里我也想泼一点冷水。
不是所有公司都值得做:
三朵云、五个 Region、全球多活。
如果一家公司的业务一年利润只有几百万,却花几千万搞全球灾备,我觉得也不一定合理。
灾备最终还是一个成本问题。
你要问:
业务中断 1 小时
损失多少钱?
业务中断 1 天
损失多少钱?
永久丢失数据
损失多少钱?
建设灾备
一年需要多少钱?如果:
灾备成本 > 灾难预期损失那就需要重新算账。
所以真正成熟的灾备不是:
“我要最牛的架构。”
而是:
“我要和业务风险匹配的架构。”
如果真的要把灾难等级拉满,我会至少检查这些:
[ ] 跨 Region
[ ] 跨 Cloud
[ ] 独立 DNS
[ ] 独立身份认证
[ ] 独立密钥恢复方案
[ ] 数据库异地复制
[ ] 独立备份
[ ] 离线备份
[ ] IaC
[ ] 镜像多仓库
[ ] 配置多副本
[ ] 核心业务分级
[ ] 明确 RTO
[ ] 明确 RPO
[ ] 自动化恢复
[ ] 手工恢复预案
[ ] 灾备账号
[ ] 灾备权限
[ ] 联系人清单
[ ] 应急通讯方案
[ ] 定期演练
[ ] 真正做过 Cloud A → Cloud B 切换最后这一项,我特别强调。
“做过切换”比“写过方案”重要一万倍。
做运维久了以后,我越来越觉得:
灾备不是为了预测灾难,而是为了接受灾难一定会发生。
我们没办法知道下一次事故到底是什么。
可能是数据库。
可能是机房。
可能是网络。
可能是供应商。
也可能是一个凌晨三点误删生产数据的工程师。
所以真正优秀的灾备架构,核心并不是:
“我们准备了多少台备用服务器。”
而是:
“当我们失去最重要的东西之后,还剩下什么?”
失去一个 Pod,还有 Node。
失去一个 AZ,还有 Region。
失去一个 Region,还有另一个 Region。
失去一朵云,还有另一朵云。
失去在线系统,还有离线备份。
甚至当自动化平台、DNS、监控、权限系统全部失效的时候,还有一份人能看懂、能执行的恢复手册。
这才是我理解的灾备底线。
因为真正的灾难恢复,最后拼的可能不是技术有多先进。
而是:
系统没了以后,你有没有第二条路。
如果连第二条路都没有,那么所谓的高可用,很多时候只是——
还没轮到你出故障而已。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。