Cloud Storage バケットを CSI エフェメラル ボリュームとしてマウントする


このガイドでは、Cloud Storage バケットを基盤とする CSI エフェメラル ボリュームを使用して、Google Kubernetes Engine(GKE)で Kubernetes Pod または Job のストレージ リソースを自動的に管理する方法について説明します。CSI エフェメラル ボリュームは Pod または Job のライフサイクルに関連付けられているため、PersistentVolume オブジェクトと PersistentVolumeClaim オブジェクトを手動で処理する必要はありません。

このガイドは、GKE アプリケーションのストレージ管理を簡素化したいプラットフォーム管理者とオペレーターを対象としています。

このページを読む前に、CSI エフェメラル ボリューム、Kubernetes Pod と Job、Cloud Storage バケットについて理解しておいてください。

PersistentVolume に精通していて、このリソースタイプに依存する既存のデプロイメントとの整合性を維持したい場合は、Cloud Storage バケットを永続ボリュームとしてマウントするをご覧ください。

始める前に

次の前提条件を満たしていることを確認してください。

Cloud Storage バケットの CSI エフェメラル ストレージの仕組み

CSI エフェメラル ボリュームを使用すると、GKE 上のアプリケーションのストレージ管理が簡素化されます。CSI エフェメラル ボリュームは、Pod または Job 仕様内で直接定義します。CSI エフェメラル ボリュームを使用すると、個別の PersistentVolume オブジェクトと PersistentVolumeClaim オブジェクトを必要としません。

CSI エフェメラル ボリュームを使用するには、次のオペレーションが必要です。

  1. ストレージの定義: 使用する CSI ドライバや必要なパラメータなど、ストレージを Pod または Job の YAML ファイルで指定します。Cloud Storage FUSE CSI ドライバの場合は、バケット名とその他の関連情報を指定します。

    必要に応じて、ファイル キャッシュ機能を使用して CSI ドライバのパフォーマンスを微調整できます。ファイル キャッシュを使用すると、頻繁にアクセスされる Cloud Storage ファイルを高速ディスクにキャッシュに保存することで、GKE アプリのパフォーマンスを向上させることができます。

    また、並列ダウンロード機能を使用して、Cloud Storage からの大規模なファイルの読み取りを高速化し、マルチスレッド ダウンロードを実現できます。この機能を使用すると、特にサイズが 1 GB を超える読み取りでモデルの読み込み時間を短縮できます。

  2. ドライバの呼び出し: Pod または Job を作成すると、GKE はエフェメラル ボリューム リクエストを検出し、Cloud Storage FUSE CSI ドライバを呼び出します。

  3. ボリュームのマウントとアタッチメント: CSI ドライバは、CSI エフェメラル ボリューム(基盤となる Cloud Storage バケットを参照)をマウントし、Pod または Job で使用できるようにして、アプリケーションからアクセスできるようにします。ファイル システムでバケットのマウント方法を微調整するには、マウント オプションを使用します。ボリューム属性を使用して、Cloud Storage FUSE CSI ドライバの特定の動作を構成することもできます。

  4. ライフサイクル管理: エフェメラル ボリュームは、Pod または Job の存続期間中のみ存在します。Pod が削除された場合、または Job が完了すると、CSI ドライバはクリーンアップと Volume のマウントを自動的に処理します。

CSI エフェメラル ボリュームをアタッチする

CSI エフェメラル ボリュームを Pod または Job に接続するかどうかに応じて、次の手順を行います。

Pod

Pod に CSI エフェメラル ボリュームをアタッチする手順は次のとおりです。

  1. 次の仕様で Pod YAML マニフェストを作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-ephemeral 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true" 
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - image: busybox
        name: busybox
        command: ["sleep"]
        args: ["infinity"] 
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
          readOnly: true
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          readOnly: true
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs" 
    

    次の値を置き換えます。

    • NAMESPACE: Pod をデプロイする Kubernetes Namespace。
    • KSA_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Kubernetes ServiceAccount の名前。
    • BUCKET_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Cloud Storage バケット名。アンダースコア(_)を指定すると、Kubernetes ServiceAccount がアクセスできるすべてのバケットをマウントできます。詳細については、Cloud Storage FUSE ドキュメントの動的マウントをご覧ください。

    次のマニフェストの例は、これらの必須設定を示しています。

    • metadata.annotations: アノテーション gke-gcsfuse/volumes: "true" は必須です。オプションのアノテーションについては、サイドカー コンテナを構成するをご覧ください。
    • spec.volumes[n].csi.driver: CSI ドライバ名として gcsfuse.csi.storage.gke.io を使用します。

    必要に応じて、次の変数を調整できます。

    • spec.terminationGracePeriodSeconds: デフォルトは 30 です。サイズの大きいファイルを Cloud Storage バケットに書き込む必要がある場合は、この値を引き上げて、Cloud Storage FUSE がアプリケーションの終了後にデータをフラッシュするのに十分な時間を確保します。詳細については、Kubernetes のベスト プラクティス: 猶予期間による終了をご覧ください。
    • spec.volumes[n].csi.volumeAttributes.mountOptions: マウント オプションを Cloud Storage FUSE に渡します。フラグはスペースなしのカンマ区切りの 1 つの文字列で指定します。
    • spec.volumes[n].csi.volumeAttributes: 追加のボリューム属性を Cloud Storage FUSE に渡します。
    • spec.volumes[n].csi.readOnly: すべてのボリューム マウントが読み取り専用の場合は、true を指定します。
    • spec.containers[n].volumeMounts[m].readOnly: 特定のボリューム マウントのみが読み取り専用の場合は、true を指定します。
  2. 次のコマンドを実行して、マニフェストをクラスタに適用します。

    kubectl apply -f FILE_PATH
    

    FILE_PATH は、YAML ファイルのパスに置き換えます。

Pod(ファイル キャッシュ保存)

Pod にファイル キャッシュを使用して CSI エフェメラル ボリュームをアタッチする手順は次のとおりです。

  1. ローカル SSD を基盤とするエフェメラル ストレージを備えたクラスタまたはノードプールを作成するの手順に沿って、ローカル SSD を基盤とするエフェメラル ストレージを備えたクラスタまたはノードプールを作成します。

  2. 次の仕様で Pod YAML マニフェストを作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-file-cache-example 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "50Gi" 
    spec:
      nodeSelector:
        cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
      restartPolicy: Never
      initContainers:
      - name: data-loader
        image: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 1Gi
        command:
          - "/bin/sh"
          - "-c"
          - |
            mkdir -p /test_files
            for i in $(seq 1 1000); do dd if=/dev/zero of=/test_files/file_$i.txt bs=1024 count=64; done
            gcloud storage cp /test_files gs://BUCKET_NAME --recursive
      containers:
      - name: data-validator
        image: busybox
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 500m
            memory: 512Mi
        command:
          - "/bin/sh"
          - "-c"
          - |
            echo "first read with cache miss"
            time cat /data/test_files/file_* > /dev/null
    
            echo "second read from local cache"
            time cat /data/test_files/file_* > /dev/null 
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs,file-cache:max-size-mb:-1"
    

    次の値を置き換えます。

    • NAMESPACE: Pod をデプロイする Kubernetes Namespace。
    • KSA_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Kubernetes ServiceAccount の名前。
    • BUCKET_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Cloud Storage バケット名。アンダースコア(_)を指定すると、Kubernetes ServiceAccount がアクセスできるすべてのバケットをマウントできます。詳細については、Cloud Storage FUSE ドキュメントの動的マウントをご覧ください。

      マニフェストの例では、init コンテナのデータローダーは、サイズが 64 KiB のファイルを 1,000 個生成し、Cloud Storage バケットにアップロードします。メインコンテナ data-validator は、バケット内のすべてのファイルを 2 回読み取り、それにかかった期間をログに記録します。

  3. 次のコマンドを実行して、マニフェストをクラスタに適用します。

    kubectl apply -f FILE_PATH
    

    FILE_PATH は、YAML ファイルのパスに置き換えます。

  4. ログ出力を表示するには、次のコマンドを実行します。

    kubectl logs -n NAMESPACE gcs-fuse-csi-file-cache-example -c data-validator
    

    NAMESPACE は、ワークロードの名前空間に置き換えます。

    出力は次のようになります。

    first read with cache miss
    real    0m 54.68s
    ...
    second read from local cache
    real    0m 0.38s
    ...
    

    出力から、ローカル キャッシュを使用した 2 回目の読み取りが、キャッシュミスを使用した 1 回目の読み取りよりもはるかに高速であることがわかります。

Pod(並列ダウンロード)

Pod で並列ダウンロードを使用して CSI エフェメラル ボリュームをアタッチする手順は次のとおりです。

  1. 次の仕様で Pod YAML マニフェストを作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-ephemeral 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "50Gi" 
    spec:
      containers:
      ...
      volumes:
      - name: gcs-fuse-csi-ephemeral 
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs,file-cache:enable-parallel-downloads:true,file-cache:max-size-mb:-1"
            fileCacheCapacity: "-1"
    

    次の値を置き換えます。

    • NAMESPACE: Pod をデプロイする Kubernetes Namespace。
    • BUCKET_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Cloud Storage バケット名。アンダースコア(_)を指定すると、Kubernetes ServiceAccount がアクセスできるすべてのバケットをマウントできます。詳細については、Cloud Storage FUSE ドキュメントの動的マウントをご覧ください。
  2. 次のコマンドを実行して、マニフェストをクラスタに適用します。

    kubectl apply -f FILE_PATH
    

    FILE_PATH は、YAML ファイルのパスに置き換えます。

ジョブ

Job で CSI エフェメラル ボリュームをアタッチする手順は次のとおりです。

  1. 次の仕様で Job YAML マニフェストを作成します。

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: gcs-fuse-csi-job-example 
      namespace: NAMESPACE 
    spec:
      template:
        metadata: 
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          serviceAccountName: KSA_NAME 
          containers:
          - name: writer
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - touch /data/test && echo $(date) >> /data/test && sleep 10
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
          - name: reader
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - sleep 10 && cat /data/test 
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
              readOnly: true
          volumes:
          - name: gcs-fuse-csi-ephemeral
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: BUCKET_NAME
          restartPolicy: Never 
      backoffLimit: 1
    

    次の値を置き換えます。

    • NAMESPACE: Pod をデプロイする Kubernetes Namespace。
    • KSA_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Kubernetes ServiceAccount の名前。
    • BUCKET_NAME: Cloud Storage バケットへのアクセスを構成するときに指定した Cloud Storage バケット名。アンダースコア(_)を指定すると、Kubernetes ServiceAccount がアクセスできるすべてのバケットをマウントできます。詳細については、Cloud Storage FUSE ドキュメントの動的マウントをご覧ください。

    次のマニフェストの例は、これらの必須設定を示しています。

    • metadata.annotations: アノテーション gke-gcsfuse/volumes: "true" は必須です。オプションのアノテーションについては、サイドカー コンテナを構成するをご覧ください。
    • spec.volumes[n].csi.driver: CSI ドライバ名として gcsfuse.csi.storage.gke.io を使用します。

    必要に応じて、次の変数を調整できます。

    • spec.volumes[n].csi.volumeAttributes.mountOptions: マウント オプションを Cloud Storage FUSE に渡します。フラグはスペースなしのカンマ区切りの 1 つの文字列で指定します。
    • spec.volumes[n].csi.volumeAttributes: 追加のボリューム属性を Cloud Storage FUSE に渡します。
    • spec.volumes[n].csi.readOnly: すべてのボリューム マウントが読み取り専用の場合は、true を指定します。
    • spec.containers[n].volumeMounts[m].readOnly: 特定のボリューム マウントのみが読み取り専用の場合は、true を指定します。
  2. 次のコマンドを実行して、マニフェストをクラスタに適用します。

    kubectl apply -f FILE_PATH
    

    FILE_PATH は、YAML ファイルのパスに置き換えます。

問題のトラブルシューティング

Cloud Storage FUSE の問題のトラブルシューティングを行う場合は、log-severity フラグを TRACE に設定できます。このフラグは、Deployment YAML 内のドライバのコンテナ仕様の args セクションで設定します。これにより、gcsfuseLoggingSeverity ボリューム属性が自動的にトレース設定されます。

その他のトラブルシューティングのヒントについては、GitHub プロジェクトのドキュメントのトラブルシューティング ガイドをご覧ください。

次のステップ