Filestore を使用してステートフル ワークロードをデプロイする


このチュートリアルでは、Google Kubernetes Engine(GKE)上で、永続ボリューム(PV)および永続ボリューム要求(PVC)を使用して、簡単な読み取り / 書き込みのステートフル・ワークロードをデプロイする方法について説明します。このチュートリアルに沿って、Google Cloud のマネージド ネットワーク ファイルシステムである Filestore を使用し、スケーラビリティの設計方法を学んでください。

背景

本来、Pod はエフェメラルです。つまり、GKE は、Pod が削除、強制排除、または再スケジュールされると、Pod に保存されている状態と値を破棄します。

アプリケーション オペレータとしてステートフル ワークロードを維持したい場合があります。このようなワークロードの例には、WordPress の記事を処理するアプリ、メッセージ アプリ、ML オペレーションを処理するアプリなどがあります。

GKE で Filestore を使用すると、次の操作を行えます。

  • スケーラブルなステートフル ワークロードをデプロイする。
  • 複数の Pod が同じストレージに対して同時に読み書きできるように、複数の Pod で ReadWriteManyaccessMode として使用できるるようにする。
  • 同時に複数の Pod へ Volume をマウントするように GKE を設定する。
  • Pod が削除されてもストレージを保持する。
  • Pod がデータを共有し、簡単にスケールできるようにする。

目標

このチュートリアルは、PVC と NFS を使用して GKE にスケーラブルなステートフル ワークロードを設定するアプリケーション オペレータやその他のユーザーを対象としています。

ステートフル ワークロード GKE 図

このチュートリアルでは、次の手順について説明します。

  1. GKE クラスタを作成する。
  2. CSI を使用して、Filestore でマネージド ファイル ストレージを構成する。
  3. 読み取り・書き込み Pod を作成する。
  4. 読み取り Pod を Service Load Balancer に公開してアクセスする。
  5. 書き込みをスケールアップする。
  6. 書き込み Pod からデータにアクセスする。

費用

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。


このタスクを Google Cloud コンソールで直接行う際の順を追ったガイダンスについては、[ガイドを表示] をクリックしてください。

ガイドを表示


始める前に

プロジェクトを設定する

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console のプロジェクト セレクタのページで、[プロジェクトを作成] をクリックして新しい Google Cloud プロジェクトの作成を開始します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Compute Engine, GKE, and Filestore API を有効にします。

    API を有効にする

  5. Google Cloud Console のプロジェクト セレクタのページで、[プロジェクトを作成] をクリックして新しい Google Cloud プロジェクトの作成を開始します。

    プロジェクト セレクタに移動

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. Compute Engine, GKE, and Filestore API を有効にします。

    API を有効にする

Google Cloud CLI のデフォルト値を設定する

  1. Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
    Cloud Shell を開く

  2. このサンプルアプリのソースコードをダウンロードします。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/databases/stateful-workload-filestore
    
  3. デフォルトの環境変数を設定します。

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    gcloud config set compute/zone COMPUTE_ZONE
    gcloud config set filestore/zone COMPUTE_ZONE
    gcloud config set filestore/region COMPUTE_REGION
    

    次の値を置き換えます。

GKE クラスタを作成する

  1. stateful-cluster という名前の GKE クラスタを作成します。

    gcloud container clusters create-auto stateful-cluster --region COMPUTE_REGION
    

    クラスタが作成されると、結果は次のようになります。

      gcloud container clusters describe stateful-cluster
      NAME: stateful-cluster
      LOCATION: northamerica-northeast2
      MASTER_VERSION: 1.21.11-gke.1100
      MASTER_IP: 34.130.255.70
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.11-gke.1100
      NUM_NODES: 3
      STATUS: RUNNING
    

    ここで、stateful-clusterSTATUSRUNNING です。

CSI を使用して Filestore でマネージド ファイル ストレージを構成する

GKE では、クラスタに Kubernetes Filestore CSI ドライバを自動でデプロイして管理できます。Filestore CSI を使用すると、Filestore インスタンスを動的に作成または削除でき、さらに StorageClassDeployment と一緒に Kubernetes ワークロードで使用できます。

Filestore インスタンスと PV を動的にプロビジョニングする PVC を作成することで新しい Filestore インスタンス作成することも、Kubernetes ワークロードに事前にプロビジョニングされた Filestore インスタンスにアクセスすることも可能です。

新しいインスタンス

ストレージ クラスを作成する

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: filestore-sc
provisioner: filestore.csi.storage.gke.io
volumeBindingMode: Immediate
allowVolumeExpansion: true
parameters:
  tier: standard
  network: default
  • volumeBindingModeImmediate に設定されていると、Volume のプロビジョニングをすぐに開始できます。
  • Filestore インスタンスの作成時間を短縮するため、tierstandard に設定されています。高可用性のある NFS ストレージ、データ バックアップ用のスナップショット、複数のゾーンにわたるデータ レプリケーション、その他のエンタープライズ レベルの機能が必要な場合は、代わりに tierenterprise に設定します。注: StorageClassreclaimPolicy が設定されていない場合、動的に作成された PV の再利用ポリシーのデフォルトは Delete になります。
  1. StorageClass リソースを作成します。

    kubectl create -f filestore-storageclass.yaml
    
  2. ストレージ クラスが作成されていることを確認する

    kubectl get sc
    

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

    NAME                     PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
    filestore-sc             filestore.csi.storage.gke.io   Delete          Immediate              true                   94m
    

事前プロビジョニングされたインスタンス

ストレージ クラスを作成する

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: filestore-sc
provisioner: filestore.csi.storage.gke.io
volumeBindingMode: Immediate
allowVolumeExpansion: true

volumeBindingModeImmediate に設定されると、Volume のプロビジョニングをすぐに開始できます。

  1. StorageClass リソースを作成します。

      kubectl create -f preprov-storageclass.yaml
    
  2. ストレージ クラスが作成されていることを確認する

      kubectl get sc
    

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

      NAME                     PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
      filestore-sc             filestore.csi.storage.gke.io   Delete          Immediate              true                   94m
    

Filestore インスタンス用の永続ボリュームを作成する

apiVersion: v1
kind: PersistentVolume
metadata:
  name: fileserver
  annotations:
    pv.kubernetes.io/provisioned-by: filestore.csi.storage.gke.io
spec:
  storageClassName: filestore-sc
  capacity:
    storage: 1Ti
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  volumeMode: Filesystem
  csi:
    driver: filestore.csi.storage.gke.io
    # Modify this to use the zone, filestore instance and share name.
    volumeHandle: "modeInstance/<FILESTORE_ZONE>/<INSTANCE_NAME>/<FILESTORE_SHARE_NAME>"
    volumeAttributes:
      ip: <IP_ADDRESS> # Modify this to Pre-provisioned Filestore instance IP
      volume: <FILESTORE_SHARE_NAME> # Modify this to Pre-provisioned Filestore instance share name
  1. 既存の Filestore インスタンスの準備ができていることを確認します。

      gcloud filestore instances list
    

    出力は次のようになります。ここで、STATE 値は READY です。

      INSTANCE_NAME: stateful-filestore
      LOCATION: us-central1-a
      TIER: ENTERPRISE
      CAPACITY_GB: 1024
      FILE_SHARE_NAME: statefulpath
      IP_ADDRESS: 10.109.38.98
      STATE: READY
      CREATE_TIME: 2022-04-05T18:58:28
    

    Filestore インスタンスの INSTANCE_NAMELOCATIONFILE_SHARE_NAMEIP_ADDRESS をメモします。

  2. Filestore インスタンスのコンソール変数を設定します。

      INSTANCE_NAME=INSTANCE_NAME
      LOCATION=LOCATION
      FILE_SHARE_NAME=FILE_SHARE_NAME
      IP_ADDRESS=IP_ADDRESS
    
  3. プレースホルダ変数を上記で取得したコンソール変数に置き換えて、preprov-pv.yaml ファイルにします。

      sed "s/<INSTANCE_NAME>/$INSTANCE_NAME/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<LOCATION>/$LOCATION/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<FILE_SHARE_NAME>/$FILE_SHARE_NAME/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<IP_ADDRESS>/$IP_ADDRESS/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
    
  4. PV を作成します。

      kubectl apply -f preprov-pv.yaml
    
  5. PV の STATUSBound に設定されていることを確認します。

      kubectl get pv
    

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

      NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS    REASON   AGE
      fileserver  1Ti        RWX            Delete           Bound    default/fileserver   filestore-sc             46m
    

PersistentVolumeClaim を使用して Volume にアクセスする

次の pvc.yaml マニフェストでは、filestore-sc という名前の Filestore CSI ドライバの StorageClass を参照しています。

複数の Pod で Volume を読み書きできるようにするため、accessModeReadWriteMany に設定します。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: fileserver
spec:
  accessModes:
  - ReadWriteMany
  storageClassName: filestore-sc
  resources:
    requests:
      storage: 1Ti
  1. PVC をデプロイします。

    kubectl create -f pvc.yaml
    
  2. PVC が作成されていることを確認します。

    kubectl get pvc
    

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

    NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    fileserver   Bound    pvc-aadc7546-78dd-4f12-a909-7f02aaedf0c3   1Ti        RWX            filestore-sc        92m
    
  3. 新しく作成された Filestore インスタンスの準備ができていることを確認します。

    gcloud filestore instances list
    

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

    INSTANCE_NAME: pvc-5bc55493-9e58-4ca5-8cd2-0739e0a7b68c
    LOCATION: northamerica-northeast2-a
    TIER: STANDARD
    CAPACITY_GB: 1024
    FILE_SHARE_NAME: vol1
    IP_ADDRESS: 10.29.174.90
    STATE: READY
    CREATE_TIME: 2022-06-24T18:29:19
    

読み取り Pod と書き込み Pod を作成する

読み取り Pod を作成する

読み取り Pod は、書き込み Pod が書き込んでいるファイルを読み取ります。読み取り Pod は、書き込み Pod レプリカが、いつファイルに書き込んだかを確認します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: reader
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reader
  template:
    metadata:
      labels:
        app: reader
    spec:
      containers:
      - name: nginx
        image: nginx:stable-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: fileserver
          mountPath: /usr/share/nginx/html # the shared directory 
          readOnly: true
      volumes:
      - name: fileserver
        persistentVolumeClaim:
          claimName: fileserver

読み取り Pod は、すべての Pod 間で共有されるパス /usr/share/nginx/html から読み取ります。

  1. 読み取り Pod をデプロイします。

    kubectl apply -f reader-fs.yaml
    
  2. Pod のリストをクエリして、読み取りレプリカが実行されていることを確認します。

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          3m30s
    

書き込み Pod を作成する

書き込み Pod は、他の書き込み Pod や読み取り Pod がアクセスできる共有ファイルに定期的に書き込みます。書き込み Pod は、ホスト名を共有ファイルに書き込むことで、自身の存在を記録します。

書き込み Pod に使用されるイメージは、ユーティリティや本番環境アプリケーションに使用される Alpine Linux のカスタム イメージです。これには、最新の書き込みのメタデータを取得して一意のすべての書き込みと合計書き込み数を保持するスクリプト indexInfo.html が含まれます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: writer
spec:
  replicas: 2 # start with 2 replicas
  selector:
    matchLabels:
      app: writer
  template:
    metadata:
      labels:
        app: writer
    spec:
      containers:
      - name: content
        image: us-docker.pkg.dev/google-samples/containers/gke/stateful-workload:latest
        volumeMounts:
        - name: fileserver
          mountPath: /html # the shared directory
        command: ["/bin/sh", "-c"]
        args:
        - cp /htmlTemp/indexInfo.html /html/index.html;
          while true; do
          echo "<b> Date :</b> <text>$(date)</text> <b> Writer :</b> <text2> ${HOSTNAME} </text2> <br>  " >> /html/indexData.html;
          sleep 30;  
          done
      volumes:
      - name: fileserver
        persistentVolumeClaim:
          claimName: fileserver

このチュートリアルでは、書き込み Pod が 30 秒ごとにパス /html/index.html に書き込みます。sleep の数値を変更すると、書き込みの頻度が変わります。

  1. 書き込み Pod をデプロイします。

    kubectl apply -f writer-fs.yaml
    
  2. Pod のリストをクエリして、書き込み Pod が実行されていることを確認します。

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          3m30s
    writer-855565fbc6-8gh2k   1/1     Running   0          2m31s
    writer-855565fbc6-lls4r   1/1     Running   0          2m31s
    

読み取り Pod を Service Load Balancer に公開してアクセスする

ワークロードをクラスタ外部に公開するには、LoadBalancer タイプの Service を作成します。このタイプの Service は、インターネット経由で到達可能な IP アドレスを持つ外部ロードバランサを作成します。

  1. LoadBalancer タイプの Service を reader-lb という名前で作成します。

    kubectl create -f loadbalancer.yaml
    
  2. Deployment を watch して、GKE が reader-lb Service に EXTERNAL-IP を割り当てていることを確認します。

    kubectl get svc --watch
    

    Service の準備が整うと、EXTERNAL-IP 列にロードバランサのパブリック IP アドレスが表示されます。

      NAME         TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
      kubernetes   ClusterIP      10.8.128.1    <none>          443/TCP        2d21h
      reader-lb    LoadBalancer   10.8.131.79   34.71.232.122   80:32672/TCP   2d20h
    
  3. Ctrl+C キーを押して watch プロセスを終了します。

  4. ウェブブラウザで、ロードバランサに割り当てられた EXTERNAL-IP に移動します。このページは 30 秒ごとに更新されます。書き込み Pod が多く、更新間隔が短いほど、表示されるエントリは多くなります。

ロードバランサ Service の詳細を確認するには、loadbalancer.yaml をご覧ください。

書き込みをスケールアップする

PV の accessModeReadWriteMany に設定されているため、GKE は、より多くの書き込み Pod がこの共有ボリュームに書き込めるように(あるいは、より多くの読み取り Pod が読み取れるように)、Pod の数をスケールアップできます。

  1. writer を 5 つのレプリカにスケールアップします。

    kubectl scale deployment writer --replicas=5
    

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

    deployment.extensions/writer scaled
    
  2. 実行中のレプリカの数を確認します。

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          11m
    writer-855565fbc6-8dfkj   1/1     Running   0          4m
    writer-855565fbc6-8gh2k   1/1     Running   0          10m
    writer-855565fbc6-gv5rs   1/1     Running   0          4m
    writer-855565fbc6-lls4r   1/1     Running   0          10m
    writer-855565fbc6-tqwxc   1/1     Running   0          4m
    
  3. ウェブブラウザで、ロードバランサに割り当てられた EXTERNAL-IP に再度移動します。

この時点で、5 つのステートフル書き込み Pod をサポートするようにクラスタを構成してスケールしました。複数の書き込み Pod は、同じファイルに同時に書き込みを行います。読み取り Pod のスケールアップも簡単です。

省略可: 書き込み Pod からデータにアクセスする

このセクションでは、コマンドライン インターフェースを使用して読み取り Pod や書き込み Pod にアクセスする方法について説明します。書き込み Pod が書き込み、読み取り Pod が読み取る対象の共有コンポーネントを確認できます。

  1. 書き込み Pod 名を取得します。

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    writer-5465d65b46-7hxv4   1/1     Running   0          20d
    

    書き込み Pod のホスト名をメモします(例: writer-5465d65b46-7hxv4)。

  2. 次のコマンドを実行して、書き込み Pod にアクセスします。

    kubectl exec -it WRITER_HOSTNAME -- /bin/sh
    
  3. indexData.html ファイルの共有コンポーネントを確認します。

    cd /html
    cat indexData.html
    
  4. indexData.html ファイルを消去します。

    echo '' > indexData.html
    

    EXTERNAL-IP アドレスをホストするウェブブラウザを更新して、変更を確認します。

  5. 環境を終了します。

    exit
    

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

個々のリソースを削除する

  1. ロードバランサ Service を削除します。

    kubectl delete service reader-lb
    

    読み取り Service 用にプロビジョニングされたロードバランサが削除されるまで待ちます。

  2. list が「Listed 0 items」を返すことを確認します。

    gcloud compute forwarding-rules list
    
  3. Deployment を削除します。

    kubectl delete deployment writer
    kubectl delete deployment reader
    
  4. Pod が削除され、「No resources found in default namespace.」が返されることを確認します。

    kubectl get pods
    
  5. PVC を削除します。保持ポリシーが delete に設定されているため、これにより、PV と Filestore インスタンスも削除されます。

    kubectl delete pvc fileserver
    
  6. GKE クラスタを削除します。

    gcloud container clusters delete stateful-cluster --zone=COMPUTE_ZONE
    

    これにより、GKE クラスタを構成するリソース(読み取り Pod と書き込み Pod を含む)が削除されます。

次のステップ