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

CSI 临时内联卷

通常,Kubernetes 中外部存储驱动程序提供的卷是**持久的**,其生命周期完全独立于 Pod,或者(作为特例)与使用卷的第一个 Pod 松散耦合(延迟绑定模式)。在 Kubernetes 中请求和定义此类卷的机制是持久卷声明 (PVC) 和持久卷 (PV) 对象。最初,由容器存储接口 (CSI) 驱动程序支持的卷只能通过这种 PVC/PV 机制使用。

但也有一些用例需要数据卷,其内容和生命周期与 Pod 绑定。例如,驱动程序可能使用特定于在 Pod 中运行的应用程序的动态创建的 Secrets 来填充卷。此类卷需要与 Pod 一起创建,并且可以作为 Pod 终止的一部分被删除(**临时**)。它们被定义为 Pod 规范的一部分(**内联**)。

自 Kubernetes 1.15 起,CSI 驱动程序也可以用于此类**临时内联**卷。在 1.15 版中,必须设置 CSIInlineVolume 功能门才能启用它,因为支持仍处于 alpha 阶段。在 1.16 版中,该功能达到了 Beta 阶段,这通常意味着它在集群中默认启用。

CSI 驱动程序必须进行调整才能支持此功能,因为尽管使用了两个现有的 CSI gRPC 调用(`NodePublishVolume` 和 `NodeUnpublishVolume`),但它们的使用方式不同且未包含在 CSI 规范中:对于临时卷,`kubelet` 在请求 CSI 驱动程序获取卷时仅调用 `NodePublishVolume`。所有其他调用(如 `CreateVolume`、`NodeStageVolume` 等)都将被跳过。卷参数在 Pod 规范中提供,并从中复制到 `NodePublishVolumeRequest.volume_context` 字段。目前没有标准化参数;即使是大小等常见参数也必须以 CSI 驱动程序定义的格式提供。同样,只有在 Pod 终止并且需要移除卷后,才会调用 `NodeUnpublishVolume`。

最初的假设是 CSI 驱动程序将专门编写用于提供持久卷或临时卷。但也有一些驱动程序提供在两种模式下都很有用的存储:例如,PMEM-CSI 管理持久内存 (PMEM),这是一种由 Intel® Optane™ DC 持久内存提供的新型本地存储。这种内存既可以用作持久数据存储(比普通 SSD 快),也可以用作临时暂存空间(容量高于 DRAM)。

因此,Kubernetes 1.16 中的支持得到了扩展。

  • Kubernetes 和用户可以通过 `CSIDriver` 对象中的 `volumeLifecycleModes` 字段来确定驱动程序支持哪种卷。
  • 驱动程序可以通过启用“挂载时的 Pod 信息”功能来获取卷模式信息,该功能将在 `NodePublishRequest.volume_context` 中添加新的 `csi.storage.k8s.io/ephemeral` 条目。

有关在 CSI 驱动程序中实现临时内联卷支持的更多信息,请参阅Kubernetes-CSI 文档原始设计文档

这篇博客文章接下来将介绍基于真实驱动程序的使用示例,并在最后进行总结。

示例

PMEM-CSI

v0.6.0 版本中添加了对临时内联卷的支持。该驱动程序可以在具有真实 Intel® Optane™ DC 持久内存的主机上使用,在 GCE 中的特殊机器上或通过 QEMU 模拟的硬件上使用。后者已完全集成到 Makefile 中,只需要 Go、Docker 和 KVM,因此本示例使用了这种方法。

git clone --branch release-0.6 https://github.com/intel/pmem-csi
cd pmem-csi
TEST_DISTRO=clear TEST_DISTRO_VERSION=32080 TEST_PMEM_REGISTRY=intel make start

启动四节点集群可能需要一段时间,但最终应该会显示:

The test cluster is ready. Log in with /work/pmem-csi/_work/pmem-govm/ssh-pmem-govm, run kubectl once logged in.
Alternatively, KUBECONFIG=/work/pmem-csi/_work/pmem-govm/kube.config can also be used directly.

To try out the pmem-csi driver persistent volumes:
...

To try out the pmem-csi driver ephemeral volumes:
   cat deploy/kubernetes-1.17/pmem-app-ephemeral.yaml | /work/pmem-csi/_work/pmem-govm/ssh-pmem-govm kubectl create -f -

deploy/kubernetes-1.17/pmem-app-ephemeral.yaml 指定了一个卷。

kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app-inline-volume
spec:
  containers:
    - name: my-frontend
      image: busybox
      command: [ "sleep", "100000" ]
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-volume
  volumes:
  - name: my-csi-volume
    csi:
      driver: pmem-csi.intel.com
      fsType: "xfs"
      volumeAttributes:
        size: "2Gi"
        nsmode: "fsdax"

一旦我们创建了该 Pod,我们就可以检查结果。

kubectl describe pods/my-csi-app-inline-volume
Name:         my-csi-app-inline-volume
...
Volumes:
  my-csi-volume:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            pmem-csi.intel.com
    FSType:            xfs
    ReadOnly:          false
    VolumeAttributes:      nsmode=fsdax
                           size=2Gi
kubectl exec my-csi-app-inline-volume -- df -h /data
Filesystem                Size      Used Available Use% Mounted on
/dev/ndbus0region0fsdax/d7eb073f2ab1937b88531fce28e19aa385e93696
                          1.9G     34.2M      1.8G   2% /data

镜像填充器

镜像填充器会自动解压容器镜像并将其内容作为临时卷提供。它仍在开发中,但已提供 canary 镜像,可以通过以下方式安装:

kubectl create -f https://github.com/kubernetes-csi/csi-driver-image-populator/raw/master/deploy/kubernetes-1.16/csi-image-csidriverinfo.yaml
kubectl create -f https://github.com/kubernetes-csi/csi-driver-image-populator/raw/master/deploy/kubernetes-1.16/csi-image-daemonset.yaml

此示例 Pod 将运行 nginx 并让它提供来自 `kfox1111/misc:test` 镜像的数据。

kubectl create -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.16-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: data
      mountPath: /usr/share/nginx/html
  volumes:
  - name: data
    csi:
      driver: image.csi.k8s.io
      volumeAttributes:
          image: kfox1111/misc:test
EOF
kubectl exec nginx -- cat /usr/share/nginx/html/test

那个 `test` 文件只包含一个单词

testing

此类数据容器可以使用 Dockerfile 构建,例如:

FROM scratch
COPY index.html /index.html

cert-manager-csi

cert-manager-csi 与 cert-manager 协同工作。此驱动程序的目标是促进无缝地向 Pod 请求和挂载证书密钥对。这对于促进 mTLS 或通过保证存在证书来保护 Pod 连接非常有用,同时拥有 cert-manager 提供的所有功能。此项目是实验性的。

后续步骤

临时内联卷存在的问题之一是 Kubernetes 在将 Pod 调度到节点时,对该节点上当前可用的存储一无所知。一旦 Pod 被调度,CSI 驱动程序必须在该节点上使卷可用。如果当前不可能,Pod 将无法启动。这将重试直到卷最终准备就绪。存储容量跟踪 KEP 正在尝试解决此问题。

一个相关的 KEP 引入了标准化大小参数

目前,CSI 临时内联卷仍处于 Beta 阶段,同时正在讨论此类问题。我们需要您的反馈来决定如何处理此功能。对于 KEP,上面链接的两个 PR 是一个很好的评论之处。SIG Storage 也定期开会,可以通过 Slack 和邮件列表联系。