ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Velero 卷快照插件备份/恢复进度报告机制设计解析(VolumePluginBackup/VolumePluginRestore CR)

Velero 卷快照插件备份/恢复进度报告机制设计解析(VolumePluginBackup/VolumePluginRestore CR) Velero 卷快照插件备份/恢复进度报告机制设计解析VolumePluginBackup/VolumePluginRestore CR【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero导读本文基于 Velero 仓库中的设计文档 plugin-backup-and-restore-progress-design.md系统梳理 Velero 为卷快照volume snapshotter插件制定的备份/恢复进度上报机制通过新增VolumePluginBackup与VolumePluginRestore两类自定义资源CR让不同云厂商插件以统一、可选的方式向用户暴露备份与恢复操作的真实进度。读完本文你将掌握该机制的两套候选设计方案Approach 1 将现有volume.Snapshot结构体升级为 CRApproach 2 由插件自主创建 CR、CR 的完整字段语义、标签定位规则、持久化与跨集群同步链路以及向后兼容、删除策略、备选方案和安全边界等实现细节。问题背景卷快照操作为何不可见Velero 此前已经为 restic/kopia 这类文件级备份/恢复提供了进度可见性用户能够了解操作的大致规模如需要处理的字节总量、操作处于进行中还是已挂起hung等状态。然而由卷快照插件volume snapshotter处理的备份/恢复操作用户很难获知进度主要痛点包括各插件进度信息不统一每个插件可能有各自的进度查询方式但彼此之间没有统一约定恢复时拿不到备份信息即使插件能提供备份进度信息这些信息在目标集群执行恢复操作时也无法传递过去必须可选用部分插件可能根本没有提供进度信息的能力因此该机制不能是强制性的。设计文档因此提出一套插件需遵循的进度上报约定目标是为卷快照插件执行的备份/恢复操作提供统一的可见性Provide uniform way of visibility into backup/restore operations performed by volume snapshotters。注意插件本身的具体实现不在本设计的目标范围内Non Goals。核心设计思路把进度写入专用 CR高层设计非常简洁、与 Velero 既有的PodVolumeBackup/PodVolumeRestore模式一脉相承备份进度由卷快照插件在与该备份操作对应的VolumePluginBackupCR 中持续更新进度恢复进度由卷快照插件在与该恢复操作对应的VolumePluginRestoreCR 中持续更新进度。进度信息以字节数为单位表达Progress字段由VolumeOperationProgress结构体承载包含TotalBytes卷/快照总字节数与BytesDone已完成字节数两个字段。用户通过读取 CR 即可知晓当前备份/恢复的完成度。Approach 1将 volume.Snapshot 升级为 CR方案一的核心判断是现有volume包中的SnapshotGo 结构体已经包含了卷快照备份操作的大部分细节但它有两个缺陷——该结构体在常规时间间隔内不会被同步到其他集群仅在恢复操作期间才会被同步且 Velero CLI 只展示其中的部分内容。因此方案一的做法是为Snapshot结构体增加进度跟踪相关字段并将其转换为 CR彻底移除volume.Snapshot结构体备份目标中保存的不再是 Go 结构体而是 CR并通过目标集群中的backupSyncController同步到集群。仓库中当前实现的Snapshot结构体见 internal/volume/native_snapshot.go正是设计文档描述的演进起点SnapshotSpec含BackupName、BackupUID、Location、PersistentVolumeName、ProviderVolumeID、VolumeType、VolumeAZ、VolumeIOPS等字段SnapshotStatus含ProviderSnapshotID与PhaseNew/Completed/Failed三种生命周期阶段对应SnapshotPhase常量。VolumePluginBackup CR 的 Spec设计文档在volume.SnapshotSpec的基础上仅新增一个字段ProviderName即得到VolumePluginBackupSpectype VolumePluginBackupSpec struct { // BackupName is the name of the Velero backup this snapshot // is associated with. BackupName string json:backupName // BackupUID is the UID of the Velero backup this snapshot // is associated with. BackupUID string json:backupUID // Location is the name of the VolumeSnapshotLocation where this snapshot is stored. Location string json:location // PersistentVolumeName is the Kubernetes name for the volume. PersistentVolumeName string json:persistentVolumeName // ProviderVolumeID is the providers ID for the volume. ProviderVolumeID string json:providerVolumeID // Provider is the Provider field given in VolumeSnapshotLocation Provider string json:provider // VolumeType is the type of the disk/volume in the cloud provider // API. VolumeType string json:volumeType // VolumeAZ is the where the volume is provisioned // in the cloud provider. VolumeAZ string json:volumeAZ,omitempty // VolumeIOPS is the optional value of provisioned IOPS for the // disk/volume in the cloud provider API. VolumeIOPS *int64 json:volumeIOPS,omitempty }字段语义要点BackupName/BackupUID关联本次快照所属的 Velero 备份Location指向存储该快照的VolumeSnapshotLocationProvider即VolumeSnapshotLocation中给定的 ProviderVolumeType/VolumeAZ/VolumeIOPS描述云厂商侧磁盘/卷的类型、可用区与可选 IOPS 配置。VolumePluginBackup CR 的 Status除前两个字段外volume.SnapshotStatus中新增若干字段后形成VolumePluginBackupStatus进度字段即落在此处type VolumePluginBackupStatus struct { // ProviderSnapshotID is the ID of the snapshot taken in the cloud // provider API of this volume. ProviderSnapshotID string json:providerSnapshotID,omitempty // Phase is the current state of the VolumeSnapshot. Phase SnapshotPhase json:phase,omitempty // PluginSpecific are a map of key-value pairs that plugin want to provide // to user to identify plugin properties related to this backup // optional PluginSpecific map[string]string json:pluginSpecific,omitempty // Message is a message about the volume plugins backups status. // optional Message string json:message,omitempty // StartTimestamp records the time a backup was started. // Separate from CreationTimestamp, since that value changes // on restores. // The servers time is used for StartTimestamps // optional // nullable StartTimestamp *metav1.Time json:startTimestamp,omitempty // CompletionTimestamp records the time a backup was completed. // Completion time is recorded even on failed backups. // Completion time is recorded before uploading the backup object. // The servers time is used for CompletionTimestamps // optional // nullable CompletionTimestamp *metav1.Time json:completionTimestamp,omitempty // Progress holds the total number of bytes of the volume and the current // number of backed up bytes. This can be used to display progress information // about the backup operation. // optional Progress VolumeOperationProgress json:progress,omitempty } type VolumeOperationProgress struct { TotalBytes int64 BytesDone int64 } type VolumePluginBackup struct { metav1.TypeMeta json:,inline // optional metav1.ObjectMeta json:metadata,omitempty // optional Spec VolumePluginBackupSpec json:spec,omitempty // optional Status VolumePluginBackupStatus json:status,omitempty }设计细节值得注意StartTimestamp与CreationTimestamp分离设计文档明确说明StartTimestamp单独记录备份开始时间因为CreationTimestamp的值在恢复时会变化CompletionTimestamp在失败时也会记录且在备份对象上传之前记录PluginSpecific是一组 key-value 映射允许插件向用户暴露与本备份相关的插件专有属性Phase沿用SnapshotPhase类型New/Completed/Failed与当前 internal/volume/native_snapshot.go 中定义的快照生命周期阶段保持一致。CR 创建时机与标签定位对于每个卷的备份操作Velero 在调用卷快照插件的CreateSnapshotAPI之前创建VolumePluginBackupCR。为便于定位某次备份的某个卷对应的 CR设计文档规定 Velero 为 CR 添加以下标签velero.io/backup-name值为备份名称velero.io/pv-name值为正在执行备份的卷名称。由于备份名称唯一不会出现重复识别 CR 的问题。所有标签值都必须经过GetValidName函数处理仓库实现见 pkg/label/label.go其作用是把输入字符串转换为符合 RFC 1035 DNS Label 规范的合法 Kubernetes 标签值。仓库中已定义对应的标签常量velerov1api.BackupNameLabel velero.io/backup-name见 pkg/apis/velero/v1/labels_annotations.goGetValidName也已用于备份、恢复选择器构造见 pkg/label/label.go。插件侧更新进度若插件支持展示自身操作进度它需要利用CreateSnapshot调用中传入的tags找到与该备份操作对应的VolumePluginBackupCR定期更新该 CR 的进度信息即Status.Progress的TotalBytes/BytesDone。持久化、同步与删除持久化takePVSnapshot仓库中的实际入口见 pkg/backup/item_backupper.go从CreateSnapshot返回后原本把volume.Snapshot加入backupRequest新设计中改为加入 CR并在persistBackup阶段随备份一起持久化到备份存储。跨集群同步恢复集群上的backupSyncController检查备份存储中是否有需要同步的VolumePluginBackupCR并按需同步到集群。这解决了引言中恢复时拿不到备份信息的核心痛点。删除VolumePluginBackup的生命周期与备份存储中的数据一致——当备份被手动删除或因过期被删除时该 CR 也可随之删除。backupDeletionController的processRequest会在调用卷快照插件的DeleteSnapshot之前执行对VolumePluginBackup的删除。向后兼容策略当前volume.Snapshot以backupname-volumesnapshots.json.gz文件的形式保存在备份存储中。为了让VolumePluginBackupCR 替代volume.Snapshot时保持兼容CR 仍以同一文件名backupname-volumesnapshots.json.gz备份。设计文档考虑了恢复侧 Velero 版本与 json.gz 文件格式组合的四种情况恢复侧 Velero 版本备份存储中 json.gz 格式兼容性处理旧版旧格式正常第一类旧版新格式GetBackupVolumeSnapshots解码时应只填充旧版本所需字段保证可用新版旧格式解码后metadata.name为空GetBackupVolumeSnapshots解码旧格式为 CR 可行需改为返回[]VolumePluginBackupSpec调用方同步调整新版新格式正常最后一类若第二类场景在实现中解码失败则需将该 CR 备份到不同的文件新版本代码应先检查旧文件是否存在——存在则走旧逻辑否则检查新文件并走新逻辑。backupSyncController在恢复集群上从备份存储获取backupname-volumesnapshots.json.gz对象并解码为内存中的VolumePluginBackupCR若metadata.name已填充则创建 CR否则不创建文档同时提到也可考虑在集群上创建该 CR。VolumePluginRestore CR对应地恢复侧设计了VolumePluginRestoreCR完整定义如下// VolumePluginRestoreSpec is the specification for a VolumePluginRestore CR. type VolumePluginRestoreSpec struct { // SnapshotID is the identifier for the snapshot of the volume. // This will be used to relate with output in velero describe backup SnapshotID string json:snapshotID // BackupName is the name of the Velero backup from which PV will be // created. BackupName string json:backupName // Provider is the Provider field given in VolumeSnapshotLocation Provider string json:provider // VolumeType is the type of the disk/volume in the cloud provider // API. VolumeType string json:volumeType // VolumeAZ is the where the volume is provisioned // in the cloud provider. VolumeAZ string json:volumeAZ,omitempty } // VolumePluginRestoreStatus is the current status of a VolumePluginRestore CR. type VolumePluginRestoreStatus struct { // Phase is the current state of the VolumePluginRestore. Phase string json:phase // VolumeID is the PV name to which restore done VolumeID string json:volumeID // Message is a message about the volume plugins restores status. // optional Message string json:message,omitempty // StartTimestamp records the time a restore was started. // Separate from CreationTimestamp, since that value changes // on restores. // The servers time is used for StartTimestamps // optional // nullable StartTimestamp *metav1.Time json:startTimestamp,omitempty // CompletionTimestamp records the time a restore was completed. // Completion time is recorded even on failed restores. // The servers time is used for CompletionTimestamps // optional // nullable CompletionTimestamp *metav1.Time json:completionTimestamp,omitempty // Progress holds the total number of bytes of the snapshot and the current // number of restored bytes. This can be used to display progress information // about the restore operation. // optional Progress VolumeOperationProgress json:progress,omitempty // PluginSpecific are a map of key-value pairs that plugin want to provide // to user to identify plugin properties related to this restore // optional PluginSpecific map[string]string json:pluginSpecific,omitempty } type VolumePluginRestore struct { metav1.TypeMeta json:,inline // optional metav1.ObjectMeta json:metadata,omitempty // optional Spec VolumePluginRestoreSpec json:spec,omitempty // optional Status VolumePluginRestoreStatus json:status,omitempty }恢复侧的定位标签与备份侧略有不同共三个velero.io/backup-name值为备份名称velero.io/snapshot-id值为需要恢复的快照 IDvelero.io/provider值为VolumeSnapshotLocation中的Provider。同样标签值需经GetValidName规范化。插件通过CreateVolumeFromSnapshotAPI 收到的snapshotID参数及其 Provider 名称即可唯一定位到对应的VolumePluginRestoreCR若支持进度展示则定期更新其恢复进度。生命周期方面Velero 在处理 Restore CR 删除时会一并删除对应的VolumePluginRestoreCR。VolumePluginRestoreStatus中的VolumeID记录恢复完成后的 PV 名称SnapshotID则用于与velero describe backup输出建立关联。Approach 2插件自主创建 CR方案二与方案一仅对备份侧不同恢复侧设计一致。其区别在于 CR 的创建主体与字段设计// VolumePluginBackupSpec is the specification for a VolumePluginBackup CR. type VolumePluginBackupSpec struct { // Volume is the PV name to be backed up. Volume string json:volume // Backup name Backup string json:backup // Provider is the Provider field given in VolumeSnapshotLocation Provider string json:provider } // VolumePluginBackupStatus is the current status of a VolumePluginBackup CR. type VolumePluginBackupStatus struct { // Phase is the current state of the VolumePluginBackup. Phase string json:phase // SnapshotID is the identifier for the snapshot of the volume. // This will be used to relate with output in velero describe backup SnapshotID string json:snapshotID // Message is a message about the volume plugins backups status. // optional Message string json:message,omitempty // StartTimestamp records the time a backup was started. // Separate from CreationTimestamp, since that value changes // on restores. // The servers time is used for StartTimestamps // optional // nullable StartTimestamp *metav1.Time json:startTimestamp,omitempty // CompletionTimestamp records the time a backup was completed. // Completion time is recorded even on failed backups. // Completion time is recorded before uploading the backup object. // The servers time is used for CompletionTimestamps // optional // nullable CompletionTimestamp *metav1.Time json:completionTimestamp,omitempty // PluginSpecific are a map of key-value pairs that plugin want to provide // to user to identify plugin properties related to this backup // optional PluginSpecific map[string]string json:pluginSpecific,omitempty // Progress holds the total number of bytes of the volume and the current // number of backed up bytes. This can be used to display progress information // about the backup operation. // optional Progress VolumeOperationProgress json:progress,omitempty } type VolumeOperationProgress struct { TotalBytes int64 BytesDone int64 } type VolumePluginBackup struct { metav1.TypeMeta json:,inline // optional metav1.ObjectMeta json:metadata,omitempty // optional Spec VolumePluginBackupSpec json:spec,omitempty // optional Status VolumePluginBackupStatus json:status,omitempty }与方案一的差异点Spec 更精简只保留Volume待备份 PV 名、Backup备份名、Provider三个字段而SnapshotID从 Spec 移到了 StatusCR 由插件创建每个卷备份操作由卷快照插件在 Velero 命名空间中创建VolumePluginBackupCR并持续更新进度及卷名、备份名、SnapshotID 等详情标签约定插件需添加velero.io/backup-name与velero.io/volume-name两个标签注意与方案一的velero.io/pv-name不同同样需经GetValidName规范化CR 命名惯例虽然对 CR 名称没有强制限制但作为通用实践插件可用CreateSnapshot的返回值作为 CR 名称。其余机制与方案一一致takePVSnapshot从CreateSnapshot返回后若该卷对应的VolumePluginBackupCR 存在Velero 将其加入backupRequest并在persistBackup时持久化backupSyncController负责跨集群同步backupDeletionController.processRequest在调用DeleteSnapshot前删除 CR。此外方案二提出了另一种删除途径CR 的删除可以委托给插件插件利用DeleteSnapshot请求中传入的snapshotID自行删除VolumePluginBackup。core Velero 客户端/服务端所需变更设计文档列出了核心组件必须完成的改动清单安装时创建VolumePluginBackup/VolumePluginRestore的 CRD备份操作接近尾声时持久化VolumePluginBackupCR备份同步时同步与该备份相关的VolumePluginBackupCR对应backupSyncController职责调用卷快照插件的DeleteSnapshot时删除VolumePluginBackup处理 Restore CR 删除时删除VolumePluginRestore若采用方案一还需将volume.Snapshot结构体转换为 CR 及配套改动在调用卷快照插件 API 之前创建VolumePluginBackup/VolumePluginRestoreCR修改GetBackupVolumeSnapshots及其调用方使其返回类型从[]volume.Snapshot变为[]VolumePluginBackupSpec。从当前仓库源码可以印证相关调用链的真实存在GetBackupVolumeSnapshots在恢复控制器中被用于获取备份的卷快照列表见 pkg/controller/restore_controller.go在备份删除控制器中被用于清理快照见 pkg/controller/backup_deletion_controller.go且原生快照列表在备份时以 gzip 压缩的 JSON 形式编码见 pkg/controller/backup_controller.go——这些正是设计文档所述改动的落点。Velero CLI 所需变更velero describeCLI 将从 API server 拉取相关 CR并在输出中展示其内容例如备份名称、PV 名称若因标签长度限制发生变更则以 CR 内容为准、PV 快照大小即Progress中的字节信息等。API 升级与版本兼容多版本支持CR 升级时Velero 在旧 API 版本被弃用之前仍可继续支持以便识别需要持久化到备份存储的 CR同时优先使用最新的受支持 API 版本同版本新增字段无风险若在不改变 API 版本的前提下新增字段不会引发问题——因为这类资源只用于提供信息不存在对这些资源的调谐reconciliation逻辑新插件配旧版 Velero支持此类 CR 的插件在 CRD 未安装时应优雅处理即能够消化创建/更新 CR 过程中产生的错误不能因此中断备份/恢复主流程。已知限制非 K8s 原生的插件无法实现该机制——因为它们无法创建 CR。设计文档对此有清醒的认知并在备选方案一节讨论了是否值得为此付出更多工程代价。备选方案对比与取舍设计文档明确评估了四个备选方案并给出了最终取舍理由向VolumeSnapshotter接口新增Progress方法由 Velero server 定期轮询该方法并代表插件更新VolumePluginBackupCR。这可以规避插件必须 K8s 原生的限制但改动量大且需要额外的向后兼容机制。鉴于卷插件绝大多数都是 K8s 原生的接受当前限制是合理的直接更新 Backup CR 的 status插件可直接更新 Backup CR 的状态但这样会偏离 Velero 现有用独立 CR 观察操作进度如PodVolumeBackup/PodVolumeRestore的一贯做法用命名约束代替标签要求VolumePluginBackupCR 的名称与CreateSnapshot返回值一致。隐患在于若卷快照插件在返回快照 ID 给 Velero 之前崩溃则无法通过名称定位 CR将 CR 备份到不同的对象若把VolumePluginBackupCR 备份到#backup-volumesnapshots.json.gz之外的其他对象恢复控制器就需要实现回退模式先检查新对象不存在则走旧流程而这种模式易出错。因此设计最终决定将 CR 备份到与volume.Snapshot相同的位置即backupname-volumesnapshots.json.gz。安全考量当前 Velero 的所有组件都运行在同一个veleroservice account 之下因此所有插件拥有宽泛的权限包含修改由其他插件创建的 CR 的能力。这意味着在设计 CR 权限模型时需要考虑插件间的信任边界——这是该机制落地时需要在 RBAC 层面额外关注的安全点。小结VolumePluginBackup/VolumePluginRestoreCR 设计为 Velero 卷快照插件的进度可见性提供了清晰的统一契约以字节级进度TotalBytes/BytesDone为核心配合Phase、Message、StartTimestamp/CompletionTimestamp、PluginSpecific等状态字段借助标签定位、backupSyncController跨集群同步、备份存储持久化与删除控制器联动构建了一条从插件到用户 CLI 的完整进度信息链路。虽然该设计以非 K8s 原生插件无法实现为已知代价但两套候选方案与详尽的兼容性、备选方案分析为后续实现者提供了可以直接落地的技术路线图。【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表