Velero CSI 快照支持完全指南:启用 EnableCSI 特性、VolumeSnapshotClass 选择策略与备份恢复原理
2026/9/17 17:52:33 网站建设 项目流程

Velero CSI 快照支持完全指南:启用 EnableCSI 特性、VolumeSnapshotClass 选择策略与备份恢复原理

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

导读

本文以 Velero(Kubernetes 应用及其持久化卷的备份与迁移工具)官方 v1.12 文档《Container Storage Interface Snapshot Support in Velero》为主体,系统讲解如何借助 Kubernetes CSI Snapshot API 为 CSI 驱动的卷提供备份与恢复能力。读完本文,你将掌握:CSI 支持的前提条件与安装方法、VolumeSnapshotClass 的三级选择策略(默认标签、备份/计划注解、PVC 注解)、CSI 快照备份恢复的完整工作原理,以及 Velero 对快照生命周期(创建、保留、过期清理)的管理细节。

什么是 Velero 的 CSI 快照支持

将 CSI(Container Storage Interface)快照支持集成进 Velero,使 Velero 能够通过 Kubernetes CSI Snapshot API 对 CSI 卷执行备份与恢复。这一机制的核心价值在于:只要卷的存储后端提供了 CSI 驱动,Velero 就能为其创建快照,无需为每个存储提供商单独编写 Velero 专属插件

在 Velero 仓库中,EnableCSI特性标志被定义为常量CSIFeatureFlag = "EnableCSI"(见 pkg/apis/velero/v1/constants.go),整个 CSI 支持能力均围绕该特性标志展开。

使用前提(Prerequisites)

在启用 CSI 快照支持前,集群需满足以下条件:

  1. 集群 Kubernetes 版本 ≥ 1.20,该版本起 Volume Snapshot 特性在 v1 API 层面 GA。
  2. 集群运行中的 CSI 驱动需支持 v1 API 级别的卷快照
  3. 跨集群恢复时,目标集群中 CSI 驱动的名称必须与源集群一致,这是保证 CSI VolumeSnapshot 跨集群可移植性的前提。

关于快照持久性的重要提示:并非所有云厂商的 CSI 驱动都保证快照的持久性——VolumeSnapshot 与 VolumeSnapshotContent 对象可能存放在与原始 PersistentVolume 相同的对象存储系统中,存在数据丢失风险。请查阅云厂商文档确认快照持久化配置。自 velero-plugin-for-csi v0.3.0 起,Velero 官方团队为 AWS 与 Azure 驱动的 CSI 插件提供正式支持。

安装启用 CSI 支持

将 Velero 与 CSI 卷快照 API 集成,需要做两件事:启用EnableCSI特性标志,以及在 Velero 服务端安装 CSI 插件velero-plugin-for-csi)。两者均可通过velero install一条命令完成:

velero install \ --features=EnableCSI \ --plugins=<object storage plugin>,velero/velero-plugin-for-csi:v0.6.0 \ ...

其中:

  • <object storage plugin>需替换为你使用的对象存储插件镜像(如 AWS、Azure、GCP 的 Velero 插件);
  • velero/velero-plugin-for-csi:v0.6.0为 CSI 插件镜像,用于在备份/恢复过程中创建和管理 CSI VolumeSnapshot;
  • --features=EnableCSI会把特性标志写入 Velero Deployment 与 node-agent DaemonSet(若启用)的启动参数。仓库安装代码中该参数被定义为“逗号分隔的 Velero 特性标志列表”(见 pkg/cmd/cli/install/install.go)。

若希望在velero backup describe的输出中包含与备份关联的 CSI 对象状态,还需在客户端侧启用该特性:

velero client config set features=EnableCSI

服务端与客户端侧的特性标志管理机制对应仓库中的 pkg/features/feature_flags.go,它提供了IsEnabledEnableDisableAllSerialize等接口,用于在 Velero 各组件中统一查询与设置特性开关。

补充说明(仓库实现证据):当EnableCSI特性未开启时,即使安装了 CSI 插件,其 BackupItemAction/RestoreItemAction 也会被 Velero 引擎主动跳过。相关逻辑见 pkg/backup/item_backupper.go(“If the EnableCSI feature is not enabled, but the executing action is from CSI plugin, skip the action”)与 pkg/restore/restore.go。

实现选择:快照生命周期与清理策略

Velero CSI 插件在实现上做了若干关键设计决策,直接决定了备份删除与过期时的行为:

  1. VolumeSnapshot 仅存活于备份生命周期内。即使 VolumeSnapshotClass 的DeletionPolicy设为Retain,由 Velero CSI 插件创建的 VolumeSnapshot 也只在备份存续期间保留。实现上,删除备份时(删除 VolumeSnapshot 之前),插件会先把 VolumeSnapshotContent 的DeletionPolicy补丁(patch)为Delete,随后删除 VolumeSnapshot 对象,从而级联删除 VolumeSnapshotContent 及存储提供商侧的实际快照。仓库中的SetVolumeSnapshotContentDeletionPolicy函数正是通过客户端 Patch 方式修改 VSC 的Spec.DeletionPolicy(见 pkg/util/csi/volume_snapshot.go)。

  2. 清理悬空(dangling)的 VolumeSnapshotContent。备份过程中产生的、尚未绑定到任何 VolumeSnapshot 对象的 VolumeSnapshotContent,会在备份删除时通过标签发现并删除,避免残留孤儿资源。

  3. VolumeSnapshot 对象会在备份上传到对象存储后被从集群中移除。这样,当DeletionPolicyDelete时,被备份的命名空间可以安全删除,而不会误删存储提供商中的快照(因为快照的真实数据由 VolumeSnapshotContent 管理)。

  4. VolumeSnapshotContent 的DeletionPolicy与创建它的 VolumeSnapshotClass 一致。在 VolumeSnapshotClass 上设置DeletionPolicy: Retain,可在 Velero 备份的整个生命周期内保留存储系统中的卷快照;即使发生灾难导致包含 VolumeSnapshot 对象的命名空间丢失,也不会删除存储系统中的快照。

  5. 备份过期时的空间释放。当 Velero 备份过期时,VolumeSnapshot 对象被删除,同时 VolumeSnapshotContent 被更新为DeletionPolicy: Delete,以释放存储系统空间。

仓库中还提供了RetainVSC(将 VSC 的删除策略改为 Retain)、EnsureDeleteVS/EnsureDeleteVSC(删除并等待对象消失)、DeleteVolumeSnapshotIfAny/DeleteVolumeSnapshotContentIfAny(若存在则删除)等工具函数,完整支撑上述生命周期管理逻辑(见 pkg/util/csi/volume_snapshot.go)。此外,CleanupVolumeSnapshot在删除 VS 前会将关联 VSC 的删除策略置为Delete,确保物理快照一并清理(见 pkg/util/csi/volume_snapshot.go)。

VolumeSnapshotClass 的选择策略

对 CSI 卷执行备份时,Velero CSI 插件需要从集群中选择合适的 VolumeSnapshotClass。仓库中的GetVolumeSnapshotClass函数(见 pkg/util/csi/volume_snapshot.go)实现了完整的优先级选择链路,依次为:

  1. PVC 注解指定的 VolumeSnapshotClass(优先级最高);
  2. 卷策略(Volume Policy)中snapshotClass参数指定的 VolumeSnapshotClass
  3. 备份/计划注解指定的 VolumeSnapshotClass
  4. 默认行为:按标签或 Kubernetes 默认类注解选择,作为兜底。

其中相关的标签与注解键在仓库中被集中定义(见 pkg/apis/velero/v1/labels_annotations.go):

常量键名用途
VolumeSnapshotClassSelectorLabelvelero.io/csi-volumesnapshot-class标记某 VolumeSnapshotClass 为某驱动类型的默认类
VolumeSnapshotClassDriverBackupAnnotationPrefixvelero.io/csi-volumesnapshot-class备份/计划注解前缀,与驱动名拼接
VolumeSnapshotClassDriverPVCAnnotationvelero.io/csi-volumesnapshot-classPVC 注解,指定该 PVC 使用的类
VolumeSnapshotClassKubernetesAnnotationsnapshot.storage.kubernetes.io/is-default-classKubernetes 原生默认类注解,作为兜底选择依据

默认行为:为驱动打上 Velero 默认标签

最直接的做法是:为某个驱动创建 VolumeSnapshotClass,并打上标签velero.io/csi-volumesnapshot-class: "true",表明它是该驱动的默认 VolumeSnapshotClass。例如为 CSI 驱动disk.csi.cloud.com创建默认快照类:

apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: test-snapclass labels: velero.io/csi-volumesnapshot-class: "true" driver: disk.csi.cloud.com

注意:对于每种驱动类型,集群中只能存在1 个velero.io/csi-volumesnapshot-class: "true"标签的 VolumeSnapshotClass。

仓库中的默认选择实现GetVolumeSnapshotClassForStorageClass(见 pkg/util/csi/volume_snapshot.go)按如下顺序兜底:

  1. 优先返回驱动名匹配且带velero.io/csi-volumesnapshot-class标签的类;
  2. 其次返回驱动名匹配且带snapshot.storage.kubernetes.io/is-default-class注解的类;
  3. 若该驱动下只有一个 VolumeSnapshotClass,直接返回它;
  4. 否则返回错误,提示用户为期望的类加上标签或注解。

仓库的 e2e 测试样例验证了这两种标记方式:AWS 样例仅使用velero.io/csi-volumesnapshot-class: "true"标签(test/testdata/volume-snapshot-class/aws.yaml),而 vSphere 样例同时使用标签与snapshot.storage.kubernetes.io/is-default-class: "true"注解(test/testdata/volume-snapshot-class/vsphere.yaml)。

为特定备份或计划指定 VolumeSnapshotClass

当集群中同一驱动存在多个 VolumeSnapshotClass,而你想为某个备份或计划使用特定类时,可在备份/计划对象上加注解,格式为:

velero.io/csi-volumesnapshot-class_<driver name> = <VolumeSnapshotClass Name>

例如,为备份指定disk.csi.cloud.com驱动使用test-snapclass

apiVersion: velero.io/v1 kind: Backup metadata: name: test-backup annotations: velero.io/csi-volumesnapshot-class_disk.csi.cloud.com: "test-snapclass" spec: includedNamespaces: - default

注意:注解必须全部使用小写,且严格遵循velero.io/csi-volumesnapshot-class_<driver name> = <VolumeSnapshotClass Name>格式。仓库实现中,注解键通过fmt.Sprintf("%s_%s", 前缀, strings.ToLower(provisioner))拼接而成(见 pkg/util/csi/volume_snapshot.go),并会校验所指定的类是否确实属于该驱动。

为特定 PVC 指定 VolumeSnapshotClass

若只想让某个特定 PVC 使用特定快照类(例如对存储敏感数据的 PVC 使用启用加密参数的类),可在 PVC 上加注解velero.io/csi-volumesnapshot-class,其优先级高于备份或计划上的注解:

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc annotations: velero.io/csi-volumesnapshot-class: "test-snapclass" spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: disk.csi.cloud.com

仓库实现GetVolumeSnapshotClassFromPVCAnnotationsForDriver(见 pkg/util/csi/volume_snapshot.go)会校验注解指定的类名是否真实存在且驱动匹配,否则返回错误。

这一“多 VolumeSnapshotClass 支持”设计源于仓库中的设计文档 design/Implemented/multiple-csi-volumesnapshotclass-support.md,它提出的典型场景包括:同一驱动在不同 Azure 资源组存放快照以便分团队管理、对敏感数据 PVC 使用带加密参数的快照类等。

工作原理总览

Velero 的 CSI 支持不依赖 Velero 传统的 VolumeSnapshotter 插件接口,而是采用一组 BackupItemAction 插件,首先作用于 PersistentVolumeClaim。

备份阶段

  1. 当 BackupItemAction 发现 PVC 指向由 CSI 驱动支持的 PersistentVolume 时,插件会按上文的选择策略找到同驱动名、带velero.io/csi-volumesnapshot-class标签(或注解指定)的 VolumeSnapshotClass,以该 PVC 为源创建 CSI VolumeSnapshot 对象。该 VolumeSnapshot 与被用作源的 PVC 位于同一命名空间
  2. 随后,CSI external-snapshotter 控制器观察到 VolumeSnapshot,创建集群范围的 VolumeSnapshotContent 对象,指向存储系统中真实存在的磁盘快照。external-snapshotter 插件调用 CSI 驱动的快照方法,驱动再调用存储系统 API 生成快照。
  3. 当快照 ID 生成且存储系统将快照标记为可用于恢复后,VolumeSnapshotContent 的status.snapshotHandle被写入、status.readyToUse字段被置位。仓库中WaitUntilVSCHandleIsReady正是等待 VolumeSnapshotContent 出现 snapshot handle 的实现(见 pkg/util/csi/volume_snapshot.go)。
  4. Velero 将生成的 VolumeSnapshot 与 VolumeSnapshotContent 对象一并打包进备份 tarball,同时把所有 VolumeSnapshot 与 VolumeSnapshotContent 对象以 JSON 文件形式上传到对象存储。

关键理解:上传到对象存储的只有 Kubernetes 对象(元数据),不包含快照中的实际数据。真正的卷数据快照存放在存储提供商系统中,由 VolumeSnapshotContent 引用。

  1. VolumeSnapshot 对象会在备份上传完成后被从集群移除(如前文“实现选择”第 3 点所述)。

同步与跨集群场景

Velero 将备份同步到新集群时,VolumeSnapshotContent 对象以及用于创建快照的 VolumeSnapshotClass 会一并同步进集群,从而使 Velero 能够正确管理备份过期与清理。

恢复阶段

从仓库源码看,恢复时 Velero 会检查 PV 是否关联 CSI VolumeSnapshot:hasCSIVolumeSnapshot会遍历恢复上下文中的csiVolumeSnapshots列表进行判断(见 pkg/restore/restore.go)。当 PV 带有 CSI VolumeSnapshot 时,Velero 会走“动态重新供应(Dynamically re-provisioning)持久卷”的路径,利用备份中携带的 VolumeSnapshot 信息创建新的 PV/PVC 并绑定到存储系统中的快照(见 pkg/restore/restore.go)。

过期与清理

备份过期时(前文已述):VolumeSnapshot 对象被删除,VolumeSnapshotContent 被更新为DeletionPolicy: Delete以释放存储空间;若快照类配置为Retain,则存储系统中的快照在备份生命周期内始终保留,为灾难恢复场景提供保障。

与其他云厂商插件的边界说明

AWS、Microsoft Azure、GCP 的 Velero 云插件(版本 ≥ 1.4)无需安装 Velero CSI 插件,即可通过云厂商自身的 API 对由 CSI 驱动供应的持久卷执行快照与恢复。具体支持的 CSI 驱动范围请以各云插件仓库的文档为准。也就是说,CSI 插件路径主要面向其他(非上述三大云厂商)或自建存储后端。

总结

  • 启用方式velero install --features=EnableCSI --plugins=<object storage plugin>,velero/velero-plugin-for-csi:v0.6.0,并用velero client config set features=EnableCSI开启客户端描述输出。
  • 前提条件:Kubernetes ≥ 1.20、CSI 驱动支持 v1 快照 API、跨集群恢复时驱动名一致。
  • 类选择优先级:PVC 注解 → 卷策略 → 备份/计划注解 → 默认标签/注解(velero.io/csi-volumesnapshot-classsnapshot.storage.kubernetes.io/is-default-class)。
  • 生命周期策略:VolumeSnapshot 只存活于备份期间;备份过期时 VSC 的DeletionPolicy被改为Delete以释放存储;Retain策略可保障灾难场景下快照不丢失。
  • 数据边界:对象存储只保存 Kubernetes 快照对象元数据,真实卷数据快照由存储提供商系统持有。

关于每个插件更详细的实现机制,可进一步查阅 CSI 插件仓库的文档;相关的标签/注解常量和工具函数定义则集中在 pkg/apis/velero/v1/labels_annotations.go 与 pkg/util/csi/volume_snapshot.go。

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询