Kubernetes灾难恢复实战:Velero与ETCD备份方案

📅 2026/7/14 17:24:29 👁️ 阅读次数 📝 编程学习
Kubernetes灾难恢复实战:Velero与ETCD备份方案

1. 项目概述:Kubernetes灾难恢复的核心挑战

在云原生架构中,Kubernetes集群的灾难恢复能力直接关系到业务连续性。去年我们生产环境就遭遇过ETCD数据损坏导致整个集群不可用的严重事故,当时由于缺乏有效的备份方案,最终不得不耗时8小时重建集群。这次教训让我深刻认识到:完善的备份还原体系不是可选项,而是生产环境的生命线。

Velero作为CNCF孵化的开源工具,专为解决Kubernetes资源备份难题而生。它不仅能捕获集群状态(包括Deployment、Service等API对象),还能通过插件机制备份持久卷数据。而ETCD作为Kubernetes的大脑,其数据完整性更是灾备的重中之重。本文将分享如何构建从应用层到控制平面的全方位防护体系。

2. 核心组件解析与选型考量

2.1 Velero架构深度剖析

Velero的备份流程涉及三个关键组件:

  1. 服务端控制器:运行在集群内的Pod,负责协调备份/恢复操作
  2. CLI工具:本地执行的命令行界面,通过kubeconfig与集群交互
  3. 对象存储后端:支持AWS S3、Azure Blob等云存储,也可用MinIO自建

我们选择Velero而非传统方案(如手动kubectl导出)的主要原因:

  • 原子性操作:自动处理资源依赖关系,避免手动备份时常见的对象遗漏
  • CRD支持:完美备份自定义资源,这是很多DIY方案无法实现的
  • 增量备份:通过--snapshot-volumes参数可只备份变更的持久卷数据

2.2 ETCD备份的特殊性

虽然Velero能备份工作负载,但控制平面组件(如kube-apiserver)的状态仍依赖ETCD。ETCD备份有两大难点:

  1. 数据一致性:直接拷贝etcd数据目录会导致损坏,必须使用etcdctl snapshot save
  2. 证书问题:恢复时若证书过期会导致集群"脑裂",需要配合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

常见问题处理:

  1. StorageClass冲突:若目标集群StorageClass不同,需添加--storage-class-mappings参数
  2. 节点亲和性失效:恢复后检查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

关键检查点:

  1. 证书有效期:确保etcd证书在恢复后仍然有效
  2. 节点IP变更:若集群IP地址变化,需调整--initial-cluster参数
  3. 数据一致性:恢复后运行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-verify

6. 生产环境经验总结

6.1 Velero性能优化参数

在大规模集群中(500+节点),这些配置可显著提升备份效率:

velero install \ ... --restic-timeout 4h \ --restic-node-selector "backup=enabled" \ --default-volumes-to-fs-backup=false \ --features=EnableCSI

关键调整项:

  1. 专用备份节点:通过nodeSelector将备份Pod调度到特定节点
  2. CSI插件:对CSI卷使用原生快照功能(需存储供应商支持)
  3. 并行度控制:调整--client-qps和--client-burst参数应对API限流

6.2 ETCD恢复的黄金法则

根据多次真实故障演练,总结出三条铁律:

  1. 3-2-1备份原则

    • 至少保留3份备份
    • 存储在2种不同介质
    • 其中1份异地保存
  2. 变更立即备份

    • 集群证书更新后
    • 节点扩缩容操作前
    • Kubernetes版本升级前后
  3. 定期恢复演练

    • 每季度执行全集群灾难恢复演练
    • 验证备份的可用性而不仅是存在性

7. 典型故障排查手册

7.1 Velero常见错误代码

错误现象可能原因解决方案
BackupStorageLocation不可用凭证失效/网络中断检查velero日志中的AWS错误详情
Volume备份卡住Pod有大量小文件增加restic-timeout或排除缓存目录
恢复后PodPendingStorageClass不匹配使用--storage-class-mappings参数

7.2 ETCD恢复异常处理

案例:恢复后apiserver无法连接etcd

Error while dialing dial tcp 10.0.1.101:2379: connect: connection refused

排查步骤:

  1. 检查etcd服务状态:sudo systemctl status etcd
  2. 查看etcd日志:journalctl -u etcd -n 100
  3. 验证证书有效性:openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -noout -dates
  4. 检查监听地址:ss -tulnp | grep 2379

根本原因往往是:

  • 证书过期(需更新所有相关证书)
  • 数据目录权限错误(chown -R etcd:etcd /var/lib/etcd)
  • 网络配置变更(检查防火墙规则)

8. 多云环境下的备份策略

对于跨云部署的集群,建议采用分级备份方案:

  1. 本地快速恢复层

    • Velero + 集群内MinIO
    • 保留最近24小时备份
    • RTO(恢复时间目标)<30分钟
  2. 云端持久层

    • 每日同步到AWS S3 IA存储
    • 保留30天备份
    • 启用对象锁定防篡改
  3. 异地灾备层

    • 每周备份到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-backup

9. 监控与告警体系建设

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: false

9.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恢复场景中,证书问题是最常见的陷阱。建议采用以下方案:

  1. 证书轮换策略

    • 使用cert-manager自动管理证书
    • 设置比备份周期更长的有效期(如1年)
  2. 恢复时的证书处理

# 检查证书有效期 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
  1. 长期方案
    • 将etcd证书与kubeadm管理的证书分离
    • 使用Hashicorp Vault等工具集中管理证书
    • 在备份元数据中记录证书过期时间

对于大规模集群,我推荐使用以下证书目录结构:

/etc/kubernetes/pki/ ├── etcd/ │ ├── ca.crt │ ├── healthcheck-client.crt │ └── peer.crt └── kubeadm/ ├── apiserver.crt └── front-proxy-ca.crt

这种隔离设计可以避免恢复时证书的交叉影响。