本文已发表一年多。较早的文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.22:卷填充器的新设计
本月初发布的 Kubernetes v1.22 引入了一种重新设计的卷填充器(volume populator)方法。该 API 最初在 v1.18 中实现,但存在向后兼容性问题。Kubernetes v1.22 包含一个名为 dataSourceRef
的新 API 字段,修复了这些问题。
数据源
早期的 Kubernetes 版本已在 PersistentVolumeClaim API 中添加了 dataSource
字段,用于克隆卷和从快照创建卷。在创建新的 PVC 时,可以使用 dataSource
字段引用同一 Namespace 中的现有 PVC 或 VolumeSnapshot。这也会修改正常的供给过程,以便新的 PVC 不再是一个空卷,而是包含与被克隆的 PVC 或 VolumeSnapshot 相同的数据。
卷填充器采用相同的设计理念,但将其扩展到任何类型的对象,只要存在一个定义数据源的自定义资源和一个实现逻辑的填充器控制器。最初,dataSource
字段被直接扩展以允许任意对象,前提是在集群上启用了 AnyVolumeDataSource
特性门控。不幸的是,这一更改导致了向后兼容性问题,因此新的 dataSourceRef
字段应运而生。
在 v1.22 中,如果启用了 AnyVolumeDataSource
特性门控,则会添加 dataSourceRef
字段,其行为与 dataSource
字段类似,但它允许指定任意对象。API Server 确保这两个字段内容始终相同,且都不可变。区别在于,创建时 dataSource
只允许 PVC 或 VolumeSnapshot,并忽略所有其他值,而 dataSourceRef
允许大多数类型的对象,在少数不允许对象(PVC 以外的核心对象)的情况下,会发生验证错误。
当此 API 变更进阶到 Stable 阶段时,我们将弃用 dataSource
,并建议在所有用例中使用 dataSourceRef
字段。在 v1.22 版本中,dataSourceRef
作为 Alpha 功能提供,专门用于需要自定义卷填充器的场景。
使用填充器
每个卷填充器必须支持一个或多个 CRD。管理员可以安装 CRD 和填充器控制器,然后带有 dataSourceRef
并指定填充器支持的 CR 类型的 PVC 将由填充器控制器处理,而不是直接由 CSI 驱动程序处理。
在底层,CSI 驱动程序仍然会被调用来创建一个空卷,填充器控制器会向其中填充相应的数据。PVC 在完全填充之前不会绑定到 PV,因此定义包含 Pod 和 PVC Spec 的完整应用 Manifest 是安全的,Pod 不会在一切准备就绪之前开始运行,就像 PVC 是另一个 PVC 或 VolumeSnapshot 的克隆一样。
工作原理
带有数据源的 PVC 仍然会被相关存储类的 external-provisioner Sidecar 注意到(假设使用了 CSI Provisioner),但由于 Sidecar 不理解数据源的 Kind,它不会做任何事情。填充器控制器也在监视带有它能理解的数据源 Kind 的 PVC,当看到一个时,它会创建一个与原始 PVC 大小、卷模式、存储类甚至拓扑(如果使用了拓扑)都相同的临时 PVC。填充器控制器创建一个 Worker Pod,该 Pod 挂载到卷并向其写入必要的数据,然后从卷中卸载,填充器控制器将 PV 从临时 PVC 重新绑定到原始 PVC。
试用
要使用卷填充器,需要满足以下条件:
- 启用
AnyVolumeDataSource
特性门控 - 为特定数据源/填充器安装一个 CRD
- 安装填充器控制器本身
填充器控制器可以使用 lib-volume-populator 库来完成大部分 Kubernetes API 级别的工作。各个填充器只需要提供根据特定 CR 实例实际将数据写入卷的逻辑。此库提供了一个示例填充器实现。
这些可选组件可以改善用户体验:
- 安装 VolumePopulator CRD
- 为每个特定数据源创建一个 VolumePopulator 自定义资源
- 安装 卷数据源验证器 控制器 (Alpha)
这些组件的目的是为没有相应填充器的数据源 PVC 生成警告事件。
综合起来
要了解其工作原理,可以安装示例“hello”填充器并试用一下。
首先安装卷数据源验证器控制器。
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/volume-data-source-validator/master/client/config/crd/populator.storage.k8s.io_volumepopulators.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/volume-data-source-validator/master/deploy/kubernetes/rbac-data-source-validator.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/volume-data-source-validator/master/deploy/kubernetes/setup-data-source-validator.yaml
接下来安装示例填充器。
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/lib-volume-populator/master/example/hello-populator/crd.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/lib-volume-populator/master/example/hello-populator/deploy.yaml
创建一个 Hello
CR 实例,包含一些文本。
apiVersion: hello.k8s.io/v1alpha1
kind: Hello
metadata:
name: example-hello
spec:
fileName: example.txt
fileContents: Hello, world!
创建一个将该 CR 作为数据源的 PVC。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
dataSourceRef:
apiGroup: hello.k8s.io
kind: Hello
name: example-hello
volumeMode: Filesystem
接下来,运行一个读取 PVC 中文件的 Job。
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
spec:
containers:
- name: example-container
image: busybox:latest
command:
- cat
- /mnt/example.txt
volumeMounts:
- name: vol
mountPath: /mnt
restartPolicy: Never
volumes:
- name: vol
persistentVolumeClaim:
claimName: example-pvc
等待 Job 完成(包括其所有依赖项)。
kubectl wait --for=condition=Complete job/example-job
最后查看 Job 的日志。
kubectl logs job/example-job
Hello, world!
注意,卷已经包含了一个带有来自 CR 的字符串内容的文本文件。这仅仅是最简单的示例。实际的填充器可以将卷设置为包含任意内容。
如何编写自己的卷填充器
鼓励有兴趣编写新填充器的开发者使用 lib-volume-populator 库,并只提供围绕该库的一个小型控制器包装器,以及一个能够挂载到卷并向其中写入相应数据的 Pod 镜像。
各个填充器可以非常通用,以便与所有类型的 PVC 配合使用,或者它们可以执行供应商特定的操作,如果卷是由同一供应商的特定 CSI 驱动程序供给的,则可以通过直接与该卷的存储通信等方式快速用数据填充卷。
未来
由于此功能仍处于 Alpha 阶段,我们期望更新树外控制器,增加更多测试和文档。社区计划最终将填充器库重新实现为 Sidecar,以简化运维。
我们希望看到一些官方社区支持的填充器,以解决一些广泛共享的用例。此外,我们期望卷填充器将被备份供应商用于将备份“恢复”到卷,并且可能会由此演进出一个标准化的 API 来执行此操作。
如何了解更多?
增强提案 卷填充器 包含了关于此功能的历史和技术实现的许多详细信息。
关于持久卷的文档主题中的卷填充器和数据源解释了如何在集群中使用此功能。
请加入 Kubernetes storage SIG 参与进来,帮助我们增强此功能。已经有很多好想法了,我们很高兴有更多人加入!