Kubernetes灾难恢复实战:Velero与ETCD备份方案
1. 项目概述:Kubernetes灾难恢复的核心挑战
在云原生架构中,Kubernetes集群的灾难恢复能力直接关系到业务连续性。去年我们生产环境就遭遇过ETCD数据损坏导致整个集群不可用的严重事故,当时由于缺乏有效的备份方案,最终不得不耗时8小时重建集群。这次教训让我深刻认识到:完善的备份还原体系不是可选项,而是生产环境的生命线。
Velero作为CNCF孵化的开源工具,专为解决Kubernetes资源备份难题而生。它不仅能捕获集群状态(包括Deployment、Service等API对象),还能通过插件机制备份持久卷数据。而ETCD作为Kubernetes的大脑,其数据完整性更是灾备的重中之重。本文将分享如何构建从应用层到控制平面的全方位防护体系。
2. 核心组件解析与选型考量
2.1 Velero架构深度剖析
Velero的备份流程涉及三个关键组件:
- 服务端控制器:运行在集群内的Pod,负责协调备份/恢复操作
- CLI工具:本地执行的命令行界面,通过kubeconfig与集群交互
- 对象存储后端:支持AWS S3、Azure Blob等云存储,也可用MinIO自建
我们选择Velero而非传统方案(如手动kubectl导出)的主要原因:
- 原子性操作:自动处理资源依赖关系,避免手动备份时常见的对象遗漏
- CRD支持:完美备份自定义资源,这是很多DIY方案无法实现的
- 增量备份:通过--snapshot-volumes参数可只备份变更的持久卷数据
2.2 ETCD备份的特殊性
虽然Velero能备份工作负载,但控制平面组件(如kube-apiserver)的状态仍依赖ETCD。ETCD备份有两大难点:
- 数据一致性:直接拷贝etcd数据目录会导致损坏,必须使用etcdctl snapshot save
- 证书问题:恢复时若证书过期会导致集群"脑裂",需要配合cert-manager处理
3. 实战部署与配置指南
3.1 Velero安装与初始化
以AWS S3为例的安装步骤(其他存储后端类似):
# 下载最新CLI工具 wget https://github.com/vmware-tanzu/velero/releases/download/v1.11.0/velero-v1.11.0-linux-amd64.tar.gz tar -xvf velero-v1.11.0-linux-amd64.tar.gz sudo mv velero /usr/local/bin/ # 创建S3存储桶 aws s3api create-bucket --bucket my-velero-backups --region us-west-2 # 安装服务端 velero install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.6.1 \ --bucket my-velero-backups \ --backup-location-config region=us-west-2 \ --snapshot-location-config region=us-west-2 \ --use-restic关键参数说明:
--use-restic:启用文件系统级持久卷备份(替代已弃用的Restic)--default-volumes-to-restic:自动备份所有Pod挂载的卷
3.2 ETCD定期备份方案
对于使用kubeadm部署的集群,建议通过CronJob实现自动化备份:
apiVersion: batch/v1 kind: CronJob metadata: name: etcd-backup namespace: kube-system spec: schedule: "0 */6 * * *" jobTemplate: spec: template: spec: containers: - name: etcdctl image: bitnami/etcd:3.5.9 env: - name: ETCDCTL_ENDPOINTS value: "https://127.0.0.1:2379" - name: ETCDCTL_CACERT value: "/etc/kubernetes/pki/etcd/ca.crt" - name: ETCDCTL_CERT value: "/etc/kubernetes/pki/etcd/server.crt" - name: ETCDCTL_KEY value: "/etc/kubernetes/pki/etcd/server.key" command: - /bin/sh - -c - | etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db && aws s3 cp /backup/*.db s3://my-etcd-backups/ volumeMounts: - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs readOnly: true - mountPath: /backup name: backup volumes: - name: etcd-certs hostPath: path: /etc/kubernetes/pki/etcd - name: backup emptyDir: {} restartPolicy: OnFailure hostNetwork: true nodeSelector: node-role.kubernetes.io/control-plane: "" tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule重要提示:备份文件必须包含时间戳,避免覆盖历史备份。同时建议启用S3版本控制功能。
4. 灾难恢复全流程演练
4.1 场景一:应用级故障恢复
当某个命名空间被误删除时,使用Velero恢复的完整流程:
# 查看可用备份 velero backup get # 执行恢复(可选择特定资源) velero restore create ns-restore \ --from-backup my-backup \ --include-namespaces critical-app \ --include-resources deployments,services,configmaps # 监控恢复进度 velero restore describe ns-restore常见问题处理:
- StorageClass冲突:若目标集群StorageClass不同,需添加--storage-class-mappings参数
- 节点亲和性失效:恢复后检查Pod分布,可能需要调整节点标签
4.2 场景二:全集群ETCD恢复
当控制平面完全崩溃时,按以下步骤重建:
# 在所有控制节点停止kube-apiserver sudo systemctl stop kube-apiserver # 从S3下载最新快照 aws s3 cp s3://my-etcd-backups/etcd-snapshot-20230801-120000.db . # 在每个控制节点执行恢复 sudo etcdctl snapshot restore etcd-snapshot-20230801-120000.db \ --data-dir /var/lib/etcd-restore \ --initial-cluster controller1=https://10.0.1.101:2380 \ --initial-advertise-peer-urls https://10.0.1.101:2380 \ --name controller1 # 修改etcd.service配置指向新数据目录 sudo sed -i 's|/var/lib/etcd|/var/lib/etcd-restore|' /etc/systemd/system/etcd.service # 重启服务 sudo systemctl daemon-reload sudo systemctl start etcd sudo systemctl start kube-apiserver关键检查点:
- 证书有效期:确保etcd证书在恢复后仍然有效
- 节点IP变更:若集群IP地址变化,需调整--initial-cluster参数
- 数据一致性:恢复后运行etcdctl endpoint status验证各成员状态
5. 高级配置与优化技巧
5.1 备份策略精细化控制
通过Schedule资源实现智能备份策略:
apiVersion: velero.io/v1 kind: Schedule metadata: name: daily-backup namespace: velero spec: schedule: "0 2 * * *" template: includedNamespaces: - '*' excludedNamespaces: - kube-system - velero ttl: 720h storageLocation: default volumeSnapshotLocations: - aws-default hooks: resources: - name: pre-backup-hook includedNamespaces: - '*' pre: - exec: container: app command: - /bin/sh - -c - "flock -n /tmp/db.lock mysqldump -u root -p$DB_PASSWORD --all-databases > /var/lib/mysql/backup.sql" onError: Fail timeout: 5m这个配置实现了:
- 每日凌晨2点全量备份(除系统命名空间)
- 备份前自动执行数据库dump
- 自动清理30天前的旧备份
5.2 ETCD备份验证方案
定期验证备份有效性的CronJob示例:
#!/bin/bash # 下载最新备份 BACKUP_FILE=$(aws s3 ls s3://my-etcd-backups/ | sort | tail -n 1 | awk '{print $4}') aws s3 cp s3://my-etcd-backups/$BACKUP_FILE /tmp/ # 启动临时etcd集群 docker run -d \ -p 12379:2379 \ -p 12380:2380 \ -v /tmp:/data \ --name etcd-verify \ bitnami/etcd:3.5.9 \ etcd --data-dir /data --snapshot-count=0 # 验证数据可读性 if etcdctl --endpoints=http://localhost:12379 get / --prefix; then echo "Backup verification SUCCESS" else echo "Backup verification FAILED" exit 1 fi # 清理 docker stop etcd-verify && docker rm etcd-verify6. 生产环境经验总结
6.1 Velero性能优化参数
在大规模集群中(500+节点),这些配置可显著提升备份效率:
velero install \ ... --restic-timeout 4h \ --restic-node-selector "backup=enabled" \ --default-volumes-to-fs-backup=false \ --features=EnableCSI关键调整项:
- 专用备份节点:通过nodeSelector将备份Pod调度到特定节点
- CSI插件:对CSI卷使用原生快照功能(需存储供应商支持)
- 并行度控制:调整--client-qps和--client-burst参数应对API限流
6.2 ETCD恢复的黄金法则
根据多次真实故障演练,总结出三条铁律:
3-2-1备份原则:
- 至少保留3份备份
- 存储在2种不同介质
- 其中1份异地保存
变更立即备份:
- 集群证书更新后
- 节点扩缩容操作前
- Kubernetes版本升级前后
定期恢复演练:
- 每季度执行全集群灾难恢复演练
- 验证备份的可用性而不仅是存在性
7. 典型故障排查手册
7.1 Velero常见错误代码
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| BackupStorageLocation不可用 | 凭证失效/网络中断 | 检查velero日志中的AWS错误详情 |
| Volume备份卡住 | Pod有大量小文件 | 增加restic-timeout或排除缓存目录 |
| 恢复后PodPending | StorageClass不匹配 | 使用--storage-class-mappings参数 |
7.2 ETCD恢复异常处理
案例:恢复后apiserver无法连接etcd
Error while dialing dial tcp 10.0.1.101:2379: connect: connection refused排查步骤:
- 检查etcd服务状态:
sudo systemctl status etcd - 查看etcd日志:
journalctl -u etcd -n 100 - 验证证书有效性:
openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -noout -dates - 检查监听地址:
ss -tulnp | grep 2379
根本原因往往是:
- 证书过期(需更新所有相关证书)
- 数据目录权限错误(chown -R etcd:etcd /var/lib/etcd)
- 网络配置变更(检查防火墙规则)
8. 多云环境下的备份策略
对于跨云部署的集群,建议采用分级备份方案:
本地快速恢复层:
- Velero + 集群内MinIO
- 保留最近24小时备份
- RTO(恢复时间目标)<30分钟
云端持久层:
- 每日同步到AWS S3 IA存储
- 保留30天备份
- 启用对象锁定防篡改
异地灾备层:
- 每周备份到Azure Archive Storage
- 保留1年以上
- 需要时人工激活
配置示例(使用velero的多个备份位置):
# 添加Azure备份位置 velero backup-location create azure-backup \ --provider azure \ --bucket velero-archive \ --config resourceGroup=my-rg,storageAccount=mystorage # 创建迁移任务 velero create schedule cross-cloud-sync \ --schedule="@weekly" \ --include-cluster-resources=true \ --storage-location=default \ --snapshot-location=aws-default \ --ttl=168h \ --copy-to=azure-backup9. 监控与告警体系建设
9.1 Prometheus监控指标
关键监控指标配置:
- job_name: 'velero' metrics_path: '/metrics' static_configs: - targets: ['velero-server:8085'] - job_name: 'etcd' static_configs: - targets: ['10.0.1.101:2379','10.0.1.102:2379'] metrics_path: '/metrics' scheme: 'https' tls_config: ca_file: /etc/prometheus/etcd-ca.crt cert_file: /etc/prometheus/etcd-client.crt key_file: /etc/prometheus/etcd-client.key insecure_skip_verify: false9.2 必须配置的告警规则
groups: - name: backup-alerts rules: - alert: VeleroBackupFailed expr: velero_backup_failure_total{job="velero"} > 0 for: 5m labels: severity: critical annotations: summary: "Velero backup failed ({{ $labels.name }})" description: "Backup {{ $labels.name }} has failed {{ $value }} times" - alert: EtcdBackupMissed expr: time() - etcd_last_backup_timestamp_seconds > 86400 labels: severity: warning annotations: summary: "ETCD backup overdue" description: "No successful backup in last 24 hours"10. 证书管理的特别注意事项
在ETCD恢复场景中,证书问题是最常见的陷阱。建议采用以下方案:
证书轮换策略:
- 使用cert-manager自动管理证书
- 设置比备份周期更长的有效期(如1年)
恢复时的证书处理:
# 检查证书有效期 openssl x509 -in /etc/kubernetes/pki/apiserver-etcd-client.crt -noout -dates # 临时解决方案(测试环境): kubeadm certs renew all --config /etc/kubernetes/kubeadm-config.yaml systemctl restart kubelet- 长期方案:
- 将etcd证书与kubeadm管理的证书分离
- 使用Hashicorp Vault等工具集中管理证书
- 在备份元数据中记录证书过期时间
对于大规模集群,我推荐使用以下证书目录结构:
/etc/kubernetes/pki/ ├── etcd/ │ ├── ca.crt │ ├── healthcheck-client.crt │ └── peer.crt └── kubeadm/ ├── apiserver.crt └── front-proxy-ca.crt这种隔离设计可以避免恢复时证书的交叉影响。