本文发表已超过一年。较早的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已发生变化。
介绍 Kubernetes 的卷快照 Alpha 版本
Kubernetes v1.12 引入了对卷快照的 Alpha 支持。此功能允许使用 Kubernetes API 原生地创建/删除卷快照,以及从快照创建新卷。
什么是快照?
许多存储系统(例如 Google Cloud Persistent Disks、Amazon Elastic Block Storage 以及许多本地存储系统)都提供了创建持久卷“快照”的能力。快照是卷在特定时间点的副本。快照可以用来供应新卷(预填充快照数据)或将现有卷恢复到先前的状态(由快照表示)。
为什么要在 Kubernetes 中添加快照?
Kubernetes 卷插件系统已经提供了强大的抽象,可自动化块存储和文件存储的供应、挂接和挂载。
支撑所有这些特性的是 Kubernetes 的工作负载可移植性目标:Kubernetes 旨在为分布式系统应用和底层集群之间创建一个抽象层,以便应用无需关注它们运行在哪个集群的具体细节,并且应用部署无需“集群特定”知识。
Kubernetes Storage SIG 将快照操作确定为许多有状态工作负载的关键功能。例如,数据库管理员可能希望在开始数据库操作之前对数据库卷进行快照。
通过在 Kubernetes API 中提供触发快照操作的标准方法,Kubernetes 用户现在可以在不绕过 Kubernetes API(以及手动执行存储系统特定操作)的情况下处理此类用例。
相反,Kubernetes 用户现在能够以与集群无关的方式将快照操作集成到他们的工具和策略中,并且放心地知道无论底层存储如何,它都可以在任意 Kubernetes 集群上工作。
此外,这些 Kubernetes 快照原语作为基本构建块,为开发 Kubernetes 的高级企业级存储管理功能提供了可能,例如数据保护、数据复制和数据迁移。
哪些卷插件支持 Kubernetes 快照?
Kubernetes 支持三种类型的卷插件:in-tree、Flex 和 CSI。有关详细信息,请参阅Kubernetes 卷插件常见问题解答。
快照仅支持 CSI 驱动程序(不支持 in-tree 或 Flex)。要使用 Kubernetes 快照功能,请确保在集群上部署了实现快照的 CSI 驱动程序。
截至本博客发布时,以下 CSI 驱动程序支持快照
对其他驱动程序的快照支持正在进行中,应该很快就可以使用。阅读“容器存储接口 (CSI) for Kubernetes 进入 Beta”博客文章,了解有关 CSI 以及如何部署 CSI 驱动程序的更多信息。
Kubernetes 快照 API
与用于管理 Kubernetes 持久卷的 API 类似,Kubernetes 卷快照引入了三个新的 API 对象来管理快照
VolumeSnapshot
- 由 Kubernetes 用户创建,用于请求为指定卷创建快照。它包含有关快照操作的信息,例如拍摄快照的时间戳以及快照是否可以使用。
- 与
PersistentVolumeClaim
对象类似,此对象的创建和删除代表用户希望创建或删除集群资源(快照)。
VolumeSnapshotContent
- 由 CSI 卷驱动程序在成功创建快照后创建。它包含有关快照的信息,包括快照 ID。
- 与
PersistentVolume
对象类似,此对象代表集群上的已供应资源(快照)。 - 与
PersistentVolumeClaim
和PersistentVolume
对象一样,快照创建后,VolumeSnapshotContent
对象会绑定到创建它的 VolumeSnapshot(一对一映射)。
VolumeSnapshotClass
- 由集群管理员创建,用于描述如何创建快照,包括驱动程序信息、访问快照所需的 Secret 等。
重要的是要注意,与核心的 Kubernetes 持久卷对象不同,这些快照对象被定义为 CustomResourceDefinitions (CRDs)。Kubernetes 项目正在摆脱在 API Server 中预定义资源类型的方式,转而采用 API Server 独立于 API 对象的设计模式。这使得 API Server 可以被 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 Feature Gate 启用 Kubernetes 卷快照功能(Alpha 版本默认禁用)
- 在 API Server 二进制文件上设置以下标志:
--feature-gates=VolumeSnapshotDataSource=true
- 在 API Server 二进制文件上设置以下标志:
在创建快照之前,您还需要通过创建 VolumeSnapshotClass
对象并设置 snapshotter
字段指向您的 CSI 驱动程序来指定快照的 CSI 驱动程序信息。在下面的 VolumeSnapshotClass
示例中,CSI 驱动程序是 com.example.csi-driver
。每个快照供应者至少需要一个 VolumeSnapshotClass
对象。您还可以通过在类定义中添加 annotation 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 驱动程序文档设置任何所需的 opaque 参数。如上例所示,参数 fakeSnapshotOption: foo
以及任何引用的 secret 将在创建和删除快照期间传递给 CSI 驱动程序 com.example.csi-driver
。默认的 CSI external-snapshotter 保留了参数键 csiSnapshotterSecretName
和 csiSnapshotterSecretNamespace
。如果指定,它会获取 Secret 并在创建和删除快照时将其传递给 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
以及任何引用的 Secret 将通过 CreateSnapshot
调用传递给 CSI 插件 com.example.csi-driver
。
响应时,CSI 驱动程序触发卷的快照,然后自动创建一个 VolumeSnapshotContent
对象来表示新快照,并将新的 VolumeSnapshotContent
对象绑定到 VolumeSnapshot
,使其可以使用。如果 CSI 驱动程序创建快照失败并返回错误,快照控制器会在 VolumeSnapshot
对象的 status 中报告错误,并且不会重试(这与 Kubernetes 中的其他控制器不同,这样做是为了防止在意外时间拍摄快照)。
如果未指定快照类,外部快照程序将尝试查找并为快照设置默认快照类。默认快照类中 snapshotter
指定的 CSI 驱动程序必须与 PVC 的 storage class 中 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
对象。外部快照程序控制器在验证快照存在且 VolumeSnapshot
和 VolumeSnapshotContent
对象之间的绑定正确后,会将快照标记为就绪。绑定后,快照即可在 Kubernetes 中使用。
应使用以下字段创建 VolumeSnapshotContent
对象以代表预供应的快照
csiVolumeSnapshotSource
- 快照标识信息。snapshotHandle
- 快照的名称/标识符。此字段是必需的。driver
- 用于处理此卷的 CSI 驱动程序。此字段是必需的。它必须与快照控制器中的 snapshotter 名称匹配。creationTime
和restoreSize
- 这些字段对于预供应卷不是必需的。外部快照程序控制器将在创建后自动更新它们。
volumeSnapshotRef
- 指向此对象应绑定到的VolumeSnapshot
对象的指针。name
和namespace
- 它指定内容绑定到的VolumeSnapshot
对象的名称和命名空间。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
应创建一个 VolumeSnapshot
对象以允许用户使用快照
snapshotClassName
- 卷快照类的名称。此字段是可选的。如果设置,快照类中的 snapshotter 字段必须与快照控制器的 snapshotter 名称匹配。如果未设置,快照控制器将尝试查找默认快照类。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_SNAPSHOT
和 LIST_SNAPSHOTS
,并实现额外的控制器 RPC:CreateSnapshot
、DeleteSnapshot
和 ListSnapshots
。有关详细信息,请参阅 CSI 规范。
尽管 Kubernetes 对 CSI 卷驱动程序的打包和部署 尽可能减少规定性限制,但它提供了一种 建议的机制,用于在 Kubernetes 上部署任意容器化的 CSI 驱动程序,以简化容器化 CSI 兼容卷驱动程序的部署。
作为此推荐部署过程的一部分,Kubernetes 团队提供了一些 Sidecar(helper)容器,其中包括一个新的 external-snapshotter Sidecar 容器。
external-snapshotter 监听 Kubernetes API 服务器上的 VolumeSnapshot
和 VolumeSnapshotContent
对象,并针对 CSI endpoint 触发 CreateSnapshot 和 DeleteSnapshot 操作。CSI external-provisioner Sidecar 容器也已更新,以支持使用新的 dataSource
PVC 字段从快照恢复卷。
为了支持快照特性,建议存储厂商除了部署 external provisioner 和 external attacher 之外,还应将其 CSI 驱动程序与 external-snapshotter Sidecar 容器一起部署在 StatefulSet 中,如下图所示。
在这个 示例部署 YAML 文件中,external provisioner 和 external snapshotter 这两个 Sidecar 容器以及 CSI 驱动程序与 hostpath CSI 插件一起部署在 StatefulSet Pod 中。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-snapshots 和 https://kubernetes-csi.github.io/docs/
如何参与贡献?
这个项目,就像 Kubernetes 的所有项目一样,是来自不同背景的许多贡献者共同努力的成果。
除了参与快照特性工作的贡献者之外
- Xing Yang (xing-yang)
- Jing Xu (jingxu97)
- Huamin Chen (rootfs)
- Tomas Smetana (tsmetana)
- Shiwei Xu (wackxu)
我们非常感谢所有在 Kubernetes Storage SIG 和 CSI 社区中帮助评审项目设计和实现的贡献者,包括但不限于以下人员
- Saad Ali (saadali)
- Tim Hockin (thockin)
- Jan Šafránek (jsafrane)
- Luis Pabon (lpabon)
- Jordan Liggitt (liggitt)
- David Zhu (davidz627)
- Garth Bushell (garthy)
- Ardalan Kangarlou (kangarlou)
- Seungcheol Ko (sngchlko)
- Michelle Au (msau42)
- Humble Devassy Chirammal (humblec)
- Vladimir Vivien (vladimirvivien)
- John Griffith (j-griffith)
- Bradley Childs (childsb)
- Ben Swartzlander (bswartz)
如果您有兴趣参与 CSI 或 Kubernetes 存储系统的任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在快速壮大,始终欢迎新的贡献者。