为Kubernetes引入卷快照Alpha

作者:Jing Xu(Google)Xing Yang(Huawei),Saad Ali(Google)

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

什么是快照?

许多存储系统(例如Google Cloud永久磁盘,Amazon Elastic Block Storage和许多本地存储系统)都可以创建持久卷的“快照”。快照表示卷的时间点副本。快照可用于供应新卷(预填充快照数据)或将现有卷还原到先前状态(由快照表示)。

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

Kubernetes卷插件系统已经提供了强大的抽象功能,可以自动配置,附加和安装块和文件存储。

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

Kubernetes存储SIG 将快照操作确定为许多有状态工作负载的关键功能。例如,数据库管理员可能要在开始数据库操作之前对数据库卷进行快照。

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

取而代之的是,Kubernetes用户现在被授权以与群集无关的方式将快照操作合并到他们的工具和策略中,并轻松地知道它将对任意Kubernetes群集有效,而与基础存储无关。

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

哪些卷插件支持Kubernetes快照?

Kubernetes支持三种类型的批量插件:in-tree,Flex和CSI。看到 Kubernetes批量插件常见问题解答 有关详细信息。

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

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

快照支持其他 司机 尚待处理,应尽快推出。阅读 ”Kubernetes的容器存储接口(CSI)进入Beta版”博客文章,以了解有关CSI以及如何部署CSI驱动程序的更多信息。

Kubernetes快照API

与用于管理Kubernetes持久卷的API相似,Kubernetes Volume Snapshots引入了三个用于管理快照的新API对象:

  • VolumeSnapshot
    • 由Kubernetes用户创建,以请求为指定的卷创建快照。它包含有关快照操作的信息,例如拍摄快照时的时间戳以及快照是否可以使用。
    • Similar to the PersistentVolumeClaim object, the creation 和 deletion of this object represents a user desire to create or delete a cluster resource (a snapshot).
  • VolumeSnapshotContent
    • 成功创建快照后,由CSI卷驱动程序创建。它包含有关快照的信息,包括快照ID。
    • Similar to the PersistentVolume object, this object represents a provisioned resource on the cluster (a snapshot).
    • Like PersistentVolumeClaimPersistentVolume objects, once a snapshot is created, the VolumeSnapshotContent object binds to the VolumeSnapshot for which it was created (with a one-to-one mapping).
  • VolumeSnapshotClass
    • 由群集管理员创建,以描述应如何创建快照。包括驱动程序信息,访问快照的机密等。

需要注意的是,与核心Kubernetes持久卷对象不同,这些Snapshot对象被定义为 CustomResourceDefinitions(CRD)。 Kubernetes项目正在远离在API服务器中预定义的资源类型,而正在朝着API服务器独立于API对象的模型发展。这使得API服务器可以重用于Kubernetes以外的项目,并且使用者(如Kubernetes)可以简单地将其所需的资源类型安装为CRD。

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

In addition to these new objects, a new, DataSource field has been added to the PersistentVolumeClaim object:

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

Before creating a snapshot, you also need to specify CSI driver information for snapshots by creating a VolumeSnapshotClass object 和 setting the snapshotter field to point to your CSI driver. In the example of VolumeSnapshotClass below, the CSI driver is com.example.csi-driver. You need at least one VolumeSnapshotClass object per snapshot provisioner. You can also set a default VolumeSnapshotClass for each individual CSI driver by putting an annotation snapshot.storage.kubernetes.io/is-default-class: "true" in the class definition.

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

You must set any required opaque parameters based on the documentation for your CSI driver. As the example above shows, the parameter fakeSnapshotOption: foo 和 any referenced secret(s) will be passed to CSI driver during snapshot creation 和 deletion. 的 默认CSI外部快照器 reserves the parameter keys csiSnapshotterSecretNamecsiSnapshotterSecretNamespace. If specified, it fetches the secret 和 passes it to the CSI driver when creating 和 deleting a snapshot.

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

使用Kubernetes创建新快照

Once a VolumeSnapshotClass object is defined 和 you have a volume you want to snapshot, you may create a new snapshot by creating a VolumeSnapshot object.

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

  • kind - 一定是 PersistentVolumeClaim
  • name -PVC API对象名称

的 namespace of the volume to snapshot is assumed to be the same as the namespace of the VolumeSnapshot object.

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

In the VolumeSnapshot spec, user can specify the VolumeSnapshotClass which has the information about which CSI driver should be used for creating the snapshot . When the VolumeSnapshot object is created, the parameter fakeSnapshotOption: foo 和 any referenced secret(s) from the VolumeSnapshotClass are passed to the CSI plugin com.example.csi-driver via a CreateSnapshot call.

In response, the CSI driver triggers a snapshot of the volume 和 then automatically creates a VolumeSnapshotContent object to represent the new snapshot, 和 binds the new VolumeSnapshotContent object to the VolumeSnapshot, making it ready to use. If the CSI driver fails to create the snapshot 和 returns error, the snapshot controller reports the error in the status of VolumeSnapshot object 和 does not retry (this is different from other controllers in Kubernetes, 和 is to prevent snapshots from being taken at an unexpected time).

If a snapshot class is not specified, the external snapshotter will try to find 和 set a default snapshot class for the snapshot. 的 CSI driver specified by snapshotter in the default snapshot class must match the CSI driver specified by the provisioner in the storage class of the PVC.

请注意,Kubernetes Snapshot的Alpha版本不提供任何一致性保证。您必须先准备好应用程序(暂停应用程序,冻结文件系统等),然后再拍摄快照以确保数据一致性。

You can verify that the VolumeSnapshot object is created 和 bound with VolumeSnapshotContent by running kubectl describe volumesnapshot:

  • Ready should be set to true under Status to indicate this volume snapshot is ready for use.
  • Creation Time 字段指示实际创建(剪切)快照的时间。
  • Restore Size 字段指示从快照还原卷时的最小卷大小。
  • Snapshot Content Name field in the spec points to the VolumeSnapshotContent object created for this snapshot.

使用Kubernetes导入现有快照

You can always import an existing snapshot to Kubernetes by manually creating a VolumeSnapshotContent object to represent the existing snapshot. Because VolumeSnapshotContent is a non-namespace API object, only a system admin may have the permission to create it. Once a VolumeSnapshotContent object is created, the user can create a VolumeSnapshot object pointing to the VolumeSnapshotContent object. 的 外部快照者 controller will mark snapshot as ready after verifying the snapshot exists 和 the binding between VolumeSnapshotVolumeSnapshotContent objects is correct. Once bound, the snapshot is ready to use in Kubernetes.

A VolumeSnapshotContent object should be created with the following fields to represent a pre-provisioned snapshot:

  • csiVolumeSnapshotSource -快照识别信息。
    • snapshotHandle -快照的名称/标识符。这是必填栏。
    • driver -用于处理该卷的CSI驱动程序。这是必填栏。它必须与快照控制器中的快照程序名称匹配。
    • creationTimerestoreSize - these fields are not required for pre-provisioned volumes. 的 外部快照者 controller will automatically update them after creation.
  • volumeSnapshotRef - Pointer to the VolumeSnapshot object this object should bind to.
    • namenamespace - It specifies the name 和 namespace of the VolumeSnapshot object which the content is bound to.
    • UID -预先配置的卷不需要这些字段。外部快照控制器将在绑定后自动更新该字段。如果用户指定UID字段,则他/她必须确保该字段与绑定快照的UID匹配。如果指定的UID与绑定快照的UID不匹配,则将内容视为孤立对象,控制器将删除该对象及其关联的快照。
  • snapshotClassName -该字段是可选的。绑定后,外部快照器控制器将自动更新该字段。
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

A VolumeSnapshot object should be created to allow a user to use the snapshot:

  • snapshotClassName -卷快照类的名称。该字段是可选的。如果设置,则快照类中的snapshoter字段必须与快照控制器的snapshoter名称匹配。如果未设置,则快照控制器将尝试查找默认的快照类。
  • 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

Once these objects are created, the snapshot controller will bind them together, 和 set the field Ready (under Status) to True to indicate the snapshot is ready to use.

使用Kubernetes从快照配置新卷

To provision a new volume pre-populated with data from a snapshot object, use the new dataSource field in the PersistentVolumeClaim. It has three parameters:

  • name - name of the VolumeSnapshot object representing the snapshot to use as source
  • 善良-必须 VolumeSnapshot
  • apiGroup-必须是 snapshot.storage.k8s.io

的 namespace of the source VolumeSnapshot object is assumed to be the same as the namespace of the PersistentVolumeClaim object.

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

When the PersistentVolumeClaim object is created, it will trigger provisioning of a new volume that is pre-populated with data from the specified snapshot.

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

To implement the snapshot feature, a CSI driver MUST add support for additional controller capabilities CREATE_DELETE_SNAPSHOTLIST_SNAPSHOTS, 和 implement additional controller RPCs: CreateSnapshot, DeleteSnapshot, 和 ListSnapshots. For details, see CSI规范.

虽然Kubernetes是 最低限度的规定 关于CSI Volume Driver的打包和部署,它提供了一个 建议机制 用于在Kubernetes上部署任意容器化CSI驱动程序,以简化与容器化CSI兼容的卷驱动程序的部署。

作为此建议的部署过程的一部分,Kubernetes团队提供了许多附带(辅助)容器,包括一个新的 外部快照者 杂物箱。

的 外部快照者 watches the Kubernetes API server for VolumeSnapshotVolumeSnapshotContent objects 和 triggers CreateSnapshot 和 DeleteSnapshot operations against a CSI endpoint. 的 CSI 外部供应商 sidecar container has also been updated to support restoring volume from snapshot using the new dataSource PVC field.

为了支持快照功能,建议存储供应商除了在外部供应器,外部连接器以及其CSI驱动程序外,在有状态集中部署外部快照器边车容器,如下图所示。

在这个 部署示例yaml 文件,两个sidecar容器,外部供应商和外部快照程序以及CSI驱动程序与hostpath CSI插件一起部署在statefulset容器中。 Hostpath CSI插件是一个示例插件,不适用于生产。

alpha的局限性是什么?

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

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

下一步是什么?

根据反馈和采用情况,Kubernetes团队计划将CSI Snapshot实施推至beta版本1.13或1.14。

我该如何学习?

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

我该如何参与?

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

除了一直在使用“快照”功能的贡献者之外:

我们非常感谢Kubernetes存储SIG和CSI社区中的所有贡献者,他们帮助审查了项目的设计和实施,包括但不限于以下内容:

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