Velero 备份 Kubernetes 集群与应用恢复实战

只备份 PVC 恢复不了应用:Deployment、Service、ConfigMap、Secret 这些 K8s 对象丢了,光有数据盘也没用。Velero 是 K8s 的标准备份工具,同时备份 K8s 对象(存对象存储)与持久卷(调 CSI 快照或 Restic 文件备份),支持跨集群恢复与迁移,是集群容灾的标配。

先说 Velero 的两种卷备份方式:CSI 快照方式快、但依赖云平台快照能力;Restic 方式把文件打包上传对象存储,不依赖云快照、跨云可用,但备份与恢复都慢一些。选哪种看你的云环境与迁移需求。

一、部署:Velero 服务端与对象存储

Velero 服务端跑在集群里一个 Deployment,备份数据存到对象存储(S3 兼容)。安装前先准备好对象存储桶与访问密钥,桶要与集群分开存放——集群挂了桶还在,备份才有意义。

<pre class="wp-block-syntaxhighlighter-code"># 准备访问密钥文件(示例为 S3 兼容存储,密钥用占位)
cat > /tmp/credentials-velero <<'EOF'
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
EOF
# 安装 Velero(以 AWS 插件为例,其他云换对应插件)
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.10.0 \
  --bucket velero-backup \
  --secret-file /tmp/credentials-velero \
  --backup-location-config region=cn-north-1 \
  --snapshot-location-config region=cn-north-1 \
  --use-node-agent
# 验证服务端正常
kubectl -n velero get pods
velero backup-location get</pre>

--use-node-agent 会在每个节点上装 Node Agent(旧称 restic DaemonSet),用于 Restic 方式的文件级备份。不用 Restic 时可以不装,但建议装上,跨云恢复时用得上。

二、备份:手动备份与定时备份

备份分两种:手动备份用于变更前、迁移前;定时备份(Schedule)用于日常容灾。备份时默认包含命名空间下所有对象,可用 label 选择器只备指定应用,避免把全集群的备份做得过大。

# 手动备份一个命名空间(含 PVC 快照)
velero backup create app-backup-20261109 --include-namespaces app-prod --wait
# 查看备份状态与内容
velero backup describe app-backup-20261109
velero backup get
# 定时备份:每天凌晨 2 点备份 app-prod 与 infra 两个命名空间,保留 30 天
velero schedule create daily-app \
  --schedule="0 2 * * *" \
  --include-namespaces app-prod,infra \
  --ttl 720h
velero schedule get

TTL 到期后备份会被自动清理,保留期要按合规与磁盘成本定。重要变更前手动备份一次,不要只依赖定时备份——定时备份可能正好在变更前一晚跑完,恢复点不是你想要的。

三、恢复:同集群恢复与跨集群迁移

恢复分两种场景:同集群恢复(误删命名空间、应用配错)与跨集群恢复(集群重建、应用迁移)。跨集群恢复前,先在目标集群装好相同版本的 Velero 并指向同一个对象存储桶,恢复时用 --restore-namespaces-mappings 可以改名恢复到新命名空间。

<pre class="wp-block-syntaxhighlighter-code"># 同集群恢复(先确认备份完成,状态为 Completed)
velero restore create --from-backup app-backup-20261109 --wait
velero restore describe <restore-name>
kubectl -n app-prod get pods
# 跨集群恢复到新命名空间(目标集群执行)
velero restore create --from-backup app-backup-20261109 \
  --namespace-mappings app-prod:app-prod-restored --wait
# 只恢复部分资源(例如只要 Deployment 与 PVC)
velero restore create --from-backup app-backup-20261109 \
  --include-resources deployments,persistentvolumeclaims --wait</pre>

恢复后要验证三件事:Pod 是否全部 Running、Service 与 Ingress 是否正常、应用数据是否在备份点。数据库类应用恢复后还要检查数据一致性,必要时用数据库自身的 PITR 再往前推。

四、Restic 文件级备份:不依赖云快照的方案

云上没有 CSI 快照、或要跨云迁移时,用 Restic 方式:Velero 在 Pod 注解里声明要备份的卷,Node Agent 把文件打包上传对象存储。备份前给 PVC 所在的 Pod 打注解,恢复时 Velero 自动把文件还原回新 PVC。

<pre class="wp-block-syntaxhighlighter-code"># 给需要文件级备份的 Pod 打注解(在 Deployment 模板里加)
# annotations:
#   backup.velero.io/backup-volumes: data
kubectl annotate pod <pod> backup.velero.io/backup-volumes=data
# 备份时指定用文件系统备份
velero backup create app-fs-backup --include-namespaces app-prod \
  --default-volumes-to-fs-backup --wait
# 查看 Node Agent 是否正常工作
kubectl -n velero get pods -l app.kubernetes.io/name=node-agent
kubectl -n velero logs -l app.kubernetes.io/name=node-agent --tail=50 | grep -i -E 'error|failed' | tail -20</pre>

五、定时备份与保留策略:备份要自动跑,也要自动清

手动备份靠人记,早晚会漏。Velero 的 Schedule 可以按 cron 定时备份,配上 TTL 自动清理过期备份,备份策略一旦定下来就不用再人工干预。定时备份的频率要按业务的 RPO 来定:核心命名空间每天一次、普通命名空间每周一次,备份窗口尽量放在业务低峰。

# 每天凌晨 2 点备份核心命名空间,保留 30 天
velero schedule create daily-core \
  --schedule="0 2 * * *" \
  --include-namespaces app-prod,db-prod \
  --ttl 720h
# 每周日备份全集群(不含 Velero 自身命名空间)
velero schedule create weekly-full \
  --schedule="0 3 * * 0" \
  --exclude-namespaces velero \
  --ttl 720h
# 看定时任务与最近一次备份状态
velero schedule get
velero backup get | head -20
# 备份失败告警:查最近一次备份的 describe,看 Failed 原因
velero backup describe daily-core-20261109020000 --details | grep -A5 -i error
# 手动清理过期备份(TTL 到期会自动删,这里是提前清理)
velero backup delete daily-core-20261101020000 --confirm

定时备份最容易踩的坑是备份窗口撞上业务高峰:备份会给 API Server 与 etcd 加压,窗口期要和业务低峰对齐。TTL 不要设得太短,至少覆盖“发现故障 → 决定恢复”的时间,30 天是比较稳妥的起点。定时任务建好后,第一周每天人工核对一次备份状态,确认稳定后再交给监控。

六、选择性备份与排除:不是所有东西都要备

全量备份会把临时 Job、已完成的 Pod、调试用的资源一起备进来,恢复时反而添乱。用 label selector 与排除规则可以精确控制备份范围:核心业务按标签备份,日志、缓存、临时资源排除在外,备份体积小了、恢复也快了。

# 只备份带 backup=true 标签的资源
velero backup create selective-backup \
  --selector backup=true \
  --include-namespaces app-prod
# 排除指定资源类型与命名空间
velero backup create backup-no-cache \
  --include-namespaces app-prod \
  --exclude-namespaces app-prod-cache \
  --exclude-resources pods,jobs
# 备份时排除指定标签的资源
velero backup create backup-no-temp \
  --include-namespaces app-prod \
  --exclude-labels temp=true
# 备份前先看会备哪些资源(dry-run 思路:先备份到测试环境核对)
velero backup describe selective-backup --details | grep -E 'Namespace|Resource' | head -30
# 恢复时也可以只恢复部分命名空间
velero restore create restore-core --from-backup selective-backup \
  --include-namespaces app-prod --namespace-mappings app-prod:app-prod-restored

选择性备份的风险是“漏备”:新上线的命名空间、没打标签的资源,可能悄悄游离在备份之外。建议每月跑一次全量备份作为兜底,日常用选择性备份做高频保护。备份范围变更后要重新核对一次备份内容清单,确认核心资源都在里面。

七、灾难恢复演练:恢复流程要定期真跑一遍

备份策略写得再好,没演练过等于没做过。演练要模拟真实故障:在隔离的命名空间或测试集群里,用备份完整恢复一次,验证应用能启动、数据能对上、外部流量能接进来。演练要计时:从“决定恢复”到“业务恢复”的耗时,就是真实的 RTO。

<pre class="wp-block-syntaxhighlighter-code"># 演练:在隔离命名空间里恢复,验证后再清理
velero restore create drill-restore \
  --from-backup daily-core-20261109020000 \
  --namespace-mappings app-prod:app-prod-drill
# 看恢复进度与状态
velero restore get drill-restore
velero restore describe drill-restore --details | grep -E 'Phase|Errors|Warnings'
# 验证:Pod 是否 Running、Service 是否正常、数据行数是否对得上
kubectl -n app-prod-drill get pods
kubectl -n app-prod-drill exec -it <pod> -- curl -s http://localhost:8080/healthz
# 演练结束清理隔离命名空间,避免残留资源干扰
kubectl delete namespace app-prod-drill
# 演练记录:恢复耗时、遇到的问题、需要改进的步骤,写进演练报告</pre>

演练频率建议每季度至少一次,核心业务每月一次。演练要覆盖两种场景:同集群恢复(命名空间级故障)与跨集群恢复(集群级故障),只练一种等于只做了一半。演练中发现的问题——比如 Secret 没恢复、镜像拉取密钥过期——要立刻修进备份策略,下次演练再验证。

八、演练与避坑清单

  • 每月演练一次:在测试集群上完整恢复一次备份,核对 Pod、Service、数据三项,记录恢复耗时(RTO 真实值)。
  • 备份校验:每次备份后看状态是否为 Completed,PartiallyFailed 的备份要查日志、不要当成成功。
  • 对象存储分开:备份桶与集群不在同一个云账号/区域,集群整体故障时桶不受影响。
  • Secret 注意:Velero 默认备份 Secret,恢复到新集群时注意云账号密钥、镜像拉取密钥是否需要更新。
  • 不要只备 PVC:快照恢复的是卷,Velero 恢复的是应用,两者配合才是完整容灾;数据库还要叠加自身的逻辑/物理备份。
  • 版本一致:源集群与目标集群的 Velero 版本、K8s 版本尽量一致,跨大版本恢复前先在测试集群验证。

发表回复

后才能评论