Kubernetes: CSI Storage Resizing Authenticated(NodeExpandSecret)の動作検証


# はじめに

Kubernetes v1.29にてGAとなったCSI Storage Resizing Authenticated(NodeExpandSecret)について動作検証を行います。
この機能は、PV(Volume)のサイズ拡張を行う際に、指定されたSecretにて設定されたパスフレーズをCSI Driverへ伝搬するための機能です。
そもそも、Volumeのサイズ拡張を行うVolume Expansion機能は、Kubernetes v1.24でGAとなっています。
通常のPV(Volume)であればGAされているVolume Expansion機能で対応可能なのですが、LUKSで暗号化されたVolumeのサイズ拡張など特殊なケースにおいてはパスフレーズが必要となります。
そのため、このパスフレーズをCSI Driverが利用するために本機能が必要となります。

# 検証環境

- Kubernetes v1.27.6 
  - Kubernetes v1.27よりBeta機能として本機能が有効化
- csi-provisioner v3.6.0
  - csi-provisioner v3.3.0から本機能がサポート

# 検証

検証用にパスフレーズを`default` ネームスペース上に`test-secret`に設定します。

```
$ kubectl create secret -n default generic test-secret \
    --from-literal=username='admin' \
    --from-literal=password='admin3'
```

次に、作成したSecretを指定したStorageClass(`test-sc`)を作ります。

- test-sc.yaml

```YAML
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: test-sc
parameters:
  csi.storage.k8s.io/node-expand-secret-name: test-secret
  csi.storage.k8s.io/node-expand-secret-namespace: default
provisioner: csi.hoge.io
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
```

parametersに`csi.storage.k8s.io/node-expand-secret-name`, `csi.storage.k8s.io/node-expand-secret-namespace`を指定します。
また、Volume Expantionを許可する `allowVolumeExpansion`を`true`に設定します。

```
$ kubectl apply -f test-sc.yaml 
storageclass.storage.k8s.io/test-sc created

$ kubectl get sc
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
test-sc                csi.hoge.io   Delete          Immediate           true                   21m
```

次に、作成したStorageClass(`test-sc`)を使ったPod,PVC/PVを作成します。
利用するManifestを以下に示します。

- pod-pvc.yaml

```YAML
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  storageClassName: test-sc
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pv-test
  name: pv-test
spec:
  containers:
  - image: busybox
    name: pv-test
    command:
    - sleep
    - infinity
    volumeMounts:
    - name: block
      mountPath: /mnt/block
  volumes:
  - name: block
    persistentVolumeClaim:
      claimName: test-pvc
```

上記Manifestをデプロイし、Pod,PVC,PVを確認します。

```
$ kubectl apply -f pod-pvc.yaml 
persistentvolumeclaim/test-pvc created
pod/pv-test created

$ kubectl get pod,pvc,pv
NAME          READY   STATUS    RESTARTS   AGE
pod/pv-test   1/1     Running   0          27s

NAME                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-pvc   Bound    pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62   1Gi        RWO            test-sc        27s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62   1Gi        RWO            Delete           Bound    default/test-pvc   test-sc                 24s
```

次に、PVCのサイズを1Giから5Giへ拡張します。

```
$ kubectl patch pvc test-pvc -p "{\"spec\":{\"resources\":{\"requests\":{\"storage\": \"5Gi\"}}}}"
persistentvolumeclaim/test-pvc patched
```

Pod,PVC,PVを確認します。

```
$ kubectl get pod,pvc,pv
NAME          READY   STATUS    RESTARTS   AGE
pod/pv-test   1/1     Running   0          2m1s

NAME                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-pvc   Bound    pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62   5Gi        RWO            test-sc        2m1s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62   5Gi        RWO            Delete           Bound    default/test-pvc   test-sc                 118s


$ kubectl describe pod pv-test 
Events:
  Type     Reason                      Age    From                     Message
  ----     ------                      ----   ----                     -------
...
  Normal   FileSystemResizeSuccessful  10s    kubelet                  MountVolume.NodeExpandVolume succeeded for volume "pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62" demo-ysakashita-w-default-bc0c9fc1-zkb8g
```

PVC/PVとも5Giに拡張されています。
本挙動(Kubernetes上のリソースの動き)は、Secretの指定があっても、指定のない場合のVolume Expansionの動作と同じになります。
違いは、PVに`nodeExpandSecretRef`が追加されている点が異なります。

```
$ kubectl get pv pvc-3622c5ea-d8f8-4292-9849-05c4cee1ed62 -o yaml
...
  csi:
    nodeExpandSecretRef:
      name: test-secret
      namespace: default
...
```

# 感想

Storage Resizing Authenticatedは、CSIのRPCで呼び出されるnodeExpandVolumeの中で、PVに設定されたnodeExpandSecretRefを参照できるようにする機能となります。
多くの場合は、この機能は使わなくてもVolume Expansionできるでしょう。
ただし、一部のユースケースではSecretで設定されるパスフレーズが必要になります。
KEPなどに記載されているユースケースは以下です。

- LUKSで暗号化されたVolumeのサイズ拡張で利用
- CephにてFS拡張の誤動作を防ぐためバックエンドに接続しチェックを行うケースで利用

上記のケースに当てはまる場合は、本検証で行ったようにPVに`nodeExpandSecretRef`を付与してSecretの情報を渡さないと、Volume Expansionが出来ませんので適切に設定してください。

# 参考情報

- [Kubernetes 1.29: CSI Storage Resizing Authenticated and Generally Available in v1.29](https://kubernetes.io/blog/2023/12/15/csi-node-expand-secret-support-ga/)
- [KEP 3107: NodeExpandSecret for CSI Driver](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/3107-csi-nodeexpandsecret)
- [container-storage-interface/spec/issues #445](https://github.com/container-storage-interface/spec/issues/445)