このチュートリアルでは、Google Kubernetes Engine(GKE)で強化学習(RL)の分散トレーニング環境をオーケストレートする方法について説明します。Ray と NVIDIA NeMo RL フレームワークを使用して、モデルをファインチューニングするための分散トレーニング環境を設定します。
このチュートリアルでは、Ray と NeMo RL を使用した GKE の Group Relative Policy Optimization(GRPO)トレーニング パイプラインに焦点を当てます。GRPO は、モデルの推論能力を向上させるように設計された強化学習アルゴリズムです。この メモリ効率の高いアルゴリズムは、 Critic または 価値モデル を排除し、相対的なグループベースの 計算を使用することで、RL プロセスを簡素化します。
このチュートリアルを実行する前に、 GKE で verl を使用して強化学習をファインチューニングしてスケーリングする チュートリアルを完了することをおすすめします。次のチュートリアルでは、verl を使用した RL のファインチューニングとスケーリングのチュートリアルと同じクラスタの設定と構成を使用します。
背景
以降のセクションでは、このチュートリアルで使用するコンセプトの概要について説明します。
強化学習(RL)
RL は、静的な模倣ではなく、経験、探索、フィードバックを通じてモデルを学習させます。事前トレーニングではモデルに何を言うかを教えますが、人間からのフィードバックを用いた強化学習(RLHF)では、役立ち、安全で、論理的な方法を教えます。RL は、特定のユースケースのベースモデルとファインチューニングされたモデルの橋渡しを行います。
詳細については、 強化学習とはをご覧ください。
Group Relative Policy Optimization(GRPO)
GRPO は、DeepSeek によって普及したアルゴリズムであり、Critic モデルを削除することで、LLM アライメントの Proximal Policy Optimization(PPO)に代わるメモリ効率の高い 方法を提供します。GRPO は、Critic ネットワークの代わりに、同じプロンプトに対するレスポンスのグループを生成し、そのグループの平均報酬をベースラインとして使用します。
詳細については、GRPO をご覧ください。
NVIDIA NeMo RL
NeMo RL は、スケーラブルな RL 向けに設計された NVIDIA のオープンソースのポストトレーニング ライブラリです。より広範な NeMo フレームワーク エコシステムの一部である NeMo RL を使用すると、単一の GPU で小規模な実験を行うことも、数千の GPU にまたがるマルチノード デプロイを行うこともできます。
詳細については、NVIDIA NeMo RL をご覧ください。
GSM8k データセット
このチュートリアルでは、8,500 個の高品質で言語的に多様な小学校の数学の文章問題を含む GSM8k データセットを使用します。
GSM8k と GRPO を使用すると、モデルは同じ問題に対して n 個の異なるレスポンスのグループを生成します。GRPO は、これらのレスポンスをグループの平均と比較します。モデルは、グループの他のパスと比較して、一貫して正しく論理的に正しいパスに対してより多くの報酬を得ます。時間が経つにつれて、モデルは手順を明確に説明することが報酬を最大化する最も信頼性の高い方法であることを学習し、パフォーマンスの低い回答に対する報酬を効果的に減らします。
詳細については、GSM8k をご覧ください。
目標
このチュートリアルでは、次の手順で NeMo RL を使用して GKE に RL を設定する方法について説明します。
- 環境を準備する
- B200 または H200 GPU を使用して GKE クラスタを設定する
- 分散 Ray クラスタを管理するように KubeRay を構成する
- 高性能ストレージに Managed Lustre を使用する
- NeMo RL を使用する GRPO トレーニング ジョブを実行する
始める前に
- アカウントにログインします。 Google Cloud を初めて使用する場合は、 アカウントを作成して、実際のシナリオで Google プロダクトのパフォーマンスを評価してください。 Google Cloud新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
-
Google Cloud CLI をインストールします。
-
外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。
-
gcloud CLI を初期化するには、次のコマンドを実行します:
gcloud init -
プロジェクトを作成または選択します Google Cloud 。
プロジェクトを選択または作成するために必要なロール
- プロジェクトを選択する: プロジェクトを選択する場合、特定の IAM ロールは必要ありません。ロールが付与されているプロジェクトを選択できます。
-
プロジェクトを作成する: プロジェクトを作成するには、プロジェクト作成者ロール
(
roles/resourcemanager.projectCreator)が必要です。これにはresourcemanager.projects.create権限が含まれています。詳しくは、ロールを付与する方法をご覧ください。
-
プロジェクトを作成します。 Google Cloud
gcloud projects create PROJECT_ID
PROJECT_IDは、作成する Google Cloud プロジェクトの名前に置き換えます。 -
作成した Google Cloud プロジェクトを選択します。
gcloud config set project PROJECT_ID
PROJECT_IDは、 Google Cloud プロジェクトの名前に置き換えます。
必要な API を有効にします。
API を有効にするために必要なロール
API を有効にするには、 権限を含む Service Usage 管理者 IAM ロール(
roles/serviceusage.serviceUsageAdmin)が必要です。serviceusage.services.enable詳しくは、ロールを付与する方法をご覧ください。gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Google Cloud CLI をインストールします。
-
外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。
-
gcloud CLI を初期化するには、次のコマンドを実行します:
gcloud init -
プロジェクトを作成または選択します Google Cloud 。
プロジェクトを選択または作成するために必要なロール
- プロジェクトを選択する: プロジェクトを選択する場合、特定の IAM ロールは必要ありません。ロールが付与されているプロジェクトを選択できます。
-
プロジェクトを作成する: プロジェクトを作成するには、プロジェクト作成者ロール
(
roles/resourcemanager.projectCreator)が必要です。これにはresourcemanager.projects.create権限が含まれています。詳しくは、ロールを付与する方法をご覧ください。
-
プロジェクトを作成します。 Google Cloud
gcloud projects create PROJECT_ID
PROJECT_IDは、作成する Google Cloud プロジェクトの名前に置き換えます。 -
作成した Google Cloud プロジェクトを選択します。
gcloud config set project PROJECT_ID
PROJECT_IDは、 Google Cloud プロジェクトの名前に置き換えます。
必要な API を有効にします。
API を有効にするために必要なロール
API を有効にするには、 権限を含む Service Usage 管理者 IAM ロール(
roles/serviceusage.serviceUsageAdmin)が必要です。serviceusage.services.enable詳しくは、ロールを付与する方法をご覧ください。gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
ユーザー アカウントにロールを付与します。次の IAM ロールごとに次のコマンドを 1 回実行します。
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
次のように置き換えます。
PROJECT_ID: プロジェクト ID。USER_IDENTIFIER: ユーザー アカウントの識別子。 例:myemail@example.com。ROLE: ユーザー アカウントに付与する IAM ロール。
- Hugging Face アカウントを作成します(まだ作成していない場合 )。
- Hugging Face トークンがあることを確認します。
- プロジェクトに B200 GPU と H200 GPU に十分な割り当てがあることを確認します。詳細については、GPU 割り当てを計画するとGPU 割り当てをご覧ください。
環境を準備する
このチュートリアルでは、Cloud Shell を使用します。
コンソールに移動します。Google Cloud
コンソール ウィンドウの上部にある [Activate Cloud Shell] ボタンをクリックします。 Google Cloud
次の環境変数を設定します。
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATION export NODE_LOCATION=NODE_LOCATION export CLUSTER_NAME=CLUSTER_NAME export GPU_TYPE=GPU_TYPE export MACHINE_TYPE=MACHINE_TYPE export GKE_VERSION=GKE_VERSION export KSA_NAME=generic-ksa export NAMESPACE=default export GS_BUCKET=BUCKET_NAME-${PROJECT_ID} export HF_TOKEN=YOUR_HUGGING_FACE_TOKEN次の値を置き換えます。
CLUSTER_NAME: GKE クラスタの名前。CONTROL_PLANE_LOCATION: GKE クラスタ コントロール プレーンの Compute Engine リージョン。NODE_LOCATION: ノードのロケーション。NVIDIA B200 または H200 GPU を使用できる ゾーンを選択します。GPU_TYPE: Compute Engine の容量予約で予約したアクセラレータ。次のいずれかの値を指定する必要があります。nvidia-b200: NVIDIA B200(180 GB)nvidia-h200-141gb: NVIDIA H200(141 GB)
MACHINE_TYPE: 使用するマシンのタイプ:- NVIDIA B200(180 GB)GPU の場合は、
a4-highgpu-8g以降を使用します。 - NVIDIA H200(141 GB)GPU の場合は、
a3-ultragpu-8g以降を使用します。
- NVIDIA B200(180 GB)GPU の場合は、
GKE_VERSION: 使用する GKE のバージョン:- NVIDIA B200(180 GB)GPU の場合は、
1.32.2-gke.1422000以降を使用します。 - NVIDIA H200(141 GB)GPU の場合は、
1.31.4-gke.1183000以降を使用します。
- NVIDIA B200(180 GB)GPU の場合は、
BUCKET_NAME: Cloud Storage バケットのベース名。YOUR_HUGGING_FACE_TOKEN: Hugging Face トークン。
ネットワークに対して次の環境変数を作成します。
export GVNIC_NETWORK_PREFIX="GVNIC-NAME" export RDMA_NETWORK_PREFIX="RDMA-NAME"次の値を置き換えます。
GVNIC-NAME: gVNIC ネットワーク名の接頭辞。任意の接頭辞を使用できます。RDMA-NAME: リモート ダイレクト メモリ アクセス(RDMA)ネットワークの接頭辞。任意の接頭辞を使用できます。
インフラストラクチャを設定する
このセクションでは、VPC ネットワークと GKE クラスタを作成します。
VPC ネットワークの作成
gVNIC インターフェース用の VPC ネットワークを作成します。
gcloud compute networks create ${GVNIC_NETWORK_PREFIX}-net \ --project=${PROJECT_ID} \ --subnet-mode=custom gcloud compute networks subnets create ${GVNIC_NETWORK_PREFIX}-sub \ --network=${GVNIC_NETWORK_PREFIX}-net \ --location=${CONTROL_PLANE_LOCATION} \ --range=192.168.0.0/24 gcloud compute firewall-rules create ${GVNIC_NETWORK_PREFIX}-internal \ --network=${GVNIC_NETWORK_PREFIX}-net \ --action=ALLOW \ --rules=tcp:0-65535,udp:0-65535,icmp \ --source-ranges=192.168.0.0/168 つの GPU 用に 8 つのサブネットを含む RDMA 用の VPC ネットワークとサブネットを作成します。
gcloud compute networks create ${RDMA_NETWORK_PREFIX}-net \ --network-profile=${CONTROL_PLANE_LOCATION}-vpc-roce \ --subnet-mode=custom for N in $(seq 0 7); do gcloud compute networks subnets create ${RDMA_NETWORK_PREFIX}-sub-$N \ --network=${RDMA_NETWORK_PREFIX}-net \ --location=${CONTROL_PLANE_LOCATION} \ --range=192.168.$((N+1)).0/24 & done wait
GKE クラスタを作成する
GKE Autopilot クラスタまたは GKE Standard クラスタで NeMo RL を設定できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、 GKE の運用モードについてをご覧ください。
Autopilot
Autopilot クラスタを作成します。
gcloud container clusters create-auto ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-multi-networking \ --enable-ray-operatorクラスタの認証情報を取得します。
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION}Autopilot 用の NCCL RDMA インストーラをインストールします。
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer-autopilot.yaml
標準
Standard クラスタを作成します。
gcloud container clusters create ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-dataplane-v2 \ --enable-ip-alias \ --enable-multi-networking \ --addons=RayOperator \ --num-nodes=1クラスタの認証情報を取得します。
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION}GPU ノードプールを作成します。
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --node-locations=${NODE_LOCATION} \ --machine-type=${MACHINE_TYPE} \ --accelerator=type=${GPU_TYPE},count=8 \ --spot \ --additional-node-network=network=${GVNIC_NETWORK_PREFIX}-net,subnetwork=${GVNIC_NETWORK_PREFIX}-sub \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-0 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-1 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-2 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-3 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-4 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-5 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-6 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-7NCCL RDMA インストーラをインストールします。
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
ネットワーク マッピングを構成する
次のマニフェストを
network-mapping.yamlとして保存します。次のようにマニフェストを適用します。
kubectl apply -f network-mapping.yaml
ストレージを準備する
このセクションでは、Cloud Storage バケットと Managed Lustre インスタンスを作成します。これにより、RL ワークロードに必要な高性能ストレージがプロビジョニングされます。
Cloud Storage バケットを作成します。
gcloud storage buckets create gs://${GS_BUCKET} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-hierarchical-namespace \ --uniform-bucket-level-accessKubernetes サービス アカウント(KSA)を作成してバケットにバインドします。
kubectl create serviceaccount ${KSA_NAME} --namespace ${NAMESPACE} gcloud storage buckets add-iam-policy-binding gs://${GS_BUCKET} \ --member "principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KSA_NAME}" \ --role "roles/storage.objectUser"次の手順で Managed Lustre を設定します。
- Managed Lustre インスタンスを作成するの手順に沿って、Managed Lustre インスタンスを作成します。インスタンスが GKE クラスタと同じネットワークを使用していることを確認します。
- 既存の Managed Lustre インスタンスにアクセスするの手順に沿って、Managed Lustre インスタンスにアクセスします。
RayCluster をデプロイする
このセクションでは、サンプル リポジトリをクローンし、マニフェストを準備して、launcher.sh スクリプトを実行します。
サンプル リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samples作業ディレクトリに移動します。
cd ai-ml/nemo-rl-on-gke/nemoRLvalues.yamlマニフェストを調べます。NCCL_TUNER_CONFIG_PATHは、このチュートリアルで使用するアクセラレータに基づいて、次のいずれかの値に置き換えます。- NVIDIA B200(180 GB):
/usr/local/gib/configs/tuner_config_a4.txtpb - NVIDIA H200(141 GB):
/usr/local/gib/configs/tuner_config_a3u.txtpb
このマニフェストでは、ヘッドノードがジョブを管理し、Ray ダッシュボードをホストします。ワーカーノードはトレーニング ジョブを実行します。
- NVIDIA B200(180 GB):
Ray クラスタをインストールします。
export REPLICA_COUNT=2 helm install ray-cluster . \ --set values.additionalWorkerGroups.worker-grp-0.replicas=$REPLICA_COUNTこのチュートリアルでは、2 つのワーカーノードを使用します。ワーカーノードの数を変更する場合は、
REPLICA_COUNTの値を変更します。Ray クラスタをデプロイするには、
launcher.shスクリプトを実行します。bash launcher.shワーカーノードとヘッドノードが実行されていることを確認します。
kubectl get pods出力は次のようになります。
NAME READY STATUS RESTARTS AGE ray-cluster-kuberay-head-sw7dp 3/3 Running 0 33h ray-cluster-kuberay-worker-grp-0-worker-gkbxw 3/3 Running 0 33h ray-cluster-kuberay-worker-grp-0-worker-kdg62 3/3 Running 0 33hRay クラスタが実行されていることを確認します。
kubectl ray get clusters出力は次のようになります。
NAME NAMESPACE DESIRED WORKERS AVAILABLE WORKERS CPUS GPUS TPUS MEMORY CONDITION STATUS AGE ray-cluster-kuberay default 2 2 618 17 0 1573741824k RayClusterProvisioned ready 33h
GRPO ジョブを起動する
Ray クラスタの準備ができたら、GKE で実行中の Ray クラスタに Ray ジョブを送信できます。NeMo RL は、RL トレーニング ジョブの実行中にモデルを自動的にダウンロードします。
Ray ジョブを送信するには、インタラクティブ セッションを開始してジョブを実行します。
Ray クラスタへのローカル接続を確立するには、次のコマンドを実行します。
kubectl ray session ray-cluster-kuberayこのコマンドにより、ローカルマシンと Ray ヘッドノード間のポート転送が GKE クラスタで開始されます。このセッションがアクティブになっている間は、ターミナルが 占有されます。続行するには、別の ターミナル インスタンスを開きます。
gemma3-27b-gsm8k.shファイルを編集します。gemma3-27b-gsm8k.shファイル内の次の値を置き換えます。YOUR_WANDB_API_KEY: WandB API キー。YOUR_HF_TOKEN: Hugging Face トークン。
このファイルでは、GSM8k データセットで gemma3-27b-it モデルを使用してジョブを実行する構成を確認できます。GRPO トレーニング パイプラインを完了するために、このスクリプトでは次のパラメータを定義します。
num_prompts_per_step: 16とnum_generations_per_prompt: 64: Gemma3-27b-it モデルは、プロンプトごとにレスポンスの大きなグループを生成します。 この構成では、モデルは合計 1,024 個のレスポンスを生成します(16 × 64 = 1,024)。policy.generation.colocated.enabled=False: このパラメータは、コロケーションされた生成機能を無効にします。つまり、モデルはトレーニング プロセスと同じノードでレスポンスを生成しません。標準の RL では、同じ GPU がトレーニングと生成の両方を処理します。この NeMo RL の設定では、特定のノード(policy.generation.colocated.resourcesパラメータで管理)を vLLM 推論専用にし、クラスタの残りの部分を負荷の高いトレーニング計算に集中させます。これらのワークロードを分離することで、メモリ集約型のトレーニング バッファとコンピューティング集約型の推論ワークロード間のリソース競合を防ぐことができます。
ジョブを送信するには、次のコマンドを実行します。
bash gemma3-27b-it/gemma3-27b-gsm8k.shジョブの実行中、出力にはトレーニング結果、タイミング、パフォーマンス指標が表示されます。
GRPO ジョブの健全性をモニタリングする
Ray がジョブを完了すると、NeMo RL は構成されたパスにチェックポイントを保存します。
GRPO ジョブの出力を確認するには、
ray-headコンテナへの SSH セッションを作成します。kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -c ray-head -- bashray-headコンテナのターミナルに apt tree ユーティリティをインストールします。apt update && apt install -y tree出力は次のようになります。
root@ray-cluster-kuberay-worker-grp-0-worker-gkbxw:/opt/nemo-rl# tree /data/nemo_rl_gemma3_27b_3_17/ /data/nemo_rl_gemma3_27b_3_17/ `-- step_10 |-- config.yaml |-- policy | |-- optimizer | | |-- __0_0.distcp | | |-- __10_0.distcp | | |-- __11_0.distcp | | |-- __12_0.distcp | | |-- __13_0.distcp | | |-- __14_0.distcp | | |-- __15_0.distcp | | |-- __1_0.distcp | | |-- __2_0.distcp | | |-- __3_0.distcp | | |-- __4_0.distcp | | |-- __5_0.distcp | | |-- __6_0.distcp | | |-- __7_0.distcp | | |-- __8_0.distcp | | `-- __9_0.distcp | |-- tokenizer | | |-- chat_template.jinja | | |-- special_tokens_map.json | | |-- tokenizer.json | | `-- tokenizer_config.json | `-- weights | |-- __0_0.distcp | |-- __10_0.distcp | |-- __11_0.distcp | |-- __12_0.distcp | |-- __13_0.distcp | |-- __14_0.distcp | |-- __15_0.distcp | |-- __1_0.distcp | |-- __2_0.distcp | |-- __3_0.distcp | |-- __4_0.distcp | |-- __5_0.distcp | |-- __6_0.distcp | |-- __7_0.distcp | |-- __8_0.distcp | `-- __9_0.distcp |-- train_dataloader.pt `-- training_info.json 6 directories, 39 files ```
クリーンアップ
料金が発生しないようにするには、リソースを削除します。
helm delete ray-cluster
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_LOCATION}
gcloud storage rm -r gs://${GS_BUCKET}