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 ガイドをご覧ください。