"Seamlessly Access Cloud Storage with Cloud Storage FUSE CSI Driver"

こんにちは。Enabling team の山本です。

2023年5月1回目は、[Cloud Storage FUSE CSI driver](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/cloud-storage-fuse-csi-driver?hl=ja)　についてです。

`gcsfuse` については、GKE を触り始めたころからお世話になっています。

NFS として、`gcsfuse` を使う理由は、「コスト」です。

- Filestore
    - Pros.
        - Mount しやすい 😊
    - Cons.
        - 高い 💰
- Cloud Storage
    - Pros.
        - 安い 😊
    - Cons.
        - Mount し難い 😵

従来の `gcsfuse` は、Dockerfile 内の script で mount するのが standard な方法です。
これが、面倒臭い、、

一方、Filestore の mount は、簡単ですが、sizing が柔軟ではないため、使い難い、、

今回、"Cloud Storage FUSE CSI driver" が Preview で公開されたことで、公式にサポートされる流れになると思います。
今までのコミュニティ ベースの `gcsfuse` に比べ、使いやすさが向上すると思います。
そして、mount の方法も Manifest ベースです。

## TL;DR
- `gcsfuse` に比べ、設定が簡単です。manifest のみで完結します。

## 実践
```mermaid
graph LR;
    Pod-->PVC;
    PVC-->PV["PV(bucket)"];
```
- Cluster を作成します。
    - FUSE の Resource を考慮して、Node を選ぶ必要があります。
- `GcsFuseCsiDriver` の表示は、Console 画面上は、見当たりません。5月7日時点。
```bash
gcloud beta container clusters create get-start-fuse \
    --addons GcsFuseCsiDriver \
    --cluster-version=1.26.3-gke.400 \
    --release-channel=rapid \
    --zone "us-central1-c" \
    --num-nodes "1" \
    --workload-pool=sanbox-334000.svc.id.goog
```

- Workload Identity を構成します。
```bash
kubectl create namespace fuse

kubectl create serviceaccount fuse-ksa \
    --namespace fuse
```

```bash
gcloud iam service-accounts create fuse-app \
    --project=sanbox-334000

gcloud projects add-iam-policy-binding sanbox-334000 \
    --member "serviceAccount:fuse-app@sanbox-334000.iam.gserviceaccount.com" \
    --role "roles/storage.admin"

gcloud iam service-accounts add-iam-policy-binding fuse-app@sanbox-334000.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:sanbox-334000.svc.id.goog[fuse/fuse-ksa]"
```

```bash
kubectl annotate serviceaccount fuse-ksa \
    --namespace fuse \
    iam.gke.io/gcp-service-account=fuse-app@sanbox-334000.iam.gserviceaccount.com
```

- Workload Identity の疎通を確認します。
```bash
cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: workload-identity-test
  namespace: fuse
spec:
  containers:
  - image: google/cloud-sdk:slim
    name: workload-identity-test
    command: ["sleep","infinity"]
  serviceAccountName: fuse-ksa
  nodeSelector:
    iam.gke.io/gke-metadata-server-enabled: "true"
EOF
```

- `pv` `pvc` `pod` を作成します。
- `csi.readOnly` は、worklaod の設定が優先されます。
- `storageClassName` の値に、意味はないようです。`pv` `pvc` で同じ値であれば良い。
```bash
cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gcs-fuse-csi-pv
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 5Gi
  storageClassName: example-storage-class
  claimRef:
    namespace: fuse
    name: gcs-fuse-csi-static-pvc
  mountOptions:
    - uid=1001
    - gid=3003
    - debug_fuse
  csi:
    driver: gcsfuse.csi.storage.gke.io
    volumeHandle: gcs-fuse-csi-bucket-k8s
    readOnly: true
EOF

cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gcs-fuse-csi-static-pvc
  namespace: fuse
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  volumeName: gcs-fuse-csi-pv
  storageClassName: example-storage-class
EOF

cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gcs-fuse-csi-example-static-pvc-b
  namespace: fuse
  annotations:
    gke-gcsfuse/volumes: "true"
    gke-gcsfuse/cpu-limit: 10m
    gke-gcsfuse/memory-limit: 100Mi
    gke-gcsfuse/ephemeral-storage-limit: 5Gi
spec:
  securityContext:
    runAsUser: 1001
    runAsGroup: 2002
    fsGroup: 3003
  containers:
  - image: busybox
    name: busybox
    command: ["sleep"]
    args: ["infinity"]
    volumeMounts:
    - name: gcs-fuse-csi-static
      mountPath: /data
      readOnly: true
  serviceAccountName: fuse-ksa
  volumes:
  - name: gcs-fuse-csi-static
    persistentVolumeClaim:
      claimName: gcs-fuse-csi-static-pvc
EOF
```

- bucket の list です。
```bash
yamamoto_daisuke@cloudshell:~ (sanbox-334000)$ gsutil ls gs://gcs-fuse-csi-bucket-k8s
gs://gcs-fuse-csi-bucket-k8s/hoge1.txt
gs://gcs-fuse-csi-bucket-k8s/hoge2.txt
gs://gcs-fuse-csi-bucket-k8s/test/
yamamoto_daisuke@cloudshell:~ (sanbox-334000)$ 
```

- Pod 内で `ls` した結果です。
```bash
yamamoto_daisuke@cloudshell:~ (sanbox-334000)$ k exec -it gcs-fuse-csi-example-static-pvc-b ash -n fuse -c busybox
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
~ $ 
~ $ 
~ $ ls -lrt /data
total 1
-rw-r--r--    1 1001     3003            13 May  6 09:37 hoge1.txt
-rw-r--r--    1 1001     3003             5 May  6 09:38 hoge2.txt
drwxr-xr-x    1 1001     3003             0 May  7 01:18 test
~ $
```

## まとめ
"Cloud Storage FUSE CSI driver" について、検証しました。
まだ、Preview です。
GA になったタイミングで `gcsfuse` を置き換えていきたいと思います。
そして、Cloud Run への適用にも期待です 🤩