Velero 工作原理深度解析:CRD 驱动的 Kubernetes 备份、恢复与灾难恢复架构
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
导读
Velero(当前仓库项目名为 GitHub_Trending/ve/velero)是面向 Kubernetes 集群的备份与迁移工具。本文基于官方文档 site/content/docs/v1.1.0/about.md 的核心内容,系统讲解 Velero 的三大核心操作——按需备份、定时备份与恢复——如何以 Kubernetes 自定义资源(CRD)+ 控制器(Controller)的机制运转,并结合当前仓库的源码实现(pkg/apis/velero/v1/下的类型定义与pkg/controller/下的控制器)进行纵深佐证。读完本文,你将掌握 Velero 的完整工作流、备份/恢复的筛选机制、TTL 过期策略、对象存储同步原理,以及如何在灾备与集群升级等真实场景中正确使用 Velero。
Velero 的核心模型:一切操作都是 Kubernetes 自定义资源
Velero 最关键的设计思想是:每一次操作——无论是按需备份、定时备份还是恢复——都被建模为一个 Kubernetes 自定义资源(Custom Resource Definition, CRD),并持久化存储在 etcd 中。与此同时,Velero 内置了一组控制器(controller),负责持续监听并处理这些自定义资源,从而驱动备份、恢复以及所有相关操作的实际执行。
这一模型在当前仓库的 API 定义中有非常清晰的体现。pkg/apis/velero/v1/目录下定义了全部 Velero 核心资源类型:
- backup_types.go:
Backup资源,其BackupSpec是备份请求的完整规范; - schedule_types.go:
Schedule资源,通过 Cron 表达式周期性触发备份; - restore_types.go:
Restore资源,描述从哪个备份恢复、恢复哪些对象; - backupstoragelocation_types.go:
BackupStorageLocation(BSL),定义备份数据的存储位置。
由于操作对象是标准 Kubernetes 资源,用户既可以通过 Velero CLI(velero backup create ...)提交请求,也可以直接使用kubectl操作对应的 CRD 对象——两条路径最终都会在 API Server 上创建自定义资源,再由控制器消费。
基于资源模型的另一个重要能力是筛选:你可以备份或恢复集群中的全部对象,也可以按资源类型(type)、命名空间(namespace)和标签(label)精确筛选。对应地,BackupSpec与RestoreSpec中都定义了IncludedNamespaces、ExcludedNamespaces、IncludedResources、ExcludedResources、LabelSelector等字段(见 backup_types.go),这些字段也正是velero backup create/velero restore create命令行中--include-namespaces、--exclude-resources、--selector等参数的直接落点。
从使用场景上看,Velero 主要面向两大类需求:
- 灾难恢复(Disaster Recovery):在集群故障后将整个集群状态恢复到可用的新集群;
- 系统变更前的状态快照:例如在集群升级等系统级操作之前,先对应用状态做一次快照,以便变更失败时快速回退。
按需备份(On-demand Backups)
按需备份是 Velero 最基础的操作,其执行过程包含两步:
- 将复制到的 Kubernetes 对象打包成 tarball 文件,上传到云对象存储(cloud object storage);
- 如果指定了卷快照,则调用云服务商 API,为持久卷(PersistentVolume)制作磁盘快照。
你还可以在备份期间指定hooks(钩子),在特定时机执行自定义命令。典型场景是:在给数据库所在卷拍摄快照之前,先通知数据库把内存中的缓冲区 flush 到磁盘,确保快照数据的一致性。关于 hooks 的完整说明见 site/content/docs/v1.1.0/hooks.md。
需要特别提醒的一点是:集群备份并不是严格原子(atomic)的。如果备份进行期间有 Kubernetes 对象正在被创建或修改,它们可能不会被纳入本次备份。虽然捕获到不一致信息的概率很低,但这种可能性是客观存在的,在要求强一致性的生产场景中需要有所预期。
定时备份(Scheduled Backups)
定时备份由Schedule资源驱动,允许你按固定时间间隔循环备份数据。其行为有两个要点:
- 首次备份在
Schedule创建后立即执行; - 后续备份按 Cron 表达式指定的时间间隔周期性执行。
Cron 表达式定义在ScheduleSpec.Schedule字段中(见 schedule_types.go)。此外ScheduleSpec还支持Paused(暂停调度)、UseOwnerReferencesInBackup(让 Schedule 成为其产生的 Backup 的属主引用)等扩展字段。
由定时备份产生的备份对象遵循统一的命名格式:
<SCHEDULE NAME>-<TIMESTAMP>其中<TIMESTAMP>的格式为YYYYMMDDhhmmss(年 4 位 + 月 2 位 + 日 2 位 + 时 2 位 + 分 2 位 + 秒 2 位)。这一格式直接对应源码中Schedule的TimestampedName方法——它使用20060102150405这个 Go 时间格式模板拼接名称(见 schedule_types.go)。例如名称为daily的 Schedule,在 2026 年 9 月 16 日 07:42:06 触发的备份会命名为daily-20260916074206。
恢复(Restores)
Restore资源支持从先前创建的备份中恢复全部对象和持久卷,也支持只恢复筛选后的对象子集。其核心筛选与映射能力包括:
- 按命名空间、资源类型、标签筛选:与备份一致,
RestoreSpec提供IncludedNamespaces、IncludedResources、LabelSelector等字段(见 restore_types.go); - 多命名空间重映射(Namespace Remapping):
NamespaceMapping字段是一个源命名空间到目标命名空间的映射表。例如,在单次恢复中,可以把命名空间abc中的对象重建到命名空间def,同时把123中的对象重建到456(见 restore_types.go)。这一能力对跨集群迁移和同名冲突规避非常实用; - 从 Schedule 恢复:当
BackupName为空而指定了ScheduleName时,Velero 会从该 Schedule 最近一次成功的备份进行恢复。
恢复对象的默认命名格式为:
<BACKUP NAME>-<TIMESTAMP>其中<TIMESTAMP>同样为YYYYMMDDhhmmss格式,你也可以指定自定义名称。此外,被恢复的对象会自动带上一个标签,其键为velero.io/restore-name、值为<RESTORE NAME>。这一标签常量定义于 labels_annotations.go,可用于后续检索、审计或区分"本次恢复创建的对象"。
关于存储位置还有一个重要的运维细节:默认情况下,备份存储位置(BackupStorageLocation)以读写模式(read-write)创建。但在恢复场景中,你可以将存储位置配置为只读模式(read-only)——该模式下会禁用此存储位置的备份创建与删除操作,从而确保在恢复期间不会因为误操作而意外创建或删除备份。这一模式由BackupStorageLocationSpec.AccessMode字段控制(见 backupstoragelocation_types.go)。
备份工作流:从 CLI 到对象存储的完整链路
当你在命令行执行velero backup create test-backup时,背后发生了以下四个关键步骤:
- 提交 Backup 对象:Velero 客户端调用 Kubernetes API Server,创建一个
Backup自定义资源; - 控制器校验:
BackupController监听(watch)到新的Backup对象后,对其进行校验; - 收集数据:
BackupController开始备份流程,通过查询 API Server 收集需要备份的资源数据; - 上传存储:
BackupController调用对象存储服务(例如 AWS S3)上传备份文件。
整个流程对应下图:
图片左侧展示了用户通过 Velero CLI 提交velero backup create test-backup --snapshot-volumes请求;中间部分是BackupController通过 Kubernetes API 监听/查询资源;右侧则是与云服务商(cloud provider)交互,完成备份文件上传与磁盘快照创建。
在控制器实现层面,pkg/controller/backup_controller.go中定义的backupReconciler承担了监听、校验和执行备份的核心职责,其resyncBackupMetrics等辅助逻辑(见 backup_controller.go)还负责在控制器重同步时校正备份指标。
关于卷快照,默认情况下velero backup create会为备份中包含的持久卷制作磁盘快照;你可以通过附加标志调整行为。运行velero backup create --help可查看全部可用标志。其中最常用的一个参数是:
velero backup create test-backup --snapshot-volumes=false即显式关闭卷快照——适合只想备份 Kubernetes 对象元数据、不需要复制卷数据的场景。该开关在BackupSpec.SnapshotVolumes字段中有直接对应(见 backup_types.go)。
备份使用的 API 版本(Backed-up API Versions)
Velero 在备份资源时,使用 Kubernetes API Server 对每个 group/resource 的**首选版本(preferred version)**进行采集。相应地,在目标集群恢复该资源时,相同的 API group/version 必须存在,恢复才能成功。
官方文档给出了一个非常直观的例子:假设被备份的集群中存在thingsAPI group 下的gizmos资源,其 group/version 依次为things/v1alpha1、things/v1beta1和things/v1,而服务端首选版本是things/v1,那么所有gizmos对象都会从things/v1端点被备份。当从这个集群的备份进行恢复时,目标集群必须具备things/v1端点才能成功恢复gizmos。注意:things/v1不需要是目标集群的首选版本,它只需存在即可。
这一"按首选版本备份、按存在版本恢复"的语义,决定了跨集群迁移(尤其是源集群与目标集群 Kubernetes 版本或 API 演进进度不一致)时必须提前核对目标集群的 API 支持情况。
设置备份过期时间(TTL)
创建备份时,可以通过--ttl <DURATION>标志指定备份的保留时长。一旦 Velero 发现某个已存在的备份资源过期,它会自动清理与该备份关联的以下全部内容:
Backup资源本身;- 云对象存储中的备份文件;
- 所有 PersistentVolume 快照;
- 所有关联的
Restore资源。
TTL字段类型为metav1.Duration,即一个可被time.Duration解析的字符串(见 backup_types.go),例如720h(30 天)。TTL 机制的工程意义在于:它让备份生命周期管理完全自动化——无需人工定时清理过期备份,存储成本也会被控制在合理范围内。
对象存储同步(Object Storage Sync):以对象存储为唯一事实来源
Velero 的一个核心理念是:对象存储(object storage)是唯一事实来源(source of truth)。Velero 会持续检查存储桶,确保正确的备份资源始终存在于 Kubernetes 集群中:
- 如果存储桶中存在格式正确的备份文件,但 Kubernetes API 中没有对应的
Backup资源,Velero 会将信息从对象存储同步到 Kubernetes; - 反之,如果
Backup对象存在于 Kubernetes 但对应的备份 tarball 已不在对象存储中,则该Backup对象会从 Kubernetes 中被删除。
这一机制的实现主体是pkg/controller/backup_sync_controller.go中的backupSyncReconciler(见 backup_sync_controller.go),它会周期性扫描对象存储并反哺集群内的备份资源视图。
对象存储同步带来的直接价值是:在集群迁移场景下,恢复功能依然可用——即便新集群中不存在原始的备份对象,只要对象存储中仍有备份文件,Velero 就能自动重建对应的Backup资源,随后执行恢复。这构成了跨集群迁移与灾难恢复的数据基础。
补充一点:对象存储同步的频率等行为由BackupStorageLocationSpec中的BackupSyncPeriod(定义对象存储到 API 的同步周期,设为 0 可禁用同步)与ValidationFrequency(定义存储位置校验周期)控制(见 backupstoragelocation_types.go),这两个字段支持细粒度运维调优。
实践要点小结
- 操作即资源:备份、定时备份、恢复都是 CRD + 控制器模式,既可用
veleroCLI 操作,也可直接使用kubectl管理对应自定义资源; - 筛选三要素:类型(resource)、命名空间(namespace)、标签(label)组合出灵活的备份/恢复边界;恢复阶段还支持多命名空间重映射;
- 备份非原子:对一致性有强要求的应用,建议结合 hooks 在快照前完成数据 flush;
- 快照默认开启:不需要卷数据时记得用
--snapshot-volumes=false关闭,节省成本; - TTL 自动化清理:为每个备份设置合理 TTL,避免过期数据长期占用存储;
- 对象存储即真相:备份文件在对象存储中的存在与否,直接决定
Backup资源能否在集群中存活,理解这一点对设计灾备与迁移方案至关重要。
若需要进一步了解实际部署步骤(安装、存储位置配置、首次备份演练),可继续阅读同目录下的 install-overview.md、locations.md 与 get-started.md。
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考