Kubernetes 1.17功能:Kubernetes卷快照移至Beta

作者: 杨星,VMware,余向谦,Google

Kubernetes Volume Snapshot功能现已在Kubernetes v1.17中处于beta版。被介绍了 作为alpha 在Kubernetes v1.12中, 第二个字母 Kubernetes v1.13中的重大更改。这篇文章总结了beta版本中的更改。

什么是卷快照?

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

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

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

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

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

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

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

此外,这些Kubernetes快照原语是基本的构建基块,可释放为Kubernetes开发高级企业级存储管理功能的能力:包括应用程序或集群级备份解决方案。

Beta有哪些新功能?

随着Volume Snapshot升级为Beta,默认情况下,此功能已在标准Kubernetes部署中启用,而不是选择启用。

Kubernetes Volume Snapshot功能迁移到Beta版还意味着:

  • 改进了卷快照API。
  • CSI外部快照工具分为两个控制器,一个是通用快照控制器,另一个是CSI外部快照工具。
  • 删除密钥将作为注释添加到卷快照内容。
  • 将新的终结器添加到卷快照API对象,以防止在将其绑定到卷快照内容API对象时将其删除。

Kubernetes 卷快照要求

如上所述,随着将Volume Snapshot升级到beta版本,此功能现在默认在标准Kubernetes部署中启用,而不是选择启用。

为了使用Kubernetes卷快照功能,您必须确保在Kubernetes集群上部署了以下组件:

有关详细信息,请参见下面的部署部分。

哪些驱动程序支持Kubernetes卷快照?

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

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

阅读 ” Kubernetes GA的容器存储接口(CSI)”博客文章,以了解有关CSI以及如何部署CSI驱动程序的更多信息。

在发布此博客时,已更新了以下CSI驱动程序,以支持卷快照beta:

Beta级卷快照支持其他功能 CSI驱动程序 尚待处理,应尽快推出。

Kubernetes 卷快照Beta API

在alpha到beta之间对Kubernetes卷快照API进行了许多更改。这些更改不向后兼容。这些更改的目的是使API定义清晰易用。

进行以下更改:

  • DeletionPolicy is now a required field rather than optional in both VolumeSnapshotClassVolumeSnapshotContent. This way the user has to explicitly specify it, leaving no room for confusion.
  • VolumeSnapshotSpec has a new required Source field. Source may be either a PersistentVolumeClaimName (if dynamically provisioning a snapshot) or VolumeSnapshotContentName (if pre-provisioning a snapshot).
  • VolumeSnapshotContentSpec also has a new required Source field. This Source may be either a VolumeHandle (if dynamically provisioning a snapshot) or a SnapshotHandle (if pre-provisioning volume snapshots).
  • VolumeSnapshotStatus now contains a BoundVolumeSnapshotContentName to indicate the VolumeSnapshot object is bound to a VolumeSnapshotContent.
  • VolumeSnapshotContentnow contains a Status to indicate the current state of the content. It has a field SnapshotHandle to indicate that the VolumeSnapshotContent represents a snapshot on the storage system.

Beta版Kubernetes VolumeSnapshot API对象:

type VolumeSnapshot struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Spec VolumeSnapshotSpec
        Status *VolumeSnapshotStatus
}
type VolumeSnapshotSpec struct {
	Source VolumeSnapshotSource
	VolumeSnapshotClassName *string
}
// Exactly one of its members MUST be specified
type VolumeSnapshotSource struct {
	// +optional
	PersistentVolumeClaimName *string
	// +optional
	VolumeSnapshotContentName *string
}
type VolumeSnapshotStatus struct {
	BoundVolumeSnapshotContentName *string
	CreationTime *metav1.Time
	ReadyToUse *bool
	RestoreSize *resource.Quantity
	Error *VolumeSnapshotError
}

Beta版Kubernetes VolumeSnapshotContent API对象:

type VolumeSnapshotContent struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Spec VolumeSnapshotContentSpec
        Status *VolumeSnapshotContentStatus
}
type VolumeSnapshotContentSpec struct {
         VolumeSnapshotRef core_v1.ObjectReference
         Source VolumeSnapshotContentSource
         DeletionPolicy DeletionPolicy
         Driver string
         VolumeSnapshotClassName *string
}
type VolumeSnapshotContentSource struct {
	// +optional
	VolumeHandle *string
	// +optional
	SnapshotHandle *string
}
type VolumeSnapshotContentStatus struct {
  CreationTime *int64
  ReadyToUse *bool
  RestoreSize *int64
  Error *VolumeSnapshotError
  SnapshotHandle *string
}

Beta版Kubernetes VolumeSnapshotClass API对象:

type VolumeSnapshotClass struct {
        metav1.TypeMeta
        metav1.ObjectMeta

        Driver string
        Parameters map[string]string
        DeletionPolicy DeletionPolicy
}

如何在Kubernetes群集上部署对卷快照的支持?

请注意,“卷快照”功能现在取决于新的通用 卷快照控制器 除了卷快照CRD。卷快照控制器和CRD都独立于任何CSI驱动程序。无论在群集上部署多少CSI驱动程序,每个群集必须仅运行一个卷快照控制器实例,并安装一组卷快照CRD。

因此,强烈建议Kubernetes发行商捆绑并部署控制器和CRD作为其Kubernetes集群管理过程的一部分(独立于任何CSI驱动程序)。

如果群集未预装正确的组件,则可以通过执行以下步骤来手动安装这些组件。

安装快照Beta CRD

安装通用快照控制器

安装CSI驱动程序

请遵循CSI驱动程序供应商提供的说明。

如何使用Kubernetes卷快照?

假设所有必需的组件(包括CSI驱动程序)已经在群集上部署并运行,则可以使用VolumeSnapshot API对象创建卷快照,并通过在PVC上指定VolumeSnapshot数据源来还原它们。

使用Kubernetes创建新的卷快照

通过创建指向支持卷快照的CSI驱动程序的VolumeSnapshotClass API对象,可以在Kubernetes集群中启用卷快照的创建/删除。

The following VolumeSnapshotClass, for example, tells the Kubernetes cluster that a CSI driver, testdriver.csi.k8s.io, can handle volume snapshots, 和 that when these snapshots are created, their deletion policy should be to delete.

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
  name: test-snapclass
driver: testdriver.csi.k8s.io
deletionPolicy: Delete
parameters:
  csi.storage.k8s.io/snapshotter-secret-name: mysecret
  csi.storage.k8s.io/snapshotter-secret-namespace: mysecretnamespace

The common snapshot controller reserves the parameter keys csi.storage.k8s.io/snapshotter-secret-namecsi.storage.k8s.io/snapshotter-secret-namespace. If specified, it fetches the referenced Kubernetes secret 和 sets it as an annotation on the volume snapshot content object. The CSI 外拍手枪 retrieves it from the content annotation 和 passes it to the CSI driver during snapshot creation.

卷快照的创建由VolumeSnapshot API对象的创建触发。

VolumeSnapshot对象必须指定以下源类型: persistentVolumeClaimName -要快照的PVC的名称。请注意,VolumeSnapshot对象的源PVC,PV和VolumeSnapshotClass必须指向相同的CSI驱动程序。

The following VolumeSnapshot, for example, triggers the creation of a snapshot for a PVC called test-pvc using the VolumeSnapshotClass above.

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  volumeSnapshotClassName: test-snapclass
  source:
    persistentVolumeClaimName: test-pvc

When volume snapshot creation is invoked, the common snapshot controller first creates a VolumeSnapshotContent object with the volumeSnapshotRef, source volumeHandle, volumeSnapshotClassName if specified, driver, 和 deletionPolicy.

The CSI 外拍手枪 then passes the VolumeSnapshotClass parameters, the source volume ID, 和 any referenced secret(s) to the CSI driver (in this case testdriver.csi.k8s.io) via a CSI CreateSnapshot call. In response, the CSI driver creates a new snapshot for the specified volume, 和 returns the ID for that snapshot. The CSI 外拍手枪 then updates the snapshotHandle, creationTime, restoreSize, 和 readyToUse in the status field of the VolumeSnapshotContent object that represents the new snapshot. For a storage system that needs to upload the snapshot after it has been cut, the CSI 外拍手枪 will keep calling the CSI CreateSnapshot to check the status until upload is complete 和 set readyToUse to true.

The common snapshot controller binds the VolumeSnapshotContent object to the VolumeSnapshot (sets BoundVolumeSnapshotContentName), 和 updates the creationTime, restoreSize, 和 readyToUse in the status field of the VolumeSnapshot object based on the status field of the VolumeSnapshotContent object.

If no volumeSnapshotClassName is specified, one is automatically selected as follows:

The StorageClass from PVC or PV of the source volume is fetched. The default VolumeSnapshotClass is fetched, if available. A default VolumeSnapshotClass is a snapshot class created by the admin with the snapshot.storage.kubernetes.io/is-default-class annotation. If the Driver field of the default VolumeSnapshotClass is the same as the Provisioner field in the StorageClass, the default VolumeSnapshotClass is used. If there is no default VolumeSnapshotClass or more than one default VolumeSnapshotClass for a snapshot, an error will be returned.

请注意,Kubernetes Snapshot API不提供任何一致性保证。您必须手动或使用其他一些更高级别的API /控制器来获取数据一致性之前,必须准备好应用程序(暂停应用程序,冻结文件系统等)。

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

Bound Volume Snapshot Content Name - field in the Status indicates the volume is bound to the specified VolumeSnapshotContent. Ready To Use - field in the Status indicates this volume snapshot is ready for use. Creation Time - field in the Status indicates when the snapshot was actually created (cut). Restore Size - field in the Status indicates the minimum volume size required when restoring a volume from this snapshot.

Name:         test-snapshot
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  snapshot.storage.k8s.io/v1beta1
Kind:         VolumeSnapshot
Metadata:
  Creation Timestamp:  2019-11-16T00:36:04Z
  Finalizers:
    snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection
    snapshot.storage.kubernetes.io/volumesnapshot-bound-protection
  Generation:        1
  Resource Version:  1294
  Self Link:         /apis/snapshot.storage.k8s.io/v1beta1/namespaces/default/volumesnapshots/new-snapshot-demo
  UID:               32ceaa2a-3802-4edd-a808-58c4f1bd7869
Spec:
  Source:
    Persistent Volume Claim Name:  test-pvc
  Volume Snapshot Class Name:      test-snapclass
Status:
  Bound Volume Snapshot Content Name:  snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
  Creation Time:                       2019-11-16T00:36:04Z
  Ready To Use:                        true
  Restore Size:                        1Gi

提醒所有使用卷快照API构建控制器的开发人员:在使用VolumeSnapshot API对象之前,请验证VolumeSnpashot和它所绑定的VolumeSnapshotContent之间的双向绑定,以确保绑定是完整且正确的(不这样做可能导致安全问题)。

kubectl describe volumesnapshotcontent
Name:         snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
Namespace:
Labels:       <none>
Annotations:  <none>
API Version:  snapshot.storage.k8s.io/v1beta1
Kind:         VolumeSnapshotContent
Metadata:
  Creation Timestamp:  2019-11-16T00:36:04Z
  Finalizers:
    snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection
  Generation:        1
  Resource Version:  1292
  Self Link:         /apis/snapshot.storage.k8s.io/v1beta1/volumesnapshotcontents/snapcontent-32ceaa2a-3802-4edd-a808-58c4f1bd7869
  UID:               7dfdf22e-0b0c-4b71-9ddf-2f1612ca2aed
Spec:
  Deletion Policy:  Delete
  Driver:           testdriver.csi.k8s.io
  Source:
    Volume Handle:             d1b34a5f-0808-11ea-808a-0242ac110003
  Volume Snapshot Class Name:  test-snapclass
  Volume Snapshot Ref:
    API Version:       snapshot.storage.k8s.io/v1beta1
    Kind:              VolumeSnapshot
    Name:              test-snapshot
    Namespace:         default
    Resource Version:  1286
    UID:               32ceaa2a-3802-4edd-a808-58c4f1bd7869
Status:
  Creation Time:    1573864564608810101
  Ready To Use:     true
  Restore Size:     1073741824
  Snapshot Handle:  127c5798-0809-11ea-808a-0242ac110003
Events:             <none>

使用Kubernetes导入现有的卷快照

You can always expose a pre-existing volume snapshot in Kubernetes by manually creating a VolumeSnapshotContent object to represent the existing volume snapshot. Because VolumeSnapshotContent is a non-namespace API object, only a cluster admin may have the permission to create it. By specifying the volumeSnapshotRef the cluster admin specifies exactly which user can use the snapshot.

The following VolumeSnapshotContent, for example exposes a volume snapshot with the name 7bdd0de3-aaeb-11e8-9aae-0242ac110002 belonging to a CSI driver called testdriver.csi.k8s.io.

群集管理员应使用以下字段创建VolumeSnapshotContent对象,以表示现有快照:

  • driver -用于处理该卷的CSI驱动程序。这是必填栏。
  • source -快照识别信息
  • snapshotHandle -快照的名称/标识符。这是必填栏。
  • volumeSnapshotRef -指向该内容应绑定到的VolumeSnapshot对象的指针。
  • namenamespace - Specifies the name 和 namespace of the VolumeSnapshot object which the content is bound to.
  • deletionPolicy - Valid values are DeleteRetain. If the deletionPolicy is Delete, then the underlying storage snapshot will be deleted along with the VolumeSnapshotContent object. If the - deletionPolicy is Retain, then both the underlying snapshot 和 VolumeSnapshotContent remain.
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotContent
metadata:
  name: manually-created-snapshot-content
spec:
  deletionPolicy: Delete
  driver: testdriver.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  volumeSnapshotRef:
    name: test-snapshot
    namespace: default

创建VolumeSnapshotContent对象后,用户可以创建指向VolumeSnapshotContent对象的VolumeSnapshot对象。 VolumeSnapshot对象的名称和名称空间必须与VolumeSnapshotContent的volumeSnapshotRef中指定的名称/名称空间匹配。它指定以下字段: volumeSnapshotContentName -上面指定的卷快照内容的名称。这是必填栏。 volumeSnapshotClassName -卷快照类的名称。该字段是可选的。

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: manually-created-snapshot
spec:
  source:
        volumeSnapshotContentName: test-content

Once both objects are created, the common snapshot controller verifies the binding between VolumeSnapshot 和 VolumeSnapshotContent objects is correct 和 marks the VolumeSnapshot as ready (if the CSI driver supports the ListSnapshots call, the controller also validates that the referenced snapshot exists). The CSI 外拍手枪 checks if the snapshot exists if ListSnapshots CSI method is implemented, otherwise it assumes the snapshot exists. The 外拍手枪 sets readyToUse to true in the status field of VolumeSnapshotContent. The common snapshot controller marks the snapshot as ready accordingly.

从快照创建卷

一旦有了绑定的就绪的VolumeSnapshot对象,就可以使用该对象来配置一个新卷,该新卷已用快照中的数据预先填充。

To provision a new volume pre-populated with data from a snapshot, use the dataSource field in the PersistentVolumeClaim. It has three parameters: name -代表要用作源的快照的VolumeSnapshot对象的名称 kind -必须是VolumeSnapshot apiGroup -必须是snapshot.storage.k8s.io

The 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: testdriver.csi.k8s.io
  dataSource:
    name: manually-created-snapshot
    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 the CSI规格 Kubernetes -CSI驱动程序开发人员指南.

尽管Kubernetes对CSI卷驱动程序的打包和部署的说明最少,但它提供了一种建议的机制,用于在Kubernetes上部署任意容器化CSI驱动程序,以简化与容器化CSI兼容的卷驱动程序的部署。

作为建议的部署过程的一部分,Kubernetes团队提供了许多补充(帮助)容器,包括 外拍手枪 容器。

The external-snapshotter watches the Kubernetes API server for VolumeSnapshotContent object 和 triggers CreateSnapshotDeleteSnapshot operations against a CSI endpoint. The CSI 外部供应商边车集装箱 还进行了更新,以支持使用dataSource PVC字段从快照还原卷。

为了支持快照功能,建议存储供应商除了部署外部供应器及其CSI驱动程序之外,还部署外部快照存储工具。

Beta的局限性是什么?

Kubernetes 的卷快照的beta版实现存在以下限制:

  • 不支持将现有卷还原到快照表示的较早状态(beta仅支持从快照配置新卷)。
  • 快照一致性保证不能超出存储系统提供的任何保证(例如崩溃一致性)。这些是高级API /控制器的责任

下一步是什么?

根据反馈和采用情况,Kubernetes团队计划在1.18或1.19中将CSI Snapshot实施推向GA。我们希望支持的一些功能包括一致性组,应用程序一致性快照,工作负载停顿,就地还原,卷备份等等。

我该如何学习?

您也可以看看 外部快照源代码存储库.

查看有关快照功能的其他文档 这里 这里 .

我该如何参与?

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

我们非常感谢最后几个季度加倍努力以帮助该项目达到Beta版的贡献者:

  • 兴阳(兴阳)
  • 项倩玉(yuxiangqian)
  • 静旭(jingxu97)
  • 格兰特·格里菲思(ggriffiths)
  • 可灿(zhucan)

特别感谢以下人员的深刻见解和对设计的透彻考虑:

  • 区美薇(msau42)
  • 萨德·阿里(saadli)
  • 帕特里克·奥哈里(pohly)
  • 蒂姆·霍金(Thockin)
  • 乔丹·利吉特(Liggitt)。

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

我们也定期举办 SIG-存储快照工作组会议。欢迎新的参与者参加设计和开发讨论。