这篇文章发布已超过一年。较旧的文章可能包含过时的内容。请检查页面上的信息自发布以来是否已变得不正确。

为 Kubernetes 引入卷快照 Alpha 版

Kubernetes v1.12 引入了对卷快照的 alpha 支持。此功能允许创建/删除卷快照,并能够使用 Kubernetes API 从快照原生创建新卷。

什么是快照?

许多存储系统(如 Google Cloud Persistent Disks、Amazon Elastic Block Storage 和许多本地存储系统)都能够创建持久卷的“快照”。快照表示卷的时间点副本。快照可用于配置新卷(预先填充快照数据)或将现有卷恢复到之前的状态(由快照表示)。

为什么要向 Kubernetes 添加快照?

Kubernetes 卷插件系统已经提供了一个强大的抽象,可以自动化块存储和文件存储的配置、附加和挂载。

所有这些功能的基础是 Kubernetes 的工作负载可移植性目标:Kubernetes 旨在在分布式系统应用程序和底层集群之间创建一个抽象层,以便应用程序可以忽略其运行的集群的具体细节,并且应用程序部署不需要“特定于集群”的知识。

Kubernetes 存储 SIG 认为快照操作是许多有状态工作负载的关键功能。例如,数据库管理员可能希望在开始数据库操作之前快照数据库卷。

通过在 Kubernetes API 中提供触发快照操作的标准方法,Kubernetes 用户现在可以处理这样的用例,而无需绕过 Kubernetes API(并手动执行特定于存储系统的操作)。

相反,Kubernetes 用户现在可以放心地将快照操作以集群无关的方式纳入他们的工具和策略中,并且知道它可以在任意 Kubernetes 集群上工作,而不管底层存储是什么。

此外,这些 Kubernetes 快照原语充当基本构建块,可解锁为 Kubernetes 开发高级的企业级存储管理功能的能力:例如数据保护、数据复制和数据迁移。

哪些卷插件支持 Kubernetes 快照?

Kubernetes 支持三种类型的卷插件:内置、Flex 和 CSI。有关详细信息,请参阅Kubernetes 卷插件常见问题解答

快照仅支持 CSI 驱动程序(不支持内置或 Flex)。要使用 Kubernetes 快照功能,请确保在集群上部署了实现快照的 CSI 驱动程序。

在本博客发布时,以下 CSI 驱动程序支持快照

其他驱动程序的快照支持正在等待中,应该很快可用。阅读“Kubernetes 的容器存储接口 (CSI) 进入 Beta 版”博客文章,了解有关 CSI 以及如何部署 CSI 驱动程序的更多信息。

Kubernetes 快照 API

与管理 Kubernetes 持久卷的 API 类似,Kubernetes 卷快照引入了三个新的 API 对象来管理快照

  • VolumeSnapshot
    • 由 Kubernetes 用户创建,以请求为指定的卷创建快照。它包含有关快照操作的信息,例如拍摄快照的时间戳以及快照是否可以使用。
    • PersistentVolumeClaim 对象类似,此对象的创建和删除表示用户希望创建或删除集群资源(快照)。
  • VolumeSnapshotContent
    • 由 CSI 卷驱动程序在成功创建快照后创建。它包含有关快照的信息,包括快照 ID。
    • PersistentVolume 对象类似,此对象表示集群上配置的资源(快照)。
    • PersistentVolumeClaimPersistentVolume 对象类似,一旦创建快照,VolumeSnapshotContent 对象就会绑定到为其创建的 VolumeSnapshot(具有一对一的映射)。
  • VolumeSnapshotClass
    • 由集群管理员创建,用于描述应如何创建快照。包括驱动程序信息、访问快照的密钥等。

重要的是要注意,与核心 Kubernetes 持久卷对象不同,这些快照对象被定义为CustomResourceDefinitions (CRD)。Kubernetes 项目正在放弃在 API 服务器中预定义资源类型,并正在转向 API 服务器独立于 API 对象的模型。这允许 API 服务器被 Kubernetes 以外的项目重用,并且使用者(如 Kubernetes)可以简单地安装他们需要的资源类型作为 CRD。

支持快照的CSI 驱动程序将自动安装所需的 CRD。Kubernetes 最终用户只需要验证是否在其 Kubernetes 集群上部署了支持快照的 CSI 驱动程序。

除了这些新对象之外,PersistentVolumeClaim 对象还添加了一个新的 DataSource 字段

type PersistentVolumeClaimSpec struct {
	AccessModes []PersistentVolumeAccessMode
	Selector *metav1.LabelSelector
	Resources ResourceRequirements
	VolumeName string
	StorageClassName *string
	VolumeMode *PersistentVolumeMode
	DataSource *TypedLocalObjectReference
}

这个新的 alpha 字段允许创建新的卷,并使用现有快照中的数据自动预先填充。

Kubernetes 快照要求

在使用 Kubernetes 卷快照之前,您必须

  • 确保在 Kubernetes 集群上部署并运行了实现快照的 CSI 驱动程序。
  • 通过新的 Kubernetes 功能门启用 Kubernetes 卷快照功能(默认情况下,alpha 功能处于禁用状态)
    • 在 API 服务器二进制文件上设置以下标志:--feature-gates=VolumeSnapshotDataSource=true

在创建快照之前,您还需要通过创建 VolumeSnapshotClass 对象并将 snapshotter 字段设置为指向您的 CSI 驱动程序来指定快照的 CSI 驱动程序信息。在下面的 VolumeSnapshotClass 示例中,CSI 驱动程序是 com.example.csi-driver。每个快照配置器至少需要一个 VolumeSnapshotClass 对象。您还可以通过在类定义中放入注释 snapshot.storage.kubernetes.io/is-default-class: "true" 来为每个单独的 CSI 驱动程序设置默认的 VolumeSnapshotClass

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
  name: default-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
snapshotter: com.example.csi-driver


apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
  name: csi-snapclass
snapshotter: com.example.csi-driver
parameters:
  fakeSnapshotOption: foo
  csiSnapshotterSecretName: csi-secret
  csiSnapshotterSecretNamespace: csi-namespace

您必须根据 CSI 驱动程序的文档设置任何必需的不透明参数。如上面的示例所示,参数 fakeSnapshotOption: foo 和任何引用的密钥将在快照创建和删除期间传递给 CSI 驱动程序。默认的 CSI external-snapshotter 保留参数键 csiSnapshotterSecretNamecsiSnapshotterSecretNamespace。如果指定,它会获取密钥并在创建和删除快照时将其传递给 CSI 驱动程序。

最后,在创建快照之前,您必须使用 CSI 驱动程序配置卷,并使用您要快照的某些数据填充它(请参阅有关如何创建和使用 CSI 卷的CSI 博客文章)。

使用 Kubernetes 创建新快照

一旦定义了 VolumeSnapshotClass 对象并且您有一个要快照的卷,您可以通过创建 VolumeSnapshot 对象来创建新快照。

快照的来源指定要从中创建快照的卷。它有两个参数

  • kind - 必须是 PersistentVolumeClaim
  • name - PVC API 对象名称

要快照的卷的命名空间假定与 VolumeSnapshot 对象的命名空间相同。

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-demo
  namespace: demo-namespace
spec:
  snapshotClassName: csi-snapclass
  source:
    name: mypvc
    kind: PersistentVolumeClaim

VolumeSnapshot 规范中,用户可以指定 VolumeSnapshotClass,其中包含有关应使用哪个 CSI 驱动程序来创建快照的信息。创建 VolumeSnapshot 对象时,来自 VolumeSnapshotClass 的参数 fakeSnapshotOption: foo 和任何引用的密钥都将通过 CreateSnapshot 调用传递给 CSI 插件 com.example.csi-driver

作为响应,CSI 驱动程序会触发卷的快照,然后自动创建一个 VolumeSnapshotContent 对象来表示新的快照,并将新的 VolumeSnapshotContent 对象绑定到 VolumeSnapshot,使其可以使用。如果 CSI 驱动程序未能创建快照并返回错误,则快照控制器会在 VolumeSnapshot 对象的状态中报告错误,并且不会重试(这与 Kubernetes 中的其他控制器不同,是为了防止在意外时间拍摄快照)。

如果未指定快照类,则外部快照程序将尝试查找并为快照设置默认快照类。默认快照类中由 snapshotter 指定的 CSI 驱动程序必须与 PVC 存储类中由 provisioner 指定的 CSI 驱动程序匹配。

请注意,Kubernetes 快照的 alpha 版本不提供任何一致性保证。在进行快照以保证数据一致性之前,您必须准备好您的应用程序(暂停应用程序、冻结文件系统等)。

您可以通过运行 kubectl describe volumesnapshot 来验证 VolumeSnapshot 对象是否已创建并与 VolumeSnapshotContent 绑定。

  • Status 下的 Ready 应该设置为 true,以表明此卷快照已准备好使用。
  • Creation Time 字段表示快照实际创建(切割)的时间。
  • Restore Size 字段表示从快照还原卷时所需的最小卷大小。
  • spec 中的 Snapshot Content Name 字段指向为此快照创建的 VolumeSnapshotContent 对象。

使用 Kubernetes 导入现有快照

您始终可以通过手动创建一个 VolumeSnapshotContent 对象来表示现有快照,从而将现有快照导入 Kubernetes。 由于 VolumeSnapshotContent 是非命名空间 API 对象,因此只有系统管理员才有权限创建它。 创建 VolumeSnapshotContent 对象后,用户可以创建一个指向 VolumeSnapshotContent 对象的 VolumeSnapshot 对象。 external-snapshotter 控制器将在验证快照存在并且 VolumeSnapshotVolumeSnapshotContent 对象之间的绑定正确后,将快照标记为就绪。绑定后,快照即可在 Kubernetes 中使用。

应使用以下字段创建 VolumeSnapshotContent 对象以表示预先配置的快照

  • csiVolumeSnapshotSource - 快照识别信息。
    • snapshotHandle - 快照的名称/标识符。此字段是必需的。
    • driver - 用于处理此卷的 CSI 驱动程序。此字段是必需的。它必须与快照控制器中的快照器名称匹配。
    • creationTimerestoreSize - 这些字段对于预先配置的卷不是必需的。 external-snapshotter 控制器将在创建后自动更新它们。
  • volumeSnapshotRef - 指向此对象应绑定到的 VolumeSnapshot 对象的指针。
    • namenamespace - 它指定内容绑定到的 VolumeSnapshot 对象的名称和命名空间。
    • UID - 这些字段对于预先配置的卷不是必需的。external-snapshotter 控制器将在绑定后自动更新该字段。 如果用户指定 UID 字段,则必须确保它与绑定快照的 UID 匹配。 如果指定的 UID 与绑定快照的 UID 不匹配,则该内容被视为孤立对象,控制器将删除它及其关联的快照。
  • snapshotClassName - 此字段是可选的。 external-snapshotter 控制器将在绑定后自动更新该字段。
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotContent
metadata:
  name: static-snapshot-content
spec:
  csiVolumeSnapshotSource:
    driver: com.example.csi-driver
    snapshotHandle: snapshotcontent-example-id
  volumeSnapshotRef:
    kind: VolumeSnapshot
    name: static-snapshot-demo
    namespace: demo-namespace

应该创建一个 VolumeSnapshot 对象以允许用户使用快照

  • snapshotClassName - 卷快照类的名称。此字段是可选的。如果设置,则快照类中的快照器字段必须与快照控制器的快照器名称匹配。如果未设置,则快照控制器将尝试查找默认快照类。
  • snapshotContentName - 卷快照内容的名称。 此字段对于预先配置的卷是必需的。
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: static-snapshot-demo
  namespace: demo-namespace
spec:
  snapshotClassName: csi-snapclass
  snapshotContentName: static-snapshot-content

创建这些对象后,快照控制器会将它们绑定在一起,并将字段 Ready(在 Status 下)设置为 True,以表明快照已准备好使用。

使用 Kubernetes 从快照配置新卷

要配置一个预先填充了来自快照对象的数据的新卷,请在 PersistentVolumeClaim 中使用新的 dataSource 字段。它有三个参数

  • name - 表示要用作源的快照的 VolumeSnapshot 对象的名称
  • kind - 必须为 VolumeSnapshot
  • apiGroup - 必须为 snapshot.storage.k8s.io

VolumeSnapshot 对象的命名空间假定与 PersistentVolumeClaim 对象的命名空间相同。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-restore
  Namespace: demo-namespace
spec:
  storageClassName: csi-storageclass
  dataSource:
    name: new-snapshot-demo
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

创建 PersistentVolumeClaim 对象后,它将触发新卷的配置,该新卷预先填充了来自指定快照的数据。

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

要实现快照功能,CSI 驱动程序必须添加对其他控制器功能 CREATE_DELETE_SNAPSHOTLIST_SNAPSHOTS 的支持,并实现其他控制器 RPC:CreateSnapshotDeleteSnapshotListSnapshots。 有关详细信息,请参阅 CSI 规范

尽管 Kubernetes 在 CSI 卷驱动程序的打包和部署方面尽可能限制性最小,但它提供了一种建议机制,用于在 Kubernetes 上部署任意容器化的 CSI 驱动程序,以简化容器化 CSI 兼容卷驱动程序的部署。

作为此建议部署过程的一部分,Kubernetes 团队提供了许多 sidecar(辅助)容器,包括一个新的 external-snapshotter sidecar 容器。

external-snapshotter 监视 Kubernetes API 服务器上的 VolumeSnapshotVolumeSnapshotContent 对象,并针对 CSI 端点触发 CreateSnapshot 和 DeleteSnapshot 操作。 CSI external-provisioner sidecar 容器也已更新,以支持使用新的 dataSource PVC 字段从快照还原卷。

为了支持快照功能,建议存储供应商除了 external provisioner 和 external attacher 之外,还应在其状态集中部署 external-snapshotter sidecar 容器及其 CSI 驱动程序,如下面的图所示。

在此示例部署 yaml 文件中,两个 sidecar 容器,external provisioner 和 external snapshotter 以及 CSI 驱动程序与状态集 pod 中的 hostpath CSI 插件一起部署。 Hostpath CSI 插件是一个示例插件,不适用于生产环境。

alpha 版本的限制是什么?

Kubernetes 快照的 alpha 实现具有以下限制

  • 不支持将现有卷恢复到快照表示的较早状态(alpha 版本仅支持从快照配置新卷)。
  • 不支持从快照对现有 PersistentVolumeClaim 进行“就地还原”:即,从快照配置新卷,但更新现有 PersistentVolumeClaim 以指向新卷,并有效地使 PVC 看起来恢复到较早的状态(alpha 版本仅支持使用通过新的 PV/PVC 从快照配置的新卷)。
  • 除了存储系统提供的任何保证之外,没有快照一致性保证(例如,崩溃一致性)。

下一步是什么?

根据反馈和采用情况,Kubernetes 团队计划在 1.13 或 1.14 版本中将 CSI 快照实现推向 beta 版本。

如何了解更多信息?

在此处查看有关快照功能的其他文档:http://k8s.io/docs/concepts/storage/volume-snapshotshttps://kubernetes-csi.github.io/docs/

如何参与其中?

与所有 Kubernetes 项目一样,该项目是来自不同背景的许多贡献者共同努力的结果。

除了致力于快照功能的贡献者之外

我们非常感谢 Kubernetes Storage SIG 和 CSI 社区的所有贡献者,他们帮助审查了该项目的设计和实施,包括但不限于以下人员

如果您有兴趣参与 CSI 或 Kubernetes 存储系统的任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在快速发展,并且始终欢迎新的贡献者。