Kubernetes 1.32:卷组快照进入 Beta 阶段

卷组快照作为 Alpha 功能随 Kubernetes 1.27 版本引入。Kubernetes v1.32 最近的版本将该支持移至Beta阶段。卷组快照的支持依赖于一组用于组快照的扩展 API。这些 API 允许用户对一组卷进行崩溃一致性快照。在幕后,Kubernetes 使用标签选择器对多个 PersistentVolumeClaims 进行分组以创建快照。一个关键目标是允许你将这组快照恢复到新的卷中,并基于崩溃一致性恢复点恢复你的工作负载。

这项新功能仅支持CSI卷驱动程序。

卷组快照概述

一些存储系统提供了创建多个卷的崩溃一致性快照的能力。组快照表示对多个卷在同一时间点创建的副本。组快照可以用于创建新的卷(预填充快照数据)或将现有卷恢复到之前的状态(由快照表示)。

为什么要将卷组快照添加到 Kubernetes?

Kubernetes 卷插件系统已经提供了一个强大的抽象,自动化了块存储和文件存储的供应、附加、挂载、调整大小和快照功能。

支持所有这些功能的是 Kubernetes 工作负载可移植性的目标:Kubernetes 旨在在分布式应用和底层集群之间创建一个抽象层,以便应用可以不关心其运行集群的具体细节,且应用部署不需要集群特定知识。

已有一个VolumeSnapshot API,它提供了对持久卷创建快照的能力,以防止数据丢失或数据损坏。然而,还有一些快照功能未被 VolumeSnapshot API 覆盖。

一些存储系统支持一致性组快照,允许在同一时间点对多个卷进行快照以实现写入顺序一致性。这对于包含多个卷的应用非常有用。例如,一个应用可能将数据存储在一个卷中,将日志存储在另一个卷中。如果数据卷和日志卷的快照在不同时间创建,那么当发生灾难时,如果从这些快照恢复,应用将无法保持一致性,也无法正常工作。

确实,你可以先静默应用,然后依次对应用中的每个卷创建单独的快照,并在所有单独快照创建完成后解除应用静默。这样,你将获得应用一致性快照。

然而,有时应用静默会非常耗时,以至于你希望减少静默频率,或者根本不可能静默应用。例如,用户可能希望每周进行一次应用静默的备份,而每晚进行一次不静默应用但具有一致性组支持的备份,后者可以为组中的所有卷提供崩溃一致性。

Kubernetes 卷组快照 API

Kubernetes 对卷组快照的支持依赖于用于管理快照的三种 API 类型

VolumeGroupSnapshot
由 Kubernetes 用户(或你自己的自动化工具)创建,用于请求为多个持久卷声明创建卷组快照。它包含卷组快照操作的信息,例如创建快照的时间戳以及是否已准备好使用。此对象的创建和删除代表了创建或删除集群资源(一个组快照)的意愿。
VolumeGroupSnapshotContent
由快照控制器为动态创建的 VolumeGroupSnapshot 创建。它包含卷组快照的信息,包括卷组快照 ID。此对象代表集群上已供应的资源(一个组快照)。VolumeGroupSnapshotContent 对象与其创建所对应的 VolumeGroupSnapshot 具有一对一的映射关系。
VolumeGroupSnapshotClass
由集群管理员创建,用于描述如何创建卷组快照,包括驱动程序信息、删除策略等。

这三种 API 类型被定义为CustomResourceDefinitions (CRD)。这些 CRD 必须安装在 Kubernetes 集群中,CSI 驱动程序才能支持卷组快照。

支持卷组快照需要哪些组件

卷组快照在external-snapshotter仓库中实现。实现卷组快照意味着添加或更改了几个组件

  • 为 VolumeGroupSnapshot 和两个支持 API 添加了新的 CustomResourceDefinitions。
  • 卷组快照控制器逻辑被添加到通用快照控制器中。
  • 添加逻辑以便快照程序边车控制器调用 CSI。

卷快照控制器和 CRD 在每个集群中部署一次,而边车(sidecar)与每个 CSI 驱动程序捆绑在一起。

因此,将卷快照控制器和 CRD 作为集群附加组件(addon)部署是有意义的。

Kubernetes 项目建议 Kubernetes 发行版将卷快照控制器和 CRD 作为其 Kubernetes 集群管理过程的一部分进行打包和部署(与任何 CSI 驱动程序无关)。

Beta 版本中有哪些新内容?

  • CSI 规范中的 VolumeGroupSnapshot 功能在v1.11.0 版本中移至 GA。

  • 快照验证 webhook 在 external-snapshotter v8.0.0 中已弃用,现在已被移除。大部分验证 webhook 逻辑已作为验证规则添加到 CRD 中。这些验证规则所需的最低 Kubernetes 版本是 1.25。验证 webhook 中未移至 CRD 的一点是防止为同一个 CSI 驱动程序创建多个默认卷快照类和多个默认卷组快照类。移除验证 webhook 后,当为同一个 CSI 驱动程序存在多个默认卷快照类或多个默认卷组快照类时,动态供应 VolumeSnapshot 或 VolumeGroupSnapshot 仍会引发错误。

  • snapshot-controller 和 CSI 快照程序边车中的 enable-volumegroup-snapshot 标志已被功能门控 (feature gate) 替换。由于 VolumeGroupSnapshot 是一个新 API,该功能移至 Beta,但功能门控默认是禁用的。要使用此功能,请在启动 snapshot-controller 和 CSI 快照程序边车时添加标志 --feature-gates=CSIVolumeGroupSnapshot=true 来启用功能门控。

  • 动态创建 VolumeGroupSnapshot 及其对应的独立 VolumeSnapshot 和 VolumeSnapshotContent 对象的逻辑已从 CSI 快照程序移至通用 snapshot-controller。相应的,新的 RBAC 规则已添加到通用 snapshot-controller 中,并从 CSI 快照程序边车中移除了一些 RBAC 规则。

如何使用 Kubernetes 卷组快照

使用 Kubernetes 创建新的组快照

定义 VolumeGroupSnapshotClass 对象并拥有需要一起创建快照的卷后,你可以通过创建 VolumeGroupSnapshot 对象来请求新的组快照。

组快照的源指定底层组快照应是动态创建的,还是使用预先存在的 VolumeGroupSnapshotContent。

预先存在的 VolumeGroupSnapshotContent 由集群管理员创建。它包含存储系统上真实卷组快照的详细信息,可供集群用户使用。

组快照源中的以下成员之一必须设置。

  • selector - 一个标签查询,用于选择需要一起创建快照的 PersistentVolumeClaims。此选择器将用于匹配添加到 PVC 的标签。
  • volumeGroupSnapshotContentName - 指定表示现有卷组快照的预先存在的 VolumeGroupSnapshotContent 对象的名称。

动态配置卷组快照

在以下示例中,有两个 PVC。

NAME    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      VOLUMEATTRIBUTESCLASS   AGE
pvc-0   Bound    pvc-6e1f7d34-a5c5-4548-b104-01e72c72b9f2   100Mi      RWO            csi-hostpath-sc   <unset>                 2m15s
pvc-1   Bound    pvc-abc640b3-2cc1-4c56-ad0c-4f0f0e636efa   100Mi      RWO            csi-hostpath-sc   <unset>                 2m7s

标记 PVC。

% kubectl label pvc pvc-0 group=myGroup
persistentvolumeclaim/pvc-0 labeled

% kubectl label pvc pvc-1 group=myGroup
persistentvolumeclaim/pvc-1 labeled

对于动态配置,必须设置选择器,以便快照控制器能够找到具有匹配标签的 PVC 并一起进行快照。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshot
metadata:
  name: snapshot-daily-20241217
  namespace: demo-namespace
spec:
  volumeGroupSnapshotClassName: csi-groupSnapclass
  source:
    selector:
      matchLabels:
        group: myGroup

在 VolumeGroupSnapshot spec 中,用户可以指定 VolumeGroupSnapshotClass,其中包含用于创建卷组快照的 CSI 驱动程序信息。动态配置需要 VolumeGroupSnapshotClass。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshotClass
metadata:
  name: csi-groupSnapclass
  annotations:
    kubernetes.io/description: "Example group snapshot class"
driver: example.csi.k8s.io
deletionPolicy: Delete

创建卷组快照后,将创建一个相应的 VolumeGroupSnapshotContent 对象,其中包含指向存储系统资源的 volumeGroupSnapshotHandle。

作为卷组快照创建的一部分,将创建两个单独的卷快照。

NAME                                                                        READYTOUSE   SOURCEPVC   RESTORESIZE   SNAPSHOTCONTENT                                                                AGE
snapshot-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0   true         pvc-0       100Mi         snapcontent-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0   16m
snapshot-da577d76bd2106c410616b346b2e72440f6ec7b12a75156263b989192b78caff   true         pvc-1       100Mi         snapcontent-da577d76bd2106c410616b346b2e72440f6ec7b12a75156263b989192b78caff   16m

使用 Kubernetes 导入现有卷组快照

要将预先存在的卷组快照导入 Kubernetes,还必须导入相应的单独卷快照。

首先识别各个卷快照句柄,手动构建 VolumeSnapshotContent 对象,然后创建指向 VolumeSnapshotContent 对象的 VolumeSnapshot 对象。为每个单独的卷快照重复此操作。

然后手动创建一个 VolumeGroupSnapshotContent 对象,指定存储系统上已有的 volumeGroupSnapshotHandle 和各个 volumeSnapshotHandle。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshotContent
metadata:
  name: static-group-content
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    groupSnapshotHandles:
      volumeGroupSnapshotHandle: e8779136-a93e-11ef-9549-66940726f2fd
      volumeSnapshotHandles:
      - e8779147-a93e-11ef-9549-66940726f2fd
      - e8783cd0-a93e-11ef-9549-66940726f2fd
  volumeGroupSnapshotRef:
    name: static-group-snapshot
    namespace: demo-namespace

之后创建一个指向 VolumeGroupSnapshotContent 对象的 VolumeGroupSnapshot 对象。

apiVersion: groupsnapshot.storage.k8s.io/v1beta1
kind: VolumeGroupSnapshot
metadata:
  name: static-group-snapshot
  namespace: demo-namespace
spec:
  source:
    volumeGroupSnapshotContentName: static-group-content

如何在 Kubernetes 中使用卷组快照进行恢复

恢复时,用户可以请求从属于 VolumeGroupSnapshot 的 VolumeSnapshot 对象创建新的 PersistentVolumeClaim。这将触发新卷的配置,新卷将预先填充指定快照中的数据。用户应重复此操作,直到从属于卷组快照的所有快照中创建所有卷为止。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: examplepvc-restored-2024-12-17
  namespace: demo-namespace
spec:
  storageClassName: example-foo-nearline
  dataSource:
    name: snapshot-0962a745b2bf930bb385b7b50c9b08af471f1a16780726de19429dd9c94eaca0
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOncePod
  resources:
    requests:
      storage: 100Mi # must be enough storage to fit the existing snapshot

作为存储供应商,如何向我的 CSI 驱动程序添加卷组快照支持?

为了实现卷组快照功能,CSI 驱动程序必须

  • 实现新的组控制器服务。
  • 实现组控制器 RPC:CreateVolumeGroupSnapshotDeleteVolumeGroupSnapshotGetVolumeGroupSnapshot
  • 添加组控制器功能 CREATE_DELETE_GET_VOLUME_GROUP_SNAPSHOT

有关更多详细信息,请参阅 CSI 规范Kubernetes-CSI 驱动程序开发人员指南

如前所述,强烈建议 Kubernetes 分发商将其 Kubernetes 集群管理过程的一部分(独立于任何 CSI 驱动程序)打包和部署卷快照控制器和 CRD。

作为此推荐部署过程的一部分,Kubernetes 团队提供了一些 Sidecar(辅助)容器,其中包括已更新以支持卷组快照的 external-snapshotter Sidecar 容器

external-snapshotter 监视 Kubernetes API 服务器上的 VolumeGroupSnapshotContent 对象,并针对 CSI 端点触发 CreateVolumeGroupSnapshotDeleteVolumeGroupSnapshot 操作。

有哪些限制?

Kubernetes 的卷组快照 beta 实现具有以下限制

  • 不支持将现有 PVC 恢复到快照表示的早期状态(仅支持从快照配置新卷)。
  • 除了存储系统提供的任何保证(例如崩溃一致性)之外,没有应用程序一致性保证。有关应用程序一致性的更多讨论,请参阅此文档

后续计划?

根据反馈和采用情况,Kubernetes 项目计划在未来的版本中将卷组快照实现推向正式发布 (GA)。

我如何了解更多信息?

如何参与?

像所有 Kubernetes 项目一样,本项目是来自不同背景的众多贡献者共同努力的结果。我代表 SIG Storage,衷心感谢在过去几个季度中挺身而出帮助项目达到 beta 阶段的贡献者们。

对于那些有兴趣参与 CSI 或 Kubernetes 存储系统任何部分的设计和开发的人,请加入Kubernetes 存储特别兴趣小组 (SIG)。我们始终欢迎新的贡献者。

我们还定期举行 数据保护工作组会议。欢迎新成员加入我们的讨论。