【K8S 运维实战】21-备份恢复Velero
2026/7/29 4:38:09 网站建设 项目流程

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

一句话定位:集群挂了不可怕,可怕的是没备份或有备份恢复不了——这篇把 Velero 备份、CSI 快照和 DR 演练打通。

写在前面

我常说一句话:没做过恢复演练的备份等于没备份。某公司用 Velero 备份了半年,真到集群挂了想恢复,发现 S3 桶权限被人改了,恢复卡在 90%,数据全丢。备份的价值不在"拍了快照",而在"能完整恢复"。Velero 是 K8s 生态里最成熟的备份工具,这篇从架构到 DR 演练,把"可恢复的备份"做成闭环。

核心问题

  • 集群挂了,业务怎么快速恢复?Velero 备份资源清单 + PV 快照,在新集群一键恢复。
  • 跨集群迁移怎么做?Velero 把备份恢复到新集群,支持跨云。
  • RPO/RTO 怎么设计?按业务分级定备份频率和恢复目标,不是所有业务都一个标准。

一、原理剖析

1.1 Velero 架构

Velero 是 CNCF 的备份恢复工具,架构简单清晰:

创建 Backup CR

备份资源清单

调用插件

创建快照

磁盘快照

恢复时

恢复 PV

velero CLI

velero server

对象存储 S3/OSS

VolumeSnapshot 插件

CSI Driver

PV 数据

读取清单

CSI VolumeSnapshot

三大组件:

  • velero server:部署在集群里的控制器,监听 Backup/Restore/Schedule CRD
  • velero CLI:本地命令行工具,跟 server 通信
  • plugin:对接各种存储后端(AWS/Azure/阿里云 CSI 等)

1.2 备份机制:资源清单 + VolumeSnapshot

Velero 备份分两部分:

┌──────────────────────────────────────────┐ │ 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-configurationLocationConstraint=us-east-1# 创建 IAM 用户和策略(最小权限)cat>velero-policy.json<<EOF { "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 velero>velero-creds.json

Step 2:创建凭证文件

cat>credentials-velero<<EOF [default] aws_access_key_id=AKIAxxx aws_secret_access_key=xxx EOF

Step 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-configregion=us-east-1\--snapshot-location-configregion=us-east-1\--secret-file credentials-velero\--use-volume-snapshots=true\--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 资源限制cat>node-agent-config.yaml<<EOF 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.yaml

2.2 按需备份与恢复

按需备份:

# 备份整个 namespacevelero backup create app1-backup-20260718\--include-namespaces app1\--include-cluster-resources=false\--default-volumes-to-fs-backup=true\--snapshot-volumes=true# 查看备份状态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 get

2.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.sql"onError: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 get

2.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.yaml

VolumeSnapshotClass 示例(AWS EBS):

# volume-snapshot-class.yamlapiVersion:snapshot.storage.k8s.io/v1kind:VolumeSnapshotClassmetadata:name:ebs-snapshot-classdriver:ebs.csi.aws.comdeletionPolicy:Retain# 删除 PV 时不删快照parameters:encrypted:"true"
kubectl 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 backup

velero restore

DB 主从复制

源集群 A

S3 对象存储

目标集群 B

Step 1:源集群备份

# 在集群 A 执行velero backup create migration-app1\--include-namespaces app1\--default-volumes-to-fs-backup=true\--snapshot-volumes=false# 跨云用 restic,不用云快照

Step 2:目标集群配置同一对象存储

# 在集群 B 安装 velero,指向同一 S3 桶veleroinstall\--provideraws\--pluginsvelero/velero-plugin-for-aws:v1.10.0\--bucketk8s-velero-backup\--backup-location-configregion=us-east-1\--snapshot-location-configregion=us-east-1\--secret-file credentials-velero\--use-volume-snapshots=true\--use-node-agent

Step 3:目标集群恢复

# 在集群 B 执行,备份会从 S3 同步过来velero backup get# 应能看到 migration-app1velero restore create migration-app1-restore\--from-backup migration-app1\--namespace-mappings app1:app1

Step 4:数据库单独迁移

DB 跨云迁移用主从复制,不用走 Velero:

# 1. 新集群 DB 配置为旧集群 DB 的从库# 2. 等待数据同步# 3. 切换:旧 DB 只读 → 等同步完成 → 新 DB 提升为主# 4. 更新 Service 指向

三、踩坑与排查

坑1:restic 备份卡住,进度不动

现象:velero backup describe显示Waiting for free upnode 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 pod<pod>backup.velero.io/backup-volumes=data,logs-napp1

坑2:恢复后 PVC 一直 Pending

现象:restore 完成,但 PVC 卡在 Pending,Pod 无法启动。

原因:跨云恢复时,VolumeSnapshotContent 引用的快照在新云不存在;或 StorageClass 不可用。

解决:

# 1. 检查 PVC 事件kubectl describe pvc<pvc>-napp1# 2. 跨云场景改用 restic 恢复(不用云快照)velero restore create app1-restore-restic\--from-backup app1-backup\--restore-volumes=true\--volume-snapshots=false# 忽略云快照,用 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-file=cloud=credentials-velero\-nvelero --dry-run=client-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 演练变成季度常规动作,真到出事那天,你才能从容不迫。

思考题

  1. CSI VolumeSnapshot 和 restic 备份,同一个 PV 都做了备份,恢复时 Velero 用哪个?
  2. 跨云迁移(AWS→阿里云),PV 数据用云快照还是 restic?为什么?
  3. 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/

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询