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 快照支持前,集群需满足以下条件:
- 集群 Kubernetes 版本 ≥ 1.20,该版本起 Volume Snapshot 特性在 v1 API 层面 GA。
- 集群运行中的 CSI 驱动需支持 v1 API 级别的卷快照。
- 跨集群恢复时,目标集群中 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,它提供了IsEnabled、Enable、Disable、All、Serialize等接口,用于在 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 插件在实现上做了若干关键设计决策,直接决定了备份删除与过期时的行为:
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)。清理悬空(dangling)的 VolumeSnapshotContent。备份过程中产生的、尚未绑定到任何 VolumeSnapshot 对象的 VolumeSnapshotContent,会在备份删除时通过标签发现并删除,避免残留孤儿资源。
VolumeSnapshot 对象会在备份上传到对象存储后被从集群中移除。这样,当
DeletionPolicy为Delete时,被备份的命名空间可以安全删除,而不会误删存储提供商中的快照(因为快照的真实数据由 VolumeSnapshotContent 管理)。VolumeSnapshotContent 的
DeletionPolicy与创建它的 VolumeSnapshotClass 一致。在 VolumeSnapshotClass 上设置DeletionPolicy: Retain,可在 Velero 备份的整个生命周期内保留存储系统中的卷快照;即使发生灾难导致包含 VolumeSnapshot 对象的命名空间丢失,也不会删除存储系统中的快照。备份过期时的空间释放。当 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)实现了完整的优先级选择链路,依次为:
- PVC 注解指定的 VolumeSnapshotClass(优先级最高);
- 卷策略(Volume Policy)中
snapshotClass参数指定的 VolumeSnapshotClass; - 备份/计划注解指定的 VolumeSnapshotClass;
- 默认行为:按标签或 Kubernetes 默认类注解选择,作为兜底。
其中相关的标签与注解键在仓库中被集中定义(见 pkg/apis/velero/v1/labels_annotations.go):
| 常量 | 键名 | 用途 |
|---|---|---|
VolumeSnapshotClassSelectorLabel | velero.io/csi-volumesnapshot-class | 标记某 VolumeSnapshotClass 为某驱动类型的默认类 |
VolumeSnapshotClassDriverBackupAnnotationPrefix | velero.io/csi-volumesnapshot-class | 备份/计划注解前缀,与驱动名拼接 |
VolumeSnapshotClassDriverPVCAnnotation | velero.io/csi-volumesnapshot-class | PVC 注解,指定该 PVC 使用的类 |
VolumeSnapshotClassKubernetesAnnotation | snapshot.storage.kubernetes.io/is-default-class | Kubernetes 原生默认类注解,作为兜底选择依据 |
默认行为:为驱动打上 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)按如下顺序兜底:
- 优先返回驱动名匹配且带
velero.io/csi-volumesnapshot-class标签的类; - 其次返回驱动名匹配且带
snapshot.storage.kubernetes.io/is-default-class注解的类; - 若该驱动下只有一个 VolumeSnapshotClass,直接返回它;
- 否则返回错误,提示用户为期望的类加上标签或注解。
仓库的 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。
备份阶段
- 当 BackupItemAction 发现 PVC 指向由 CSI 驱动支持的 PersistentVolume 时,插件会按上文的选择策略找到同驱动名、带
velero.io/csi-volumesnapshot-class标签(或注解指定)的 VolumeSnapshotClass,以该 PVC 为源创建 CSI VolumeSnapshot 对象。该 VolumeSnapshot 与被用作源的 PVC 位于同一命名空间。 - 随后,CSI external-snapshotter 控制器观察到 VolumeSnapshot,创建集群范围的 VolumeSnapshotContent 对象,指向存储系统中真实存在的磁盘快照。external-snapshotter 插件调用 CSI 驱动的快照方法,驱动再调用存储系统 API 生成快照。
- 当快照 ID 生成且存储系统将快照标记为可用于恢复后,VolumeSnapshotContent 的
status.snapshotHandle被写入、status.readyToUse字段被置位。仓库中WaitUntilVSCHandleIsReady正是等待 VolumeSnapshotContent 出现 snapshot handle 的实现(见 pkg/util/csi/volume_snapshot.go)。 - Velero 将生成的 VolumeSnapshot 与 VolumeSnapshotContent 对象一并打包进备份 tarball,同时把所有 VolumeSnapshot 与 VolumeSnapshotContent 对象以 JSON 文件形式上传到对象存储。
关键理解:上传到对象存储的只有 Kubernetes 对象(元数据),不包含快照中的实际数据。真正的卷数据快照存放在存储提供商系统中,由 VolumeSnapshotContent 引用。
- 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-class或snapshot.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),仅供参考