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

Kubernetes 1.25:使用密钥进行节点驱动的 CSI 卷扩展

本月早些时候发布的 Kubernetes v1.25 引入了一项新功能,允许您的集群扩展存储卷,即使访问这些卷需要一个密钥(例如:用于访问 SAN 光纤网络的凭据)来执行节点扩展操作。此新行为处于 Alpha 阶段,您必须启用一个功能门(CSINodeExpandSecret)才能使用它。您还必须使用 CSI 存储;此更改与 Kubernetes 内置的存储驱动程序无关。

要启用此新的 Alpha 功能,您需要为 kube-apiserver 和 kubelet 启用 CSINodeExpandSecret 功能门,这将启用一种机制,将 secretRef 配置作为 CSI 驱动程序节点扩展的一部分发送,从而利用相同的配置来执行底层存储系统的节点侧扩展操作。

这一切是关于什么的?

在 Kubernetes v1.24 之前,您可以定义一个使用 StorageClass Secrets 的集群级 StorageClass,但是您没有任何机制来指定在存储被挂载到节点上以及卷必须在节点侧扩展时执行的操作所使用的凭据。

Kubernetes CSI 已经为特定类型的卷调整实现了类似的机制;即 PersistentVolume 的调整大小,其中调整大小独立于任何被称为控制器扩展的节点进行。在这种情况下,您将 PersistentVolume 与一个包含用于卷调整大小操作的凭据的 Secret 相关联,以便可以进行控制器扩展。CSI 还支持 nodeExpandVolume 操作,CSI 驱动程序可以使用它,独立于控制器扩展或与控制器扩展一起使用,其中调整大小是从集群中附加了该卷的节点驱动的。请阅读 Kubernetes 1.24:卷扩展现在是一项稳定功能

  • 有时,CSI 驱动程序需要在继续进行节点级文件系统扩展操作之前检查后端块存储(或映像)的实际大小。这避免了在文件系统扩展期间后端存储集群返回误报。

  • 当 PersistentVolume 表示加密的块存储(例如使用 LUKS)时,您需要提供密码短语才能扩展设备,并使其可以在该设备上扩展文件系统。

  • 为了在节点扩展时进行各种验证,CSI 驱动程序必须连接到后端存储集群。如果 nodeExpandVolume 请求包含 secretRef,则 CSI 驱动程序可以使用它并连接到存储集群以执行集群操作。

它是如何工作的?

为了启用此版本的 Kubernetes 中的此功能,SIG Storage 引入了一个名为 CSINodeExpandSecret 的新功能门。一旦在集群中启用了该功能门,NodeExpandVolume 请求就可以包含一个 secretRef 字段。NodeExpandVolume 请求是 CSI 的一部分;例如,在从 Kubernetes 控制平面发送到 CSI 驱动程序的请求中。

作为集群操作员,管理员可以在 StorageClass 中将这些密钥指定为不透明参数,就像您已经可以指定其他 CSI 密钥数据一样。StorageClass 需要设置一些 CSI 特定的参数。以下是这些参数的示例

csi.storage.k8s.io/node-expand-secret-name: test-secret
csi.storage.k8s.io/node-expand-secret-namespace: default

如果启用了功能门并且存储类带有上述密钥配置,则 CSI 供应程序将从 Secret 中接收凭据作为 NodeExpansion 请求的一部分。

需要密钥进行在线扩展的 CSI 卷将设置 NodeExpandSecretRef 字段。如果未设置,则将执行不带密钥的 NodeExpandVolume CSI RPC 调用。

尝试一下

  1. 启用 CSINodeExpandSecret 功能门(请参考 功能门)。

  2. 创建一个 Secret,然后创建一个使用该 Secret 的 StorageClass。

以下是保存凭据的 Secret 的示例清单

apiVersion: v1
kind: Secret
metadata:
  name: test-secret
  namespace: default
data:
stringData:
  username: admin
  password: t0p-Secret

以下是引用这些凭据的 StorageClass 的示例清单

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-blockstorage-sc
parameters:
  csi.storage.k8s.io/node-expand-secret-name: test-secret   # the name of the Secret
  csi.storage.k8s.io/node-expand-secret-namespace: default  # the namespace that the Secret is in
provisioner: blockstorage.cloudprovider.example
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true

示例输出

如果 PersistentVolumeClaim (PVC) 创建成功,您可以在 PersistentVolume 的 spec.csi 字段中看到该配置(查找 spec.csi.nodeExpandSecretRef)。通过运行 kubectl get persistentvolume <pv_name> -o yaml 来检查它是否有效。您应该看到类似的内容。

apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/provisioned-by: blockstorage.cloudprovider.example
  creationTimestamp: "2022-08-26T15:14:07Z"
  finalizers:
  - kubernetes.io/pv-protection
  name: pvc-95eb531a-d675-49f6-940b-9bc3fde83eb0
  resourceVersion: "420263"
  uid: 6fa824d7-8a06-4e0c-b722-d3f897dcbd65
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 6Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: csi-pvc
    namespace: default
    resourceVersion: "419862"
    uid: 95eb531a-d675-49f6-940b-9bc3fde83eb0
  csi:
    driver: blockstorage.cloudprovider.example
    nodeExpandSecretRef:
      name: test-secret
      namespace: default
    volumeAttributes:
      storage.kubernetes.io/csiProvisionerIdentity: 1648042783218-8081-blockstorage.cloudprovider.example
    volumeHandle: e21c7809-aabb-11ec-917a-2e2e254eb4cf
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.hostpath.csi/node
          operator: In
          values:
          - racknode01
  persistentVolumeReclaimPolicy: Delete
  storageClassName: csi-blockstorage-sc
  volumeMode: Filesystem
status:
  phase: Bound

如果您然后触发在线存储扩展,kubelet 会通过加载该 Secret 并将数据传递给存储驱动程序,将适当的凭据传递给 CSI 驱动程序。

以下是示例调试日志

I0330 03:29:51.966241       1 server.go:101] GRPC call: /csi.v1.Node/NodeExpandVolume
I0330 03:29:51.966261       1 server.go:105] GRPC request: {"capacity_range":{"required_bytes":7516192768},"secrets":"***stripped***","staging_target_path":"/var/lib/kubelet/plugins/kubernetes.io/csi/blockstorage.cloudprovider.example/f7c62e6e08ce21e9b2a95c841df315ed4c25a15e91d8fcaf20e1c2305e5300ab/globalmount","volume_capability":{"AccessType":{"Mount":{}},"access_mode":{"mode":7}},"volume_id":"e21c7809-aabb-11ec-917a-2e2e254eb4cf","volume_path":"/var/lib/kubelet/pods/bcb1b2c4-5793-425c-acf1-47163a81b4d7/volumes/kubernetes.io~csi/pvc-95eb531a-d675-49f6-940b-9bc3fde83eb0/mount"}
I0330 03:29:51.966360       1 nodeserver.go:459] req:volume_id:"e21c7809-aabb-11ec-917a-2e2e254eb4cf" volume_path:"/var/lib/kubelet/pods/bcb1b2c4-5793-425c-acf1-47163a81b4d7/volumes/kubernetes.io~csi/pvc-95eb531a-d675-49f6-940b-9bc3fde83eb0/mount" capacity_range:<required_bytes:7516192768 > staging_target_path:"/var/lib/kubelet/plugins/kubernetes.io/csi/blockstorage.cloudprovider.example/f7c62e6e08ce21e9b2a95c841df315ed4c25a15e91d8fcaf20e1c2305e5300ab/globalmount" volume_capability:<mount:<> access_mode:<mode:SINGLE_NODE_MULTI_WRITER > > secrets:<key:"XXXXXX" value:"XXXXX" > secrets:<key:"XXXXX" value:"XXXXXX" >

未来

由于此功能仍处于 Alpha 阶段,Kubernetes Storage SIG 希望通过更多测试和实现来更新或获得来自 CSI 驱动程序作者的反馈。社区计划最终在即将发布的版本中将该功能升级为 Beta 版。

参与或了解更多?

增强提案包括有关此功能的历史和技术实现的许多详细信息。

要了解有关 Kubernetes 中基于 StorageClass 的动态供应的更多信息,请参考 Storage ClassesPersistent Volumes

请加入 Kubernetes Storage SIG(特别兴趣小组)来参与,以帮助我们增强此功能。已经有很多好主意了,我们很高兴能有更多!