ML のバッチ ワークロードをデプロイする

このチュートリアルでは、Google Kubernetes Engine(GKE)を使用して、費用を抑えながらフォールト トレラントなバッチ ワークロードを管理する方法を説明します。このチュートリアルでは、Job と費用が最適化された Spot Pod の使用方法、および GKE のクラスタ内 Redis ジョブキューの構成方法について説明します。

背景

通常、バッチ ワークロードとは、開始点と終了点を持つように設計されたプロセスのことです。アーキテクチャが、生のデータを使用するものではなく、データを取り込み、処理し、出力する必要がある場合に、GKE でのバッチ ワークロードを検討する必要があります。機械学習、人工知能、ハイ パフォーマンス コンピューティング(HPC)などの分野は、オフラインのモデル トレーニング、一括予測、データ分析、物理システムのシミュレーション、動画の処理など、さまざまなバッチ ワークロードを特徴としています。

コンテナ化されたバッチ ワークロードを設計することで、次のような GKE のメリットを活用できます。

  • オープン標準、幅広いコミュニティ、マネージド サービス。
  • 効果的なワークロードとインフラストラクチャのオーケストレーションおよび専用のコンピューティング リソースによる高い費用対効果。
  • コンテナ化による分離と高いポータビリティ。データ セキュリティを維持しながらクラウドを余剰の容量として使用できます。
  • 高速な GKE クラスタのスケールダウンが後に続くバースト容量が利用可能なこと。

環境を準備する

  1. このチュートリアルで使用するサンプル リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/batch/aiml-workloads
    
  2. GKE Autopilot クラスタを作成します。

    gcloud container clusters create-auto batch-aiml \
        --location=us-central1
    

    この手順は完了までに最大 5 分かかる場合があります。

ネットワーク ファイル システム(NFS)を使用してデータセット ストレージを設定する

ML ワークロードには、データセットと出力ファイル用のストレージ ソリューションが必要です。このセクションでは、Filestore インスタンスを作成し、PersistentVolumePersistentVolumeClaim を使用してインスタンスへのアクセスを指定します。

詳細については、最適なストレージ戦略の設計方法と、GKE クラスタからの Filestore インスタンスへのアクセス方法をご覧ください。

Filestore インスタンスを作成する

  1. Filestore インスタンスを作成します。

    gcloud filestore instances create batch-aiml-filestore \
        --zone=us-central1-b \
        --tier=BASIC_HDD \
        --file-share=name="NFSVol",capacity=1TB \
        --network=name="default"
    

    このコマンドでは次のオプションを指定します。

    • tier: Filestore インスタンスのサービス階層。このサンプルでは、ベーシック ティアを使用します。その他のオプションについては、サービスティアをご覧ください。

    • network=name: Filestore インスタンスの Virtual Private Cloud(VPC)ネットワークの名前。GKE クラスタは、Filestore インスタンスと同じ VPC ネットワークに存在する必要があります。

    • capacity: ボリュームの目的のサイズ。このストレージ値は、リソース量に記載されているサポート対象の単位のいずれかで指定します。

  2. Filestore インスタンスがデプロイされていることを確認します。

    gcloud filestore instances list \
        --project=PROJECT_ID \
        --zone=us-central1-b
    

    PROJECT_ID は、実際の Google Cloudプロジェクト ID に置き換えます。

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

    INSTANCE_NAME: batch-aiml-filestore
    LOCATION: us-central1-b
    TIER: BASIC_HDD
    CAPACITY_GB: 1024
    FILE_SHARE_NAME: NFSVol
    IP_ADDRESS: 203.0.113.54
    STATE: READY
    CREATE_TIME: 2022-03-15T18:23:51
    
  3. 次のセクションで使用するために、IP_ADDRESS フィールドの値をメモしておきます。

PersistentVolume を作成する

Kubernetes の PersistentVolume 仕様を使用すると、GKE クラスタが Filestore インスタンスに接続できます。

  1. kubernetes-manifests/persistent-volume.yaml ファイルを Filestore インスタンスの IP アドレスで更新します。

    sed -i "\
      s/<FILESTORE_IP_ADDRESS>/IP_ADDRESS/g" \
      kubernetes-manifests/persistent-volume.yaml
    

    IP_ADDRESS は、前のセクションで Filestore インスタンスの作成時にメモした IP アドレスに置き換えます。

  2. PersistentVolume をデプロイします。

    kubectl apply -f kubernetes-manifests/persistent-volume.yaml
    

PersistentVolumeClaim を作成する

Kubernetes の PersistentVolumeClaim を使用すると、Kubernetes の Pod と Job が PersistentVolume のストレージ リソースにアクセスできます。

PersistentVolumeClaim をデプロイします。

kubectl apply -f kubernetes-manifests/persistent-volume-claim.yaml

PersistentVolumeClaim を使用する

GKE クラスタで PersistentVolume と PersistentVolumeClaim が設定されていると、PersistentVolumeClaim を使用するように Redis サーバーとバッチジョブを構成できます。これはマウント可能なストレージ ボリュームとして表示されます。

kubernetes-manifests/redis-pod.yaml ファイルと kubernetes-manifests/workload.yaml ファイルを確認します。マニフェスト構成は、次のようになります。

  spec:
  
  containers:
  - name: workload
    image: "us-central1-docker.pkg.dev/gke-batch-aiml/batch-aiml-docker-repo/workload"
    volumeMounts:
    - mountPath: /mnt/fileserver
      name: workload-pvc
  volumes:
  - name: workload-pvc
    persistentVolumeClaim:
      claimName: fileserver-claim
      readOnly: false

このマニフェストでは、次の処理が行われています。

  • spec.volumes は、使用する PersistentVolumeClaim を指定します。
  • spec.containers.volumeMounts は、Pod が Filestore fileshare にアクセスできるローカル ファイルのパスを指定します。

Redis ジョブキューを設定する

ワークロードはデータを一括処理して、不正検出モデルを反復トレーニングします。処理中またはキューにあるデータセットを管理するには、Redis サーバーを GKE クラスタにデプロイします。

このチュートリアルでは、Redis の単一インスタンスを起動します。Redis をスケーラブルかつ冗長にデプロイするには、Redis と PHP を使用した多層ウェブ アプリケーションを作成するをご覧ください。

  1. Redis サーバー仕様をデプロイします。

    kubectl apply -f kubernetes-manifests/redis-pod.yaml
    
  2. Pod が実行されていることを確認するには、次のコマンドを使用します。

    kubectl get pods
    

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

    NAME           READY   STATUS    RESTARTS   AGE
    redis-leader   1/1     Running   0          118s
    

    Pod の実行が開始されるまでに最大で 2 分ほどかかります。

  3. トレーニング用のデータセットとテスト用のデータセットを含むファイルを NFS ボリュームに転送します。

    sh scripts/transfer-datasets.sh
    

    このスクリプトは、ファイルをサンプルコード リポジトリから redis-leader Pod の /mnt/fileserver/datasets/ ディレクトリにコピーします。

  4. Redis キューにデータを入力します。

    sh scripts/queue-jobs.sh
    

    このスクリプトは、トレーニング用のデータセットのファイルパスを Redis データベースの datasets という名前のリストに push します。このキューは、次に処理するデータセットを見つけるためにワークロードによって使用されます。

  5. Service をデプロイして、GKE クラスタ内で Redis サーバーを検出可能にします。

    kubectl apply -f ./kubernetes-manifests/redis-service.yaml
    

バッチ ワークロードを実行する

この時点で、GKE クラスタ、Redis ジョブキュー、ファイル共有の準備が完了しています。これで、バッチ ワークロードを実行できるようになりました。

このセクションでは、サンプル ワークロードのコンテナ イメージを使用して、金融取引データのバッチを使った不正検出モデルのトレーニングを行います。トレーニング プロセスの概要は次のとおりです。

  1. Redis クライアントが Redis キュー内のジョブ(データセットのファイルパス)をリクエストし、完了するとキューからジョブを削除します。

  2. モデル トレーニング マネージャー クラス FraudDetectionModelTrainer が、データの新しいバッチと、必要に応じて機械学習モデルの保存された状態を読み込みます。データセットは、モデルの改良(「ウォームスタート」トレーニングと呼ばれるプロセス)に使用されます。

  3. モデルの新しい状態、バッチの詳細とパフォーマンス スコアが Filestore NFS ボリュームに保存されます。これらには GKE クラスタの PersistentVolumeClaim を使用してアクセスできます。

詳細は、ソースコードをご覧ください

Job を定義する

次のマニフェストでは、バッチ ワークロード イメージの Kubernetes Job を記述します。Kubernetes の Job コントローラは、1 つ以上の Pod を作成し、特定のタスクが正常に実行されるようにします。

apiVersion: batch/v1
kind: Job
metadata:
  name: workload
spec:
  parallelism: 1
  template:
    metadata:
      name: workload
    spec:
      nodeSelector:
        cloud.google.com/gke-spot: "true"
      containers:
      - name: workload
        image: "us-docker.pkg.dev/google-samples/containers/gke/batch-ml-workload"
        volumeMounts:
        - mountPath: /mnt/fileserver
          name: workload-pvc
      volumes:
      - name: workload-pvc
        persistentVolumeClaim:
          claimName: fileserver-claim
          readOnly: false
      restartPolicy: OnFailure

ワークロードをデプロイする

  1. Job をデプロイします。

    kubectl apply -f ./kubernetes-manifests/workload.yaml
    
  2. workload-XXX Pod のステータスが Completed かどうかを確認します。

    watch kubectl get pods
    

    この処理には数秒かかることがあります。Ctrl+C を押すと、コマンドラインに戻れます。

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

    NAME             READY   STATUS      RESTARTS   AGE
    redis-leader     1/1     Running     0          16m
    workload-4p55d   0/1     Completed   0          83s
    
  3. workload Job のログを確認します。

    kubectl logs job/workload
    

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

    Worker with sessionID: b50f9459-ce7f-4da8-9f84-0ab5c3233a72
    Initial queue state: empty=False
    Processing dataset: datasets/training/2018-04-04.pkl
    Processing dataset: datasets/training/2018-04-03.pkl
    Processing dataset: datasets/training/2018-04-02.pkl
    Processing dataset: datasets/training/2018-04-01.pkl
    Queue empty, exiting
    

    .pkl ファイルは、クレジット カード トランザクション一式を含むデータセットをシリアル化したもので、有効または不正としてマークされます。workload Job は、そのファイルを Redis キューから削除する前に、これらのファイルを反復処理(データセットを解凍して ML モデルをトレーニング)します。ワークロードは、Redis キューが空になるまでバッチでデータを継続的に処理した後、正常終了します。

NFS ボリュームを調べる

オペレーションの間ワークロードは、マウントされた NFS ボリューム(クラスタを超えて他のバッチジョブやオンライン アプリケーションにアクセスできる)にファイルを作成します。

  1. ワークロードによって作成されたファイルを一覧表示します。

    kubectl exec --stdin --tty redis-leader -- /bin/sh -c "ls -1 /mnt/fileserver/output"
    

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

    model_cpt_2018-04-01.pkl
    model_cpt_2018-04-02.pkl
    model_cpt_2018-04-03.pkl
    model_cpt_2018-04-04.pkl
    report.txt
    

    NFS ボリュームの /mnt/fileserver/output ディレクトリに、トレーニング済みモデルのチェックポイント(model_cpt_XXX.pkl などのファイル名)とモデル パフォーマンスのレポート(report.txt)が作成されました。

  2. モデルのパフォーマンス レポートを確認します。

    kubectl exec --stdin --tty redis-leader -- /bin/sh -c "cat /mnt/fileserver/output/report.txt"
    

    出力のスニペットは次のとおりです。

    Report generated on: 2022-02-09 14:19:42.303619
    Training dataset: 2018-04-04.pkl
    Model checkpoint: model_cpt_2018-04-04.pkl
    ---
    Accuracy on training data: 0.9981112277019937
    Accuracy on testing data: 0.9977204434773599
    

    このファイルには、トレーニングの時刻、使用したデータセット、達成された精度、トレーニングに関連付けられたモデル チェックポイントのファイル名などの詳細が記述されています。

NFS ボリュームの詳細については、Filestore ガイドをご覧ください。