这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 1.22:卷填充器的新设计

本月早些时候发布的 Kubernetes v1.22 引入了一种重新设计的卷填充器方法。最初在 v1.18 中实现,该 API 存在向后兼容性问题。Kubernetes v1.22 包含一个新的 API 字段 dataSourceRef,可以解决这些问题。

数据源

早期的 Kubernetes 版本已经在 PersistentVolumeClaim API 中添加了一个 dataSource 字段,用于克隆卷和从快照创建卷。您可以在创建新的 PVC 时使用 dataSource 字段,引用同一命名空间中现有的 PVC 或 VolumeSnapshot。这也修改了正常的配置过程,以便新的 PVC 不会产生空卷,而是包含与克隆的 PVC 或克隆的 VolumeSnapshot 相同的数据。

卷填充器采用相同的设计理念,但将其扩展到任何类型的对象,只要存在一个 自定义资源 来定义数据源,并且有一个填充器控制器来实现逻辑。最初,如果集群启用了 AnyVolumeDataSource 特性门,dataSource 字段被直接扩展以允许任意对象。不幸的是,该更改导致了向后兼容性问题,因此新的 dataSourceRef 字段诞生了。

在 v1.22 中,如果启用了 AnyVolumeDataSource 特性门,则会添加 dataSourceRef 字段,其行为类似于 dataSource 字段,但允许指定任意对象。API 服务器确保这两个字段始终具有相同的内容,并且它们都是不可变的。区别在于,在创建时,dataSource 仅允许 PVC 或 VolumeSnapshot,并忽略所有其他值,而 dataSourceRef 允许大多数类型的对象,在少数情况下不允许对象(PVC 以外的核心对象)时,会发生验证错误。

当此 API 更改升级为稳定版本时,我们将弃用使用 dataSource,并建议所有用例都使用 dataSourceRef 字段。在 v1.22 版本中,dataSourceRef 可用(作为 alpha 功能),专门用于您想要用于自定义卷填充器的情况。

使用填充器

每个卷填充器必须具有一个或多个它支持的 CRD。管理员可以安装 CRD 和填充器控制器,然后具有 dataSourceRef 的 PVC 指定填充器支持的类型的 CR 将由填充器控制器而不是 CSI 驱动程序直接处理。

在底层,仍然会调用 CSI 驱动程序来创建一个空卷,然后填充器控制器会用适当的数据填充它。PVC 在完全填充之前不会绑定到 PV,因此定义包含 Pod 和 PVC 规范的整个应用程序清单是安全的,并且 Pod 将不会开始运行,直到一切准备就绪,就像 PVC 是另一个 PVC 或 VolumeSnapshot 的克隆一样。

工作原理

具有数据源的 PVC 仍然会被相关存储类的 external-provisioner sidecar 注意到(假设使用 CSI 配置器),但由于 sidecar 不理解数据源类型,因此它不会执行任何操作。填充器控制器也在监视具有它理解的数据源类型的 PVC,当它看到一个时,它会创建一个具有相同大小、卷模式、存储类,甚至与原始 PVC 相同的拓扑(如果使用拓扑)的临时 PVC。填充器控制器创建一个 worker Pod,该 Pod 连接到卷并将必要的数据写入其中,然后从卷分离,填充器控制器将 PV 从临时 PVC 重新绑定到原始 PVC。

尝试一下

使用卷填充器需要以下内容

  • 启用 AnyVolumeDataSource 特性门
  • 为特定数据源/填充器安装 CRD
  • 安装填充器控制器本身

填充器控制器可以使用 lib-volume-populator 库来完成大部分 Kubernetes API 级别的工作。单独的填充器只需要提供基于特定 CR 实例将数据实际写入卷的逻辑。该库提供了一个示例填充器实现。

这些可选组件可改善用户体验

  • 安装 VolumePopulator CRD
  • 为每个特定数据源创建一个 VolumePopulator 自定义资源
  • 安装 卷数据源验证器 控制器 (alpha)

这些组件的目的是为没有填充器的 PVC 生成带有数据源的警告事件。

将其全部组合在一起

要了解其工作原理,您可以安装示例“hello”填充器并尝试一下。

首先安装 volume-data-source-validator 控制器。

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!

创建一个 PVC,将该 CR 作为其数据源引用。

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 存储 SIG 以参与进来,帮助我们增强此功能。已经有很多好主意,我们很乐意拥有更多!