【K8S 运维实战】21-备份恢复Velero
备份恢复:Velero 实战与灾备方案一句话定位:集群挂了不可怕,可怕的是没备份或有备份恢复不了——这篇把 Velero 备份、CSI 快照和 DR 演练打通。写在前面我常说一句话:没做过恢复演练的备份等于没备份。某公司用 Velero 备份了半年,真到集群挂了想恢复,发现 S3 桶权限被人改了,恢复卡在 90%,数据全丢。备份的价值不在拍了快照,而在能完整恢复。Velero 是 K8s 生态里最成熟的备份工具,这篇从架构到 DR 演练,把可恢复的备份做成闭环。核心问题集群挂了,业务怎么快速恢复?Velero 备份资源清单 PV 快照,在新集群一键恢复。跨集群迁移怎么做?Velero 把备份恢复到新集群,支持跨云。RPO/RTO 怎么设计?按业务分级定备份频率和恢复目标,不是所有业务都一个标准。一、原理剖析1.1 Velero 架构Velero 是 CNCF 的备份恢复工具,架构简单清晰:创建 Backup CR备份资源清单调用插件创建快照磁盘快照恢复时恢复 PVvelero CLIvelero server对象存储 S3/OSSVolumeSnapshot 插件CSI DriverPV 数据读取清单CSI VolumeSnapshot三大组件:velero server:部署在集群里的控制器,监听 Backup/Restore/Schedule CRDvelero CLI:本地命令行工具,跟 server 通信plugin:对接各种存储后端(AWS/Azure/阿里云 CSI 等)1.2 备份机制:资源清单 VolumeSnapshotVelero 备份分两部分:┌──────────────────────────────────────────┐ │ Velero Backup 内容 │ │ │ │ ┌────────────────────────────────┐ │ │ │ 1. 资源清单(YAML) │ │ │ │ - Deployment/Service/ConfigMap│ │ │ │ - Secret/PV/PVC/Ingress │ │ │ │ - 全部 namespace 的资源 │ │ │ └────────────────────────────────┘ │ │ ┌────────────────────────────────┐ │ │ │ 2. PV 数据快照 │ │ │ │ 方式A: 云原生 VolumeSnapshot │ │ │ │ (CSI,推荐) │ │ │ │ 方式B: 文件系统级 restic │ │ │ │ (兜底,跨云可用) │ │ │ └────────────────────────────────┘ │ └──────────────────────────────────────────┘两种 PV 备份方式对比:方式原理优点缺点适用场景CSI VolumeSnapshot调用存储驱动做块级快照快、一致性好、支持增量需 CSI 驱动支持云盘存储restic文件系统级备份到对象存储通用、跨云慢、占对象存储NFS/本地盘/跨云1.3 RPO/RTO 设计不同业务对备份的要求不同,分级设计:业务等级RPO(数据丢失)RTO(恢复时间)备份策略核心交易5 分钟30 分钟每小时定时 DB 主从业务系统1 小时2 小时每 2 小时定时内部工具24 小时8 小时每日备份测试环境无要求无要求手动备份RPO 决定备份频率,RTO 决定恢复手段。核心交易光靠 Velero 不够,要配合 DB 主从复制做接近零 RPO。二、实战操作2.1 Velero 安装Step 1:准备对象存储(S3/OSS)# 创建 S3 桶(示例 AWS CLI)aws s3api create-bucket\--bucketk8s-velero-backup\--regionus-east-1\--create-bucket-configurationLocationConstraintus-east-1# 创建 IAM 用户和策略(最小权限)catvelero-policy.jsonEOF { Version: 2012-10-17, Statement: [ { Effect: Allow, Action: [s3:GetObject,s3:DeleteObject,s3:PutObject,s3:AbortMultipartUpload,s3:ListMultipartUploadParts], Resource: [arn:aws:s3:::k8s-velero-backup/*] }, { Effect: Allow, Action: [s3:ListBucket], Resource: [arn:aws:s3:::k8s-velero-backup] }, { Effect: Allow, Action: [ec2:CreateSnapshot,ec2:CreateVolume,ec2:DeleteSnapshot,ec2:DescribeSnapshots,ec2:DescribeVolumes], Resource: * } ] } EOFaws iam create-user --user-name velero aws iam put-user-policy --user-name velero --policy-name velero --policy-document file://velero-policy.json aws iam create-access-key --user-name velerovelero-creds.jsonStep 2:创建凭证文件catcredentials-veleroEOF [default] aws_access_key_idAKIAxxx aws_secret_access_keyxxx EOFStep 3:安装 Velero# 下载 velero CLIwgethttps://github.com/vmware-tanzu/velero/releases/download/v1.15.0/velero-v1.15.0-linux-amd64.tar.gztarxzf velero-v1.15.0-linux-amd64.tar.gzmvvelero-v1.15.0-linux-amd64/velero /usr/local/bin/# 安装到集群(对接 S3 AWS CSI 插件)veleroinstall\--provideraws\--pluginsvelero/velero-plugin-for-aws:v1.10.0\--bucketk8s-velero-backup\--backup-location-configregionus-east-1\--snapshot-location-configregionus-east-1\--secret-file credentials-velero\--use-volume-snapshotstrue\--use-node-agent\--node-agent-configmap node-agent-config\--velero-pod-cpu-request 500m\--velero-pod-mem-request 512Mi\--velero-pod-cpu-limit2\--velero-pod-mem-limit 2Gi\--replicas2# 验证kubectl get pods-nvelero# velero 和 node-agent(原 restic daemonset)都要 Runningvelero backup-location get# 期望: default 可用Step 4:启用 restic 兜底(可选,给不支持 CSI 的存储用)# 上面 --use-node-agent 已启用 restic daemonset# 配置 restic 资源限制catnode-agent-config.yamlEOF apiVersion: v1 kind: ConfigMap metadata: name: node-agent-config namespace: velero data: restic.yaml: | podResources: cpuRequest: 200m memRequest: 128Mi cpuLimit: 1000m memLimit: 1Gi EOFkubectl apply-fnode-agent-config.yaml2.2 按需备份与恢复按需备份:# 备份整个 namespacevelero backup create app1-backup-20260718\--include-namespaces app1\--include-cluster-resourcesfalse\--default-volumes-to-fs-backuptrue\--snapshot-volumestrue# 查看备份状态velero backup describe app1-backup-20260718--detailsvelero backup get恢复:# 恢复到原 namespacevelero restore create --from-backup app1-backup-20260718# 恢复到新 namespace(迁移场景)velero restore create app1-restore-new\--from-backup app1-backup-20260718\--namespace-mappings app1:app1-new# 查看恢复状态velero restore describe app1-restore-new--detailsvelero restore get2.3 定时备份 Schedule CRD# schedule-core.yaml - 核心业务每小时备份apiVersion:velero.io/v1kind:Schedulemetadata:name:backup-app1-hourlynamespace:velerospec:schedule:0 * * * *# 每小时template:includedNamespaces:-app1-app2includedClusterResources:falsedefaultVolumesToFsBackup:truesnapshotVolumes:truettl:168h# 保留 7 天storageLocation:defaultvolumeSnapshotLocations:-defaulthooks:pre:-exec:container:appcommand:-/bin/sh--c-pg_dump -U postgres appdb /tmp/dump.sqlonError:Fail---apiVersion:velero.io/v1kind:Schedulemetadata:name:backup-all-dailynamespace:velerospec:schedule:0 2 * * *# 每天 2 点template:includedNamespaces:-*defaultVolumesToFsBackup:truesnapshotVolumes:truettl:720h# 保留 30 天kubectl apply-fschedule-core.yaml velero schedule get2.4 CSI VolumeSnapshot 配置CSI 快照比 restic 快且一致性好,生产优先用。需要先部署 CSI snapshot controller:# 安装 CSI snapshot CRD 和 controllerkubectl apply-fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v7.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml kubectl apply-fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v7.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml kubectl apply-fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v7.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml kubectl apply-fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v7.0.0/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml kubectl apply-fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v7.0.0/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yamlVolumeSnapshotClass 示例(AWS EBS):# volume-snapshot-class.yamlapiVersion:snapshot.storage.k8s.io/v1kind:VolumeSnapshotClassmetadata:name:ebs-snapshot-classdriver:ebs.csi.aws.comdeletionPolicy:Retain# 删除 PV 时不删快照parameters:encrypted:truekubectl apply-fvolume-snapshot-class.yaml# 设置默认 VolumeSnapshotClasskubectl patch volumesnapshotclass ebs-snapshot-class\-p{metadata:{annotations:{snapshot.storage.kubernetes.io/is-default-class:true}}}2.5 跨集群迁移跨集群迁移是 Velero 的强项,流程:velero backupvelero restoreDB 主从复制源集群 AS3 对象存储目标集群 BStep 1:源集群备份# 在集群 A 执行velero backup create migration-app1\--include-namespaces app1\--default-volumes-to-fs-backuptrue\--snapshot-volumesfalse# 跨云用 restic,不用云快照Step 2:目标集群配置同一对象存储# 在集群 B 安装 velero,指向同一 S3 桶veleroinstall\--provideraws\--pluginsvelero/velero-plugin-for-aws:v1.10.0\--bucketk8s-velero-backup\--backup-location-configregionus-east-1\--snapshot-location-configregionus-east-1\--secret-file credentials-velero\--use-volume-snapshotstrue\--use-node-agentStep 3:目标集群恢复# 在集群 B 执行,备份会从 S3 同步过来velero backup get# 应能看到 migration-app1velero restore create migration-app1-restore\--from-backup migration-app1\--namespace-mappings app1:app1Step 4:数据库单独迁移DB 跨云迁移用主从复制,不用走 Velero:# 1. 新集群 DB 配置为旧集群 DB 的从库# 2. 等待数据同步# 3. 切换:旧 DB 只读 → 等同步完成 → 新 DB 提升为主# 4. 更新 Service 指向三、踩坑与排查坑1:restic 备份卡住,进度不动现象:velero backup describe显示Waiting for free up或node agent is not available。原因:node-agent(restic daemonset)在某些节点没起来,或资源不足。解决:# 1. 检查 node-agent 是否所有节点都有kubectl get ds-nvelero# 2. 查看失败节点的 node-agent 日志kubectl logs-nvelero node-agent-xxxxx# 3. 常见问题:PV 没挂载点,restic 无法访问数据# 给 Pod 加 backup.velero.io/backup-volumes 注解指定要备份的卷kubectl annotate podpodbackup.velero.io/backup-volumesdata,logs-napp1坑2:恢复后 PVC 一直 Pending现象:restore 完成,但 PVC 卡在 Pending,Pod 无法启动。原因:跨云恢复时,VolumeSnapshotContent 引用的快照在新云不存在;或 StorageClass 不可用。解决:# 1. 检查 PVC 事件kubectl describe pvcpvc-napp1# 2. 跨云场景改用 restic 恢复(不用云快照)velero restore create app1-restore-restic\--from-backup app1-backup\--restore-volumestrue\--volume-snapshotsfalse# 忽略云快照,用 restic 数据# 3. 确认目标集群有合适的 StorageClasskubectl get storageclass坑3:备份成功但恢复时资源冲突现象:restore 部分失败,日志resource exists and cannot be patched。原因:目标集群已有同名资源,默认策略导致冲突。解决:指定恢复策略:velero restore create app1-restore\--from-backup app1-backup\--existing-resource-policy update# update 覆盖,none 跳过坑4:S3 桶权限丢失,备份全失效现象:velero backup-location get显示 unavailable,新备份全失败。原因:IAM 凭证过期或权限被改。解决:# 1. 更新凭证kubectl create secret generic cloud-credentials\--from-filecloudcredentials-velero\-nvelero --dry-runclient-oyaml|kubectl apply-f-# 2. 重启 velerokubectl rollout restart deployment velero-nvelero# 3. 验证velero backup-location get预防:对象存储权限纳入监控,定期验证备份可恢复。四、最佳实践生产用 CSI VolumeSnapshot 为主,restic 兜底非 CSI 存储按业务等级分级备份(核心每小时,普通每日)TTL 自动清理老备份(7 天/30 天)对象存储开启版本控制,防误删备份前用 pre-hook 做 DB dump,保证一致性每月做一次完整 DR 演练(备份恢复)跨集群迁移用 restic 而非云快照(跨云不兼容)DB 不依赖 Velero,走主从复制监控备份成功率,Prometheus 告警备份桶权限最小化,凭证定期轮转node-agent 资源给足(大 PV 备份吃内存)备份对象存储异地复制(防区域级灾难)五、小结备份恢复是运维的最后一道防线,这道防线必须可靠。Velero 解决了资源清单 PV 数据的备份恢复,但真正的灾备是体系工程:Velero 负责 K8s 资源,DB 走主从复制,对象存储做异地副本,定期演练验证可恢复性。记住备份的金科玉律:没验过恢复的备份等于没备份。把 DR 演练变成季度常规动作,真到出事那天,你才能从容不迫。思考题CSI VolumeSnapshot 和 restic 备份,同一个 PV 都做了备份,恢复时 Velero 用哪个?跨云迁移(AWS→阿里云),PV 数据用云快照还是 restic?为什么?DB 用 Velero 备份和用 DB 自身的 dump主从,哪个 RPO 更低?为什么?延伸阅读Velero 官方文档:https://velero.io/docs/CSI VolumeSnapshot:https://kubernetes.io/docs/concepts/storage/volume-snapshots/Velero 插件列表:https://velero.io/plugins/