このチュートリアルでは、Google Kubernetes Engine(GKE)で強化学習用の分散トレーニング環境をオーケストレートする方法について説明します。Ray と verl (Volcano Engine Reinforcement Learning)フレームワークを使用して、Qwen2.5-32B-Instruct モデルをファイン チューニングするための分散トレーニング環境を設定します。
このチュートリアルでは、Ray と verl を使用した GKE での Group Relative Policy Optimization(GRPO)トレーニング パイプラインに焦点を当てています。GRPO は、モデルの推論能力を向上させるように設計された強化学習アルゴリズムです。このメモリ効率の高いアルゴリズムは、Critic または値モデルを排除し、相対的なグループベースの計算を使用することで、強化学習(RL)プロセスを簡素化します。
このチュートリアルは、効率を高めるためにデータ、モデルの重み、トレーニング エンジンを分離した分散トレーニング環境を設定する必要がある場合の出発点として適しています。
背景
以降のセクションでは、このチュートリアルで使用する概念の概要について説明します。
強化学習
RL は、静的な模倣ではなく、経験、探索、フィードバックを通じてモデルを学習させます。事前トレーニングではモデルに何を言うかを教えますが、RL(特に人間からのフィードバックを用いた強化学習(RLHF))では、役立つ、安全、論理的な方法を教えます。RL は、特定のユースケースのベースモデルとファイン チューニングされたモデルの橋渡しとして機能します。
詳細については、強化学習とはをご覧ください。
Volcano Engine Reinforcement Learning(verl)
verl は、LLM ベースの RL の複雑なメモリとコンピューティング パターンを処理するように設計された高性能フレームワークです。
詳細については、verl をご覧ください。
Group Relative Policy Optimization(GRPO)
GRPO は、DeepSeek によって普及したアルゴリズムであり、Critic モデルを削除することで、LLM アライメントの Proximal Policy Optimization(PPO)に代わるメモリ効率の高い 方法を提供します。Critic ネットワークの代わりに、GRPO は同じプロンプトに対するレスポンスのグループを生成し、そのグループの平均報酬をベースラインとして使用します。
詳細については、GRPO をご覧ください。
目標
このチュートリアルでは、次の手順に沿って、verl を使用して GKE で強化学習を設定する方法について説明します。
- B200 または H200 GPU を使用して GKE クラスタを設定します。
- 分散 Ray クラスタを管理するように KubeRay を構成します。
- Cloud Storage FUSE を使用して、すべてのノードで Cloud Storage バケットをマウントします。
- verl を使用して GRPO トレーニング ジョブを実行し、Qwen2.5-32B-Instruct モデルを GSM8K データセットに合わせます。
始める前に
- アカウントにログインします。 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 GPU_TYPE=GPU_TYPE export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATION export NODE_LOCATION=NODE_LOCATION export CLUSTER_NAME=CLUSTER_NAME export KSA_NAME=CLUSTER_NAME export GS_BUCKET=BUCKET_NAME-${PROJECT_ID} export NAMESPACE=default export HF_TOKEN=YOUR_HUGGING_FACE_TOKEN export MACHINE_TYPE=MACHINE_TYPE export GKE_VERSION=GKE_VERSION次の値を置き換えます。
CONTROL_PLANE_LOCATION: GKE クラスタ コントロール プレーンの Compute Engine リージョン。GPU_TYPE: Compute Engine の容量予約で予約したアクセラレータ。次のいずれかの値を指定する必要があります。nvidia-b200: NVIDIA B200(180 GB)nvidia-h200-141gb: NVIDIA H200(141 GB)
NODE_LOCATION: GKE ノードのゾーン。NVIDIA B200 または H200 GPU を使用できる ゾーンを選択します。CLUSTER_NAME: GKE クラスタの名前。BUCKET_NAME: Cloud Storage バケットのベース名。gs://プレフィックスを指定する必要はありません。YOUR_HUGGING_FACE_TOKEN: モデル アクセス用の Hugging Face トークン。MACHINE_TYPE: 使用するマシンのタイプ。有効なオプションはc2standard8またはc2standard16です。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 の場合は、
ネットワークに対して次の環境変数を作成します。
export GVNIC_NETWORK_PREFIX="GVNIC-NAME" export RDMA_NETWORK_PREFIX="RDMA-NAME"次の値を置き換えます。
GVNIC-NAME: gVNIC ネットワーク名の接頭辞。任意の接頭辞を使用できます。RDMA-NAME: リモート ダイレクト メモリ アクセス(RDMA)ネットワークの接頭辞。任意の接頭辞を使用できます。
インフラストラクチャを設定する
このセクションでは、RDMA ネットワークと GKE クラスタを作成します。
RDMA ネットワークとサブネットを作成する
gVNIC インターフェース用の VPC ネットワークを作成します。
gcloud compute networks create ${GVNIC_NETWORK_PREFIX}-net \ --subnet-mode=custom \ --project=${PROJECT} 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 beta 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サンプル リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samples作業ディレクトリに移動します。
cd ai-ml/verl-on-gke
GKE クラスタを作成する
GKE Autopilot クラスタまたは GKE Standard クラスタで verl を設定できます。フルマネージドの 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=${REGION}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} \ --location=${ZONE} \ --enable-dataplane-v2 \ --enable-ip-alias \ --enable-multi-networking \ --addons=RayOperator,GcsFuseCsiDriver \ --machine-type=${MACHINE_TYPE} \ --num-nodes=1 \ --min-nodes=1 \ --max-nodes=5 \ --enable-autoscalingクラスタの認証情報を取得します。
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${ZONE}GPU ノードプールを作成します(費用対効果を高めるためにスポット インスタンスを使用します)。
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --location=${NODE_LOCATION} \ --machine-type=${MACHINE_TYPE} \ --accelerator=type=${GPU_TYPE},count=8,gpu-driver-version=DEFAULT \ --spot \ --enable-autoscaling \ --num-nodes=0 \ --total-max-nodes=10 \ --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-7Standard クラスタで使用される NCCL 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 バケットを作成します。
gcloud storage buckets create gs://${GS_BUCKET} --location=${REGION} --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"Hugging Face の Secret を作成します。
kubectl create secret generic hf-secret --from-literal=hf_api_token=${HF_TOKEN}gcsfuse-storage.yamlマニフェストを調べます。次のようにマニフェストを適用します。
kubectl apply -f gcsfuse-storage.yaml
モデルとデータを準備する
これらのコマンドは、ローカルまたは GKE Pod で実行してバケットにデータを入力できます。
verl リポジトリのクローンを作成します。
git clone https://github.com/volcengine/verl.gitHugging Face CLI を使用して Qwen2.5-32B-Instruct モデルをダウンロードします。
huggingface-cli download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-InstructGSM8K データセットを前処理します。
python examples/data_preprocess/gsm8k.py --local_save_dir ~/data/gsm8kモデル、データ、verl コードを Cloud Storage バケットにアップロードします。
gcloud storage cp --recursive verl gs://${GS_BUCKET}/verl gcloud storage cp --recursive Qwen2.5-32B-Instruct gs://${GS_BUCKET}/Qwen2.5-32B-Instruct gcloud storage cp --recursive ~/data/gsm8k/* ${GS_BUCKET}
RayCluster カスタム リソースをデプロイする
RayCluster カスタム リソースをデプロイします。通常、これは 1 つのシステム Pod と複数のワーカー Pod で構成されます。
Autopilot
RayCluster をデプロイします。次の内容を
ray-cluster-auto.yamlに保存します。RayCluster を適用します。
kubectl apply -f ray-cluster.yaml
標準
RayCluster をデプロイします。次の内容を
ray-cluster.yamlに保存します。RayCluster を適用します。
kubectl apply -f ray-cluster.yaml
GRPO ジョブを起動する
Ray ダッシュボード ノードへのポート転送を設定します。
kubectl port-forward svc/b200-ray-cluster-head-svc 8265:8265runtime-env.yamlマニフェストを調べます。H200 GPU を使用する場合は、
NCCL_TUNER_CONFIG_PATHを/usr/local/gib/configs/tuner_config_a3u.txtpbに変更します。このファイルは Ray クライアントで使用されます。このマニフェストをクラスタに適用する必要はありません。
ray job submitを使用してジョブを送信します。ray -- job submit \ --address "http://localhost:8265" \ --runtime-env runtime-env.yaml \ -- \ bash -c " cd /data/verl && PYTHONUNBUFFERED=1 python3 -m verl.trainer.main_ppo \ data.train_files=/data/gsm8k/train.parquet \ data.val_files=/data/gsm8k/test.parquet \ data.train_batch_size=256 \ data.max_prompt_length=512 \ data.max_response_length=512 \ actor_rollout_ref.model.path=Qwen/Qwen2.5-32B-Instruct \ actor_rollout_ref.actor.optim.lr=1e-5 \ actor_rollout_ref.actor.ppo_mini_batch_size=256 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=64 \ actor_rollout_ref.rollout.name=vllm \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=8 \ actor_rollout_ref.rollout.tensor_model_parallel_size=8 \ actor_rollout_ref.rollout.gpu_memory_utilization=0.6 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=4 \ actor_rollout_ref.actor.strategy=fsdp2 \ algorithm.kl_ctrl.kl_coef=0.001 \ trainer.logger=console \ trainer.val_before_train=False \ trainer.n_gpus_per_node=8 \ trainer.nnodes=2 \ trainer.save_freq=10 \ trainer.test_freq=10 \ algorithm.adv_estimator=grpo \ actor_rollout_ref.rollout.n=8 \ trainer.total_epochs=2" 2>&1 | tee verl_demo.logRay ダッシュボードまたは出力でログをモニタリングします。
critic/score/meanが増加していることを確認します。これは学習を示しています。
クリーンアップ
料金が発生しないようにするには、次のリソースを削除します。
kubectl delete raycluster b200-ray-cluster # change to variables
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_LOCATION}
gcloud storage rm -r gs://${GS_BUCKET}