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

Kubernetes 1.22:卷填充器的新设计

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

数据源

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

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

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

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

使用填充器

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

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

工作原理

具有数据源的PVC仍然会被相关存储类的外部供应器sidecar注意到(假设使用了CSI供应器),但由于sidecar不理解数据源类型,它不会执行任何操作。填充器控制器也在监视具有它理解的数据源类型的PVC,当它看到一个时,它会创建一个与原始PVC大小、卷模式、存储类甚至拓扑(如果使用了拓扑)相同的临时PVC。填充器控制器创建一个工作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!

创建一个将该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中文件的作业。

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

等待作业完成(包括所有依赖项)。

kubectl wait --for=condition=Complete job/example-job

最后检查作业的日志。

kubectl logs job/example-job
Hello, world!

请注意,卷中已经包含一个文本文件,其中包含CR中的字符串内容。这只是最简单的示例。实际的填充器可以设置卷以包含任意内容。

如何编写自己的卷填充器

有兴趣编写新填充器的开发人员,建议使用lib-volume-populator库,并且只需提供围绕该库的小型控制器包装器,以及一个能够连接到卷并向卷写入适当数据的Pod镜像。

单个填充器可以非常通用,以便它们适用于所有类型的PVC,或者它们可以执行供应商特定的操作,以快速将数据填充到卷中,如果该卷是由同一供应商的特定CSI驱动程序提供的,例如,通过直接与该卷的存储进行通信。

未来

由于此功能仍处于Alpha阶段,我们希望更新树外控制器,提供更多测试和文档。社区计划最终将填充器库重新实现为sidecar,以简化操作。

我们希望看到一些针对广泛共享用例的官方社区支持的填充器。此外,我们预计卷填充器将被备份供应商用作将备份“恢复”到卷的一种方式,并且可能会演变出用于执行此操作的标准化API。

我如何了解更多信息?

增强提案卷填充器包含了关于此功能的历史和技术实现的详细信息。

在关于持久卷的文档主题中,卷填充器和数据源解释了如何在集群中使用此功能。

请通过加入Kubernetes存储SIG参与进来,帮助我们增强此功能。我们已经有很多好主意了,我们很高兴能有更多!