Velero 跨集群迁移实战:基于 Backup 与 Restore 的 Kubernetes 应用搬迁指南
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
Velero 提供了一套简洁而强大的跨集群迁移方案:只要源、目标两个集群的 Velero 实例指向同一个云对象存储位置,就可以通过"源集群备份、目标集群恢复"的方式,将 Kubernetes 应用及其数据完整地搬迁到另一个集群。本指南以site/content/docs/v1.1.0/migration-case.md的迁移步骤为主线,结合当前仓库中的 CLI 源码与控制器实现,带你从原理到实操完整掌握集群迁移流程,并理解 TTL、只读存储位置、备份同步周期等关键机制背后的实现细节。
适用范围说明:本文描述的操作适用于将应用从集群 A 迁移到集群 B,且两个集群由同一云厂商托管、共用同一个对象存储桶的场景。Velero 不支持跨云厂商的持久化卷(PV)迁移。
迁移原理:同一个对象存储,两个集群的"交接棒"
Velero 的跨集群迁移不依赖集群之间的任何直接网络连接。其核心思路是:
- 源集群(Cluster 1)将集群状态与持久卷数据备份到云对象存储(如 AWS S3、Azure Blob、GCP GCS)中的某个 bucket。
- 目标集群(Cluster 2)配置指向同一个 bucket的
BackupStorageLocation(备份存储位置)与VolumeSnapshotLocation(卷快照位置)。 - 目标集群的 Velero 服务器周期性从对象存储同步备份元数据,将远端备份文件"物化"为集群内的 Backup 对象。
- 用户基于该 Backup 对象执行恢复,应用即在目标集群中重建。
由于备份数据与快照数据都保存在共享的对象存储中,两个集群的 Velero 只需在存储层"交接",即可完成整个迁移流程。这也是为什么文档中明确要求"每个 Velero 实例指向相同的云对象存储位置"。
前提条件与关键限制
在动手之前,请确认以下前提:
- 同一云厂商:两个集群必须由同一云厂商托管(例如同为 AWS EKS、同为 Azure AKS),因为
VolumeSnapshotLocation的快照是云厂商绑定的资源。 - 共享对象存储:两个集群的
BackupStorageLocation必须指向相同的 bucket 与 prefix。 - 持久化卷不可跨云迁移:Velero 不支持把 PV 从一家云厂商迁移到另一家云厂商。若你的目标确实需要跨云搬迁持久化数据,需要配合其他数据迁移手段(本文不展开)。
- Velero 部署在相同命名空间:如果恢复过程遇到异常,优先检查两个集群中 Velero 是否都运行在同一个命名空间下(默认
velero)。
第一步(Cluster 1):备份整个源集群
如果你此前没有通过 Velero 的schedule定时备份对集群做持续"检查点"(checkpoint)保护,那么迁移的第一步就是在源集群上创建一个覆盖全集群的备份:
velero backup create <BACKUP-NAME>其中<BACKUP-NAME>替换为你期望的备份名称,例如migration-backup-20260916。
TTL 与备份生命周期
默认情况下,该备份的 TTL(生存时间)为30 天(720 小时),到期后备份会被垃圾回收机制清理,无法再用于恢复。如果你需要更长的保留期,可使用--ttl标志覆盖:
velero backup create <BACKUP-NAME> --ttl 2160h0m0s上述命令将 TTL 延长到 90 天。从源码结构看,默认 TTL 定义在 pkg/cmd/server/config/config.go 中:defaultBackupTTL = 30 * 24 * time.Hour,该值通过服务器参数--default-backup-ttl暴露,最终由 backup_controller.go 在请求未显式指定 TTL 时填充到 Backup 对象的Spec.TTL。对应的单元测试TestDefaultBackupTTL(见 backup_controller_test.go)验证了默认 TTL 为24 * 30 * time.Hour且 Expiration 时间正确。
此外,--ttl参数的解析入口位于 pkg/cmd/cli/backup/create.go,其帮助文本为 "How long before the backup can be garbage collected.",说明 TTL 直接决定了备份何时可被垃圾回收——迁移前请务必评估备份保留期是否覆盖完整的迁移窗口。
迁移窗口提示:备份完成后到恢复执行期间,备份文件必须保持在 TTL 之内,否则对象存储中的备份可能已被清理,目标集群将无法同步到该备份。
第二步(Cluster 2):配置指向源存储的备份位置
在目标集群中,需要配置两类存储位置,让 Velero 知道去哪里读取源集群的备份数据:
velero backup-location create <BSL-NAME> \ --provider <PROVIDER> \ --bucket <BUCKET-NAME> \ --prefix <PREFIX> \ --access-mode=ReadOnly velero snapshot-location create <VSL-NAME> \ --provider <PROVIDER> \ ...参数说明(以当前仓库 CLI 实现为准):
--provider:对象存储厂商标识,例如aws、azure、gcp(来源:pkg/cmd/cli/backuplocation/create.go)。--bucket:对象存储桶名称,必须与 Cluster 1 使用的 bucket 一致(同上,L93)。--prefix:桶内 Velero 数据的存储前缀,必须与 Cluster 1 的 prefix 一致(同上,L96)。--access-mode=ReadOnly:将BackupStorageLocation配置为只读模式,防止目标集群误写入或覆盖源集群的备份数据。这是迁移场景中的关键安全措施。- 可选:
--backup-sync-period覆盖该位置的备份同步周期;--validation-frequency覆盖存储位置有效性校验频率;--cacert指定验证对象存储 TLS 连接用的 CA 证书包(同上,L97-L101)。
只读模式的实现
--access-mode在 create.go 中被实现为一个枚举标志(flag.Enum),允许值仅为ReadWrite(默认)与ReadOnly;其取值最终写入BackupStorageLocation.Spec.AccessMode(见BuildBackupStorageLocation,L168)。只读位置不会参与备份写入,从而保证迁移过程中源数据不被目标集群污染。
关于 VolumeSnapshotLocation
VolumeSnapshotLocation用于告诉 Velero 在哪个云区域、以何种方式创建/读取卷快照。迁移时它必须指向源集群快照所在的区域与配置,否则恢复阶段无法找到对应的云快照。由于快照是云厂商级资源,这也是文档强调"集群需由同一云厂商托管"的根本原因。
第三步(Cluster 2):等待并确认备份同步
配置好存储位置后,目标集群的 Velero 会周期性地从对象存储同步备份文件,将远端的备份"物化"为本地的 Backup API 对象。在 Cluster 2 上检查备份是否已经同步:
velero backup describe <BACKUP-NAME>同步间隔与默认值
默认情况下,备份同步间隔为1 分钟——刚配置完存储位置后立即执行命令可能还看不到该备份,需要稍作等待。你可以通过 Velero 服务器的--backup-sync-period标志调整这个间隔(默认值同样为 1 分钟,定义于 pkg/cmd/server/config/config.go)。
从源码实现看,备份同步由 backup_sync_controller.go 中的backupSyncReconciler驱动:
- 同步周期优先取每个
BackupStorageLocation的Spec.BackupSyncPeriod;未显式设置时回退到服务器默认值(L406-L408)。 - 若该位置显式设置为
0s,则该位置的备份同步被禁用(L409-L411)。 - 若周期为负值,则回退到默认周期(L414-L417)。
- 实际同步时机会根据
Status.LastSyncedTime判断:lastSync + syncPeriod之前不会重复同步(L420-L427)。
因此,如果你想加速迁移验证,可以临时将--backup-sync-period调小,或在确认同步完成后恢复默认值。
提示:
velero backup describe <BACKUP-NAME>也能用于确认备份内容(包含的命名空间、资源、卷等)与源集群预期一致,相当于迁移前的"数据清单核验"。
第四步(Cluster 2):从备份恢复
确认 Cluster 2 上已经存在正确的 Backup 对象后,执行恢复:
velero restore create --from-backup <BACKUP-NAME>该命令的入口定义在 pkg/cmd/cli/restore/create.go,使用形式为velero restore create [RESTORE_NAME] [--from-backup BACKUP_NAME | --from-schedule SCHEDULE_NAME]。--from-backup标志(L138)指定恢复来源的备份名,并且 CLI 提供了--from-backup的自动补全(L85)。
恢复是可选的细粒度控制的——例如只恢复 PVC 与 PV:
velero restore create --from-backup <BACKUP-NAME> --include-resources persistentvolumeclaims,persistentvolumes恢复默认会还原备份中的全部资源。如需限定范围,可使用--include-namespaces、--exclude-namespaces、--include-resources、--exclude-resources等过滤器(与备份创建命令同源,见 pkg/cmd/cli/backup/create.go 的对应标志)。
验证两个集群的迁移结果
恢复发起后,在 Cluster 2 上确认恢复是否成功:
velero restore get该命令会列出集群中所有恢复及其状态(InProgress、Completed、Failed等)。找到本次恢复的名称后,查看详细情况:
velero restore describe <RESTORE-NAME-FROM-GET-COMMAND>describe输出中包含恢复的总体状态、处理的资源项数、错误与警告统计等信息。如果恢复包含卷数据,还可以进一步通过velero backup describe或云厂商快照控制台核验持久化数据是否完整。
从源码结构看,恢复执行路径由 pkg/controller/restore_controller.go 负责驱动:它读取 Backup 中的资源清单,逐一重建 Kubernetes 对象并触发卷数据恢复,最终更新 Restore 对象状态。
restore get/describe展示的正是该控制器写入的状态字段。
常见问题与排查
backup describe找不到备份:大概率是同步尚未完成。默认同步间隔 1 分钟,请等待后重试;也可以调小--backup-sync-period加速。- 恢复报错找不到卷快照:检查
VolumeSnapshotLocation是否指向源集群快照所在区域与配置;确认两个集群由同一云厂商托管。 - 备份被清理:确认备份仍在 TTL 内;迁移窗口较长的场景建议在创建备份时显式设置足够大的
--ttl。 - Velero 命名空间不一致:文档特别强调,遇到问题时务必确认 Velero 在两个集群中运行于同一个命名空间,否则存储位置、备份等对象无法正确对齐。
结语
通过"共享对象存储 + 只读备份位置 + 备份同步 + 恢复"四个步骤,Velero 让跨集群迁移变得清晰可控。理解 TTL、同步周期、AccessMode 这些参数背后的源码实现,能帮助你在真实迁移场景中做出更稳妥的配置决策。如果想深入探索备份同步控制器、恢复控制器的完整实现,可以直接阅读本仓库的 pkg/controller/backup_sync_controller.go、pkg/controller/restore_controller.go,以及 CLI 层的 pkg/cmd/cli/backuplocation/create.go 与 pkg/cmd/cli/restore/create.go。
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考