本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
为 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 支持三种类型的卷插件:in-tree、Flex 和 CSI。有关详细信息,请参阅Kubernetes 卷插件常见问题解答。
快照仅支持 CSI 驱动程序(不支持 in-tree 或 Flex)。要使用 Kubernetes 快照功能,请确保已在您的集群上部署实现了快照的 CSI 驱动程序。
截至本博客发布时,以下 CSI 驱动程序支持快照:
对其他驱动程序的快照支持正在进行中,应该很快就会推出。阅读“Kubernetes 容器存储接口 (CSI) 进入 Beta 版”博客文章,了解有关 CSI 以及如何部署 CSI 驱动程序的更多信息。
Kubernetes 快照 API
与用于管理 Kubernetes 持久卷的 API 类似,Kubernetes 卷快照引入了三个新的 API 对象来管理快照:
VolumeSnapshot
- 由 Kubernetes 用户创建,用于请求为指定卷创建快照。它包含有关快照操作的信息,例如快照拍摄的时间戳以及快照是否已准备好使用。
- 类似于
PersistentVolumeClaim
对象,此对象的创建和删除表示用户希望创建或删除集群资源(快照)。
VolumeSnapshotContent
- 快照成功创建后由 CSI 卷驱动程序创建。它包含有关快照的信息,包括快照 ID。
- 类似于
PersistentVolume
对象,此对象表示集群上已置备的资源(快照)。 - 与
PersistentVolumeClaim
和PersistentVolume
对象一样,快照创建后,VolumeSnapshotContent
对象会绑定到它所创建的 VolumeSnapshot(一对一映射)。
VolumeSnapshotClass
- 由集群管理员创建,用于描述应如何创建快照,包括驱动程序信息、访问快照的秘密等。
重要的是要注意,与核心 Kubernetes 持久卷对象不同,这些快照对象被定义为自定义资源定义 (CRD)。Kubernetes 项目正在从 API 服务器中预定义资源类型的模式转向 API 服务器独立于 API 对象的模型。这允许 API 服务器被其他 Kubernetes 项目重用,并且使用者(如 Kubernetes)可以简单地安装他们所需的资源类型作为 CRD。
支持快照的CSI 驱动程序将自动安装所需的 CRD。Kubernetes 最终用户只需要验证支持快照的 CSI 驱动程序已部署在其 Kubernetes 集群上。
除了这些新对象之外,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
- 在 API 服务器二进制文件上设置以下标志:
在创建快照之前,您还需要通过创建 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 外部快照器保留参数键 csiSnapshotterSecretName
和 csiSnapshotterSecretNamespace
。如果指定,它会获取秘密并在创建和删除快照时将其传递给 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
对象时,参数 fakeSnapshotOption: foo
和 VolumeSnapshotClass
中引用的任何秘密将通过 CreateSnapshot
调用传递给 CSI 插件 com.example.csi-driver
。
作为响应,CSI 驱动程序会触发卷快照,然后自动创建一个 VolumeSnapshotContent
对象来表示新快照,并将新的 VolumeSnapshotContent
对象绑定到 VolumeSnapshot
,使其可供使用。如果 CSI 驱动程序未能创建快照并返回错误,快照控制器会在 VolumeSnapshot
对象的status中报告错误,并且不会重试(这与 Kubernetes 中的其他控制器不同,旨在防止快照在意外时间被拍摄)。
如果未指定快照类,则外部快照器将尝试查找并为快照设置默认快照类。默认快照类中由 snapshotter
指定的 CSI 驱动程序
必须与 PVC 存储类中由 provisioner
指定的 CSI 驱动程序
匹配。
请注意,Kubernetes 快照的 alpha 版本不提供任何一致性保证。您必须在拍摄快照以确保数据一致性之前准备好应用程序(暂停应用程序、冻结文件系统等)。
您可以通过运行 kubectl describe volumesnapshot
来验证 VolumeSnapshot
对象是否已创建并与 VolumeSnapshotContent
绑定。
Ready
应该在Status
下设置为 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 驱动程序。此字段是必需的。它必须与快照控制器中的快照器名称匹配。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
- 卷快照类的名称。此字段是可选的。如果设置,快照类中的快照器字段必须与快照控制器的快照器名称匹配。如果未设置,快照控制器将尝试查找默认快照类。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(辅助)容器,包括一个新的 external-snapshotter sidecar 容器。
external-snapshotter 监视 Kubernetes API 服务器中的 VolumeSnapshot
和 VolumeSnapshotContent
对象,并触发针对 CSI 端点的 CreateSnapshot 和 DeleteSnapshot 操作。CSI external-provisioner sidecar 容器也已更新,以支持使用新的 dataSource
PVC 字段从快照恢复卷。
为了支持快照功能,建议存储供应商除了 external provisioner 和 external attacher 之外,还将其 CSI 驱动程序与 external-snapshotter sidecar 容器一起部署在有状态集中,如下图所示。
在此示例部署 yaml 文件中,两个 sidecar 容器(external provisioner 和 external snapshotter)以及 CSI 驱动程序与 hostpath CSI 插件一起部署在有状态集 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 存储 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)。我们正在迅速发展,并始终欢迎新的贡献者。