概述
Kubernetes 集群的灾难恢复是运维中最容易被忽视的领域——直到灾难发生。etcd 损坏导致整个集群不可用、PV 数据误删无法恢复、集群升级失败无法回滚……这些场景没有备份就是灾难,有备份就是一次常规恢复。
详细梳理 K8s 灾难恢复的三个层次:etcd 备份恢复(集群元数据)、Velero 备份(K8s 资源)、PV 数据备份(持久化数据),以及跨集群恢复和恢复演练的实践。
本文基于 Kubernetes v1.30 和 Velero v1.14。参考 Kubernetes 灾难恢复文档
灾备基础概念
RTO 与 RPO
| 指标 | 全称 | 含义 | 目标 |
|---|---|---|---|
| RTO | Recovery Time Objective | 恢复时间目标(多快恢复) | < 30min |
| RPO | Recovery Point Objective | 数据丢失目标(丢多少数据) | < 5min |
故障发生 恢复完成
|◄────── RTO ──────────►|
| |
|◄── RPO ──►| |
| | |
最后一次备份 故障点 恢复点
备份层次
| 层次 | 备份对象 | 工具 | RPO | 恢复粒度 |
|---|---|---|---|---|
| etcd | 集群所有元数据 | etcdctl snapshot | 分钟级 | 整个集群 |
| K8s 资源 | Deployment/Service/ConfigMap 等 | Velero | 分钟级 | 命名空间/资源 |
| PV 数据 | 持久化卷数据 | Velero/Restic/Kasten | 小时级 | 单个 PV |
| 应用数据 | 数据库/对象存储 | 应用自身机制 | 秒级 | 应用级 |
灾备分类
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 备份恢复 | 定期备份,故障时恢复 | 通用 |
| 活跃-备用 | 备集群 standby,故障切换 | 核心业务 |
| 活跃-活跃 | 多集群同时服务,故障切流 | 全球业务 |
| 混沌演练 | 模拟故障验证恢复能力 | 灾备成熟度 |
etcd 备份与恢复
为什么 etcd 备份最重要
etcd 是 K8s 的"大脑"——所有集群状态(Pod、Service、ConfigMap、Secret、Deployment 等)都存储在 etcd 中。etcd 损坏等于整个集群的数据丢失。没有 etcd 备份,其他备份都无意义。
etcd 备份
# 方式一:使用 etcdctl 快照
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 验证备份
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot-20260710-120000.db \
--write-out=table
# 输出:
# +---------+---------+-----------+-----------+-----------+
# | HASH |REVISION |TOTAL KEYS |TOTAL BYTES|TOTAL SIZE |
# +---------+---------+-----------+-----------+-----------+
# | 3a2b1c | 123456 | 5678 | 89 MB | 120 MB |
# +---------+---------+-----------+-----------+-----------+
自动化 etcd 备份
#!/bin/bash
# /usr/local/bin/etcd-backup.sh
BACKUP_DIR="/backup/etcd"
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/etcd-snapshot-${DATE}.db"
RETENTION_DAYS=7
mkdir -p "${BACKUP_DIR}"
# 创建快照
ETCDCTL_API=3 etcdctl snapshot save "${BACKUP_FILE}" \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 验证
if ETCDCTL_API=3 etcdctl snapshot status "${BACKUP_FILE}" >/dev/null 2>&1; then
echo "$(date): Backup successful: ${BACKUP_FILE}"
# 压缩
gzip "${BACKUP_FILE}"
# 清理旧备份
find "${BACKUP_DIR}" -name "etcd-snapshot-*.db.gz" -mtime +${RETENTION_DAYS} -delete
echo "$(date): Old backups cleaned (>${RETENTION_DAYS} days)"
else
echo "$(date): Backup FAILED: ${BACKUP_FILE}"
rm -f "${BACKUP_FILE}"
exit 1
fi
# Cron 定时任务
# crontab -e
# 每30分钟备份一次
*/30 * * * * /usr/local/bin/etcd-backup.sh >> /var/log/etcd-backup.log 2>&1
etcd 备份到对象存储
#!/bin/bash
# 备份到 S3
BACKUP_FILE="/tmp/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db"
ETCDCTL_API=3 etcdctl snapshot save "${BACKUP_FILE}" \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
gzip "${BACKUP_FILE}"
# 上传到 S3
aws s3 cp "${BACKUP_FILE}.gz" \
"s3://k8s-etcd-backup/$(hostname)/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db.gz" \
--sse AES256
# 清理本地文件
rm -f "${BACKUP_FILE}.gz"
# 清理 S3 旧备份(保留30天)
aws s3 ls s3://k8s-etcd-backup/$(hostname)/ | \
awk '{print $4}' | \
while read f; do
DATE=$(echo "$f" | grep -oP '\d{8}-\d{6}')
if [ $(date -d "${DATE:0:4}-${DATE:4:2}-${DATE:6:2}" +%s 2>/dev/null) -lt $(date -d "30 days ago" +%s) ]; then
aws s3 rm "s3://k8s-etcd-backup/$(hostname)/$f"
fi
done
etcd 恢复
单节点恢复
# 1. 停止 etcd
systemctl stop etcd
# 2. 清空旧数据
rm -rf /var/lib/etcd
# 3. 恢复快照
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot-20260710-120000.db \
--data-dir=/var/lib/etcd
# 4. 修改权限
chown -R etcd:etcd /var/lib/etcd
# 5. 启动 etcd
systemctl start etcd
# 6. 验证
ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
多节点集群恢复
# 在每个 etcd 节点上执行:
# 节点 1
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd \
--name=etcd-node-1 \
--initial-cluster=etcd-node-1=https://10.0.1.1:2380,etcd-node-2=https://10.0.1.2:2380,etcd-node-3=https://10.0.1.3:2380 \
--initial-cluster-token=new-cluster \
--initial-advertise-peer-urls=https://10.0.1.1:2380
# 节点 2
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd \
--name=etcd-node-2 \
--initial-cluster=etcd-node-1=https://10.0.1.1:2380,etcd-node-2=https://10.0.1.2:2380,etcd-node-3=https://10.0.1.3:2380 \
--initial-cluster-token=new-cluster \
--initial-advertise-peer-urls=https://10.0.1.2:2380
# 节点 3
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd \
--name=etcd-node-3 \
--initial-cluster=etcd-node-1=https://10.0.1.1:2380,etcd-node-2=https://10.0.1.2:2380,etcd-node-3=https://10.0.1.3:2380 \
--initial-cluster-token=new-cluster \
--initial-advertise-peer-urls=https://10.0.1.3:2380
# 在所有节点上启动 etcd
systemctl start etcd
恢复后验证
# 检查 etcd 集群健康
ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://10.0.1.1:2379,https://10.0.1.2:2379,https://10.0.1.3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 检查集群状态
ETCDCTL_API=3 etcdctl endpoint status \
--endpoints=https://10.0.1.1:2379,https://10.0.1.2:2379,https://10.0.1.3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
--write-out=table
# 检查 K8s 组件
kubectl get nodes
kubectl get pods -A
kubectl get cs
etcd 备份注意事项
| 注意事项 | 说明 |
|---|---|
| 备份频率 | 生产至少每 30 分钟一次 |
| 备份验证 | 每次备份后验证快照完整性 |
| 异地备份 | 备份文件要存到异地(S3/OSS) |
| 保留策略 | 至少保留 7 天的备份 |
| 加密 | 备份文件包含 Secret,必须加密存储 |
| 恢复测试 | 定期在测试环境验证恢复 |
Velero 备份方案
Velero 简介
Velero(前身为 Heptio Ark)是 VMware 开源的 K8s 备份工具,支持:
- K8s 资源备份和恢复
- PV 数据备份(通过 Restic 或快照)
- 命名空间迁移
- 定时备份
- 跨集群恢复
Velero vs etcd 备份
| 特性 | etcd 备份 | Velero |
|---|---|---|
| 备份粒度 | 整个集群 | 命名空间/资源 |
| 恢复粒度 | 整个集群 | 命名空间/资源 |
| PV 数据 | 不备份 | 支持 |
| 跨集群恢复 | 不支持 | 支持 |
| 定时备份 | 需自己实现 | 原生支持 |
| 应用层一致性 | 无 | 无(需应用配合) |
好的实践:etcd 备份和 Velero 备份同时使用。etcd 备份是最后的兜底,Velero 用于细粒度恢复和迁移。
安装 Velero
# 下载
wget https://github.com/vmware-tanzu/velero/releases/download/v1.14.0/velero-v1.14.0-linux-amd64.tar.gz
tar xzf velero-v1.14.0-linux-amd64.tar.gz
mv velero-v1.14.0-linux-amd64/velero /usr/local/bin/
# 创建 S3 凭证
cat > /tmp/credentials-velero << 'EOF'
[default]
aws_access_key_id=YOUR_ACCESS_KEY
aws_secret_access_key=YOUR_SECRET_KEY
EOF
# 安装
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.10.0 \
--bucket k8s-velero-backup \
--backup-location-config region=us-east-1 \
--snapshot-location-config region=us-east-1 \
--secret-file /tmp/credentials-velero \
--use-restic \
--default-volumes-to-restic \
--restic-pod-cpu-request 100m \
--restic-pod-cpu-limit 1000m \
--restic-pod-mem-request 128Mi \
--restic-pod-mem-limit 512Mi
# 验证
kubectl get pods -n velero
velero version
创建备份
# 备份命名空间
velero backup create myapp-backup --include-namespaces production
# 备份指定资源
velero backup create deployments-backup \
--include-namespaces production \
--include-resources deployments,services
# 带标签的备份
velero backup create labeled-backup \
--selector app=myapp
# 排除命名空间
velero backup create cluster-backup \
--exclude-namespaces kube-system,velero
# 从定时备份触发
velero backup create manual-from-schedule daily-backup
# 带选项的备份(YAML 方式)
apiVersion: velero.io/v1
kind: Backup
metadata:
name: production-backup
namespace: velero
spec:
includedNamespaces:
- production
includedResources:
- deployments
- services
- configmaps
- secrets
- persistentvolumeclaims
- ingresses
excludedResources:
- pods
- events
labelSelector:
matchLabels:
backup: "true"
storageLocation: default
ttl: 720h0m0s # 保留30天
includeClusterResources: false
snapshotVolumes: true # 快照 PV
volumeSnapshotLocations:
- default
定时备份
# 每天凌晨2点备份 production 命名空间
velero schedule create daily-production-backup \
--schedule="0 2 * * *" \
--include-namespaces production \
--ttl 168h0m0s # 保留7天
# 每30分钟备份所有命名空间
velero schedule create frequent-backup \
--schedule="*/30 * * * *" \
--ttl 2h0m0s # 保留2小时
# 每周完整备份
velero schedule create weekly-full-backup \
--schedule="0 3 * * 0" \
--ttl 720h0m0s # 保留30天
# YAML 方式
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: daily-production-backup
namespace: velero
spec:
schedule: "0 2 * * *"
template:
includedNamespaces:
- production
ttl: 168h0m0s
snapshotVolumes: true
查看备份
# 列出所有备份
velero backup get
# 查看备份详情
velero backup describe daily-production-backup --details
# 查看备份内容
velero backup describe myapp-backup --details | grep -A 20 "Included Resources"
恢复
# 从备份恢复
velero restore create --from-backup myapp-backup
# 恢复到不同命名空间
velero restore create --from-backup myapp-backup \
--namespace-mappings production:production-restored
# 只恢复指定资源
velero restore create --from-backup myapp-backup \
--include-resources deployments,services
# 恢复时排除资源
velero restore create --from-backup myapp-backup \
--exclude-resources secrets,persistentvolumeclaims
# 恢复指定标签
velero restore create --from-backup myapp-backup \
--selector app=critical
# YAML 方式
apiVersion: velero.io/v1
kind: Restore
metadata:
name: myapp-restore
namespace: velero
spec:
backupName: myapp-backup
includedNamespaces:
- production
namespaceMapping:
production: production-restored
restorePVs: true
PV 数据备份
方式一:快照备份
# StorageClass 支持快照时
apiVersion: velero.io/v1
kind: Backup
metadata:
name: with-snapshots
namespace: velero
spec:
includedNamespaces:
- production
snapshotVolumes: true # 使用存储层快照
volumeSnapshotLocations:
- default
方式二:Restic 文件级备份
# 不支持快照的存储(如 NFS)
apiVersion: velero.io/v1
kind: Backup
metadata:
name: with-restic
namespace: velero
spec:
includedNamespaces:
- production
defaultVolumesToRestic: true # 使用 Restic 文件级备份
| 方式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 快照 | 快、一致性高 | 需要 StorageClass 支持 | 云盘(EBS/GCP PD) |
| Restic | 通用、跨存储 | 慢、需 fsfreeze | NFS/本地存储 |
Restic 备份注解
# 在 Pod 中指定需要 Restic 备份的卷
metadata:
annotations:
backup.velero.io/backup-volumes: data,config
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc
- name: config
configMap:
name: app-config
跨集群恢复
场景一:集群迁移
# 在源集群创建备份
velero backup create migration-backup --include-namespaces production
# 等待备份完成
velero backup get migration-backup
# 在目标集群配置相同的备份存储
velero install \
--provider aws \
--bucket k8s-velero-backup \
--backup-location-config region=us-east-1 \
--secret-file /tmp/credentials-velero
# 在目标集群恢复
velero restore create migration-restore --from-backup migration-backup
场景二:灾备集群
源集群(Active) 灾备集群(Standby)
│ │
▼ ▼
Velero 定时备份 ──→ S3 ←── Velero 同步恢复
│ │
▼ ▼
应用数据 ──→ DB 复制 ──→ 灾备集群 DB
# 灾备集群配置定时同步恢复
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: dr-sync
namespace: velero
spec:
schedule: "*/30 * * * *"
template:
includedNamespaces:
- production
ttl: 24h
场景三:命名空间克隆
# 备份源命名空间
velero backup create source-ns-backup --include-namespaces production
# 恢复到新命名空间
velero restore create cloned-ns \
--from-backup source-ns-backup \
--namespace-mappings production:production-clone
恢复演练
演练流程
1. 在测试环境模拟故障
2. 执行恢复流程
3. 验证恢复结果
4. 记录恢复时间
5. 评估 RTO/RPO
6. 完善恢复流程
etcd 恢复演练
#!/bin/bash
# etcd-restore-drill.sh
echo "===== etcd 恢复演练 ====="
# 1. 记录开始时间
START_TIME=$(date +%s)
echo "开始时间: $(date)"
# 2. 停止 etcd(模拟故障)
echo "停止 etcd..."
systemctl stop etcd
# 3. 备份当前数据(以防万一)
mv /var/lib/etcd /var/lib/etcd.drill-backup
# 4. 恢复
echo "恢复 etcd..."
LATEST_BACKUP=$(ls -t /backup/etcd/etcd-snapshot-*.db.gz | head -1)
gunzip -c "${LATEST_BACKUP}" > /tmp/etcd-restore.db
ETCDCTL_API=3 etcdctl snapshot restore /tmp/etcd-restore.db \
--data-dir=/var/lib/etcd
chown -R etcd:etcd /var/lib/etcd
# 5. 启动
echo "启动 etcd..."
systemctl start etcd
# 6. 验证
sleep 5
echo "验证集群状态..."
kubectl get nodes
kubectl get pods -A | head -20
# 7. 记录结束时间
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "恢复时间: ${DURATION} 秒"
echo "RTO 评估: $([ ${DURATION} -lt 1800 ] && echo '达标 (<30min)' || echo '未达标 (>30min)')"
# 8. 清理
rm /tmp/etcd-restore.db
echo "===== 演练完成 ====="
Velero 恢复演练
#!/bin/bash
# velero-restore-drill.sh
echo "===== Velero 恢复演练 ====="
START_TIME=$(date +%s)
echo "开始时间: $(date)"
# 1. 删除测试命名空间(模拟故障)
echo "删除测试命名空间..."
kubectl delete namespace drill-test --ignore-not-found
# 等待命名空间删除完成
kubectl wait --for=delete namespace/drill-test --timeout=60s 2>/dev/null || true
# 2. 获取最新备份
LATEST_BACKUP=$(velero backup get -o json | jq -r '.items | sort_by(.metadata.creationTimestamp) | last | .metadata.name')
echo "使用备份: ${LATEST_BACKUP}"
# 3. 恢复
echo "执行恢复..."
velero restore create drill-restore --from-backup "${LATEST_BACKUP}"
# 4. 等待恢复完成
echo "等待恢复完成..."
while true; do
PHASE=$(velero restore get drill-restore -o jsonpath='{.status.phase}')
if [ "${PHASE}" = "Completed" ] || [ "${PHASE}" = "PartiallyFailed" ] || [ "${PHASE}" = "Failed" ]; then
break
fi
sleep 5
done
echo "恢复阶段: ${PHASE}"
# 5. 验证
echo "验证恢复结果..."
kubectl get pods -n drill-test
kubectl get svc -n drill-test
# 6. 记录时间
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "恢复时间: ${DURATION} 秒"
# 7. 检查数据一致性
echo "检查数据完整性..."
kubectl exec -n drill-test deployment/myapp -- \
curl -s http://localhost:8080/health || echo "应用健康检查失败"
echo "===== 演练完成 ====="
演练检查清单
| 检查项 | 达标标准 | 实际结果 |
|---|---|---|
| etcd 恢复时间 | < 15min | _____ |
| Velero 恢复时间 | < 30min | _____ |
| 应用启动时间 | < 10min | _____ |
| 数据完整性 | 无丢失 | _____ |
| RTO | < 30min | _____ |
| RPO | < 30min | _____ |
| 监控恢复 | 告警正常 | _____ |
| 日志恢复 | 日志正常 | _____ |
灾备架构设计
架构一:同区域灾备
┌─────────────────┐
│ Route53 / GSLB │
└──────┬──────────┘
│
┌────────────┴────────────┐
▼ ▼
┌────────────────┐ ┌────────────────┐
│ 主集群 │ │ 备集群 │
│ (Active) │ │ (Standby) │
│ AZ-a │ │ AZ-b │
└────────┬───────┘ └───────┬────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ RDS Primary │ ────→ │ RDS Standby │
└────────────────┘ └────────────────┘
- RTO: 5-15min
- RPO: < 5min
- 成本: 中等
架构二:跨区域灾备
┌─────────────────┐
│ Route53 / GSLB │
└──────┬──────────┘
│
┌────────────┴────────────┐
▼ ▼
┌────────────────┐ ┌────────────────┐
│ 北京集群 │ │ 上海集群 │
│ (Active) │ │ (Standby) │
│ Region-A │ │ Region-B │
└────────┬───────┘ └───────┬────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ RDS Primary │ ─同步→ │ RDS ReadReplica│
└────────────────┘ └────────────────┘
- RTO: 15-30min
- RPO: < 1min
- 成本: 高
架构三:多集群活跃
┌─────────────────┐
│ 全局负载均衡 │
└──┬──────────┬────┘
│ │
┌────────┘ └────────┐
▼ ▼
┌────────────────┐ ┌────────────────┐
│ 集群 A │ │ 集群 B │
│ (Active) │ │ (Active) │
└────────┬───────┘ └───────┬────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ RDS A (Primary)│◄─双向同步─►│ RDS B (Primary)│
└────────────────┘ └────────────────┘
- RTO: 0min(流量切换)
- RPO: 0min(实时同步)
- 成本: 极高
备份策略矩阵
| 数据类型 | 备份方式 | 频率 | 保留 | RPO |
|---|---|---|---|---|
| etcd | etcdctl snapshot | 30min | 7天 | 30min |
| K8s 资源 | Velero | 每日 | 30天 | 24h |
| 数据库 | 数据库备份 | 1h | 7天 | 1h |
| 数据库日志 | WAL/binlog | 实时 | 3天 | 秒级 |
| 对象存储 | 跨区域复制 | 实时 | - | 秒级 |
| 配置 | Git 仓库 | 每次提交 | 永久 | 0 |
生产灾备清单
备份配置
- etcd 每 30 分钟自动备份
- etcd 备份上传到异地存储
- Velero 定时备份已配置
- PV 数据备份策略已配置
- 数据库备份策略已配置
- 备份保留策略合理
- 备份存储已加密
恢复能力
- etcd 恢复流程文档化
- Velero 恢复流程文档化
- 数据库恢复流程文档化
- 跨集群恢复已验证
- 恢复脚本已自动化
- 恢复演练每季度执行
监控告警
- 备份失败有告警
- 备份空间不足有告警
- 恢复失败有告警
- RPO 超标有告警
- 备份完整性定期验证
文档与流程
- 灾备架构文档
- 恢复操作手册(Runbook)
- 联系人列表(含供应商)
- 演练记录和改进跟踪
- RTO/RPO 目标定义
总结
K8s 灾难恢复的核心要点:
- etcd 备份是底线:没有 etcd 备份就没有一切。每 30 分钟自动备份,上传到异地存储,定期验证可恢复性。
- Velero 做细粒度恢复:etcd 恢复是全量的,Velero 支持命名空间和资源级别的恢复,两者互补。
- PV 数据单独备份:etcd 只存储 PV 的元数据,实际数据需要通过 Velero 快照/Restic 或应用层备份。
- 数据库用自身机制:数据库的备份不能依赖 PV 快照,要用数据库自身的备份机制(WAL/binlog/快照),才能保证一致性。
- 恢复演练不可少:没有演练过的备份等于没有备份。每季度至少做一次完整恢复演练,验证 RTO/RPO。
- 分层设计 RTO/RPO:不同业务有不同的恢复要求。核心业务 RTO < 5min,非核心可以 < 4h。不要一刀切。
- 备份要监控:备份失败必须有告警。很多团队备份在悄悄失败,直到需要恢复时才发现备份不可用。
- 文档要到位:恢复操作必须在 Runbook 中详细记录。灾难发生时,操作人员可能不是平时维护系统的人。
灾备的本质是用成本换确定性。备份和演练都需要投入,但这些投入在灾难发生时会回报百倍。记住一个原则:如果没测过恢复,就等于没有备份。
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- Kubernetes etcd Backup — Kubernetes 官方,参考了Kubernetes etcd Backup相关内容
- Kubernetes 灾难恢复文档 — Kubernetes 官方,参考了Kubernetes 灾难恢复文档相关内容
- Velero Documentation — Velero 项目,参考了Velero Documentation相关内容