本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 1.25:使用 Secret 進行節點驅動的 CSI 卷擴充套件

Kubernetes v1.25 於本月早些時候釋出,引入了一項新功能,允許你的叢集擴充套件儲存卷,即使訪問這些卷需要 Secret(例如:訪問 SAN 網路的憑據)來執行節點擴容操作。這項新行為處於 Alpha 階段,你必須啟用一個特性門控(CSINodeExpandSecret)才能使用它。你還必須使用 CSI 儲存;此變更與 Kubernetes 內建的儲存驅動程式無關。

要開啟這個新的 Alpha 功能,你需要在 kube-apiserver 和 kubelet 中啟用 CSINodeExpandSecret 特性門控。這將開啟一個機制,在 NodeExpansion 期間將 secretRef 配置傳送給 CSI 驅動程式,從而利用該機制透過底層儲存系統執行節點側的擴容操作。

這是什麼意思?

在 Kubernetes v1.24 之前,你可以定義一個叢集級別的 StorageClass 來使用 StorageClass Secret,但你沒有任何機制來指定在儲存掛載到節點以及需要在節點側擴展卷時將用於操作的憑據。

Kubernetes CSI 已經為特定型別的卷大小調整實現了一個類似的機制;即針對 PersistentVolume 的大小調整,這種調整獨立於任何節點進行,被稱為控制器擴容(Controller Expansion)。在這種情況下,你將一個 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 驅動程式的請求中。

作為叢集操作員,你可以將這些 Secret 作為 StorageClass 中的一個不透明引數來指定,就像你已經可以指定其他 CSI Secret 資料一樣。StorageClass 需要設定一些 CSI 特定的引數。以下是這些引數的示例:

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

如果啟用了特性門控並且儲存類攜帶了上述 Secret 配置,CSI Provisioner 就會在 NodeExpansion 請求中從 Secret 中接收憑據。

需要 Secret 才能進行線上擴容的 CSI 卷將設定 NodeExpandSecretRef 欄位。如果未設定,則 NodeExpandVolume CSI RPC 呼叫將在沒有 Secret 的情況下進行。

試一試

  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 會將適當的憑據傳遞給 CSI 驅動程式,透過載入該 Secret 並將資料傳遞給儲存驅動程式。

以下是一個除錯日誌示例

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 的動態供應,請參閱 儲存類持久卷

請加入 Kubernetes 儲存 SIG (特別興趣小組) 來幫助我們增強此功能。已經有很多好主意了,我們非常歡迎更多人參與進來!