本教程介绍如何在 Google Kubernetes Engine (GKE) 上编排强化学习 (RL) 的分布式训练环境。您将使用 Ray 和 NVIDIA NeMo RL 框架设置分布式训练环境,以微调模型。
本教程重点介绍如何使用 Ray 和 NeMo RL 在 GKE 上运行群组相对策略优化 (GRPO) 训练流水线。GRPO 是一种强化学习算法,旨在提高模型的推理能力。这种 内存高效的算法通过 消除 Critic 或价值模型来简化 RL 流程,并改用基于群组的相对 计算。
在运行本教程之前,我们建议您先完成 在 GKE 上使用 verl 微调和扩缩强化学习 教程。以下教程使用与在 GKE 上使用 verl 微调和伸缩强化学习教程相同的集群设置和配置。
背景
以下部分简要介绍了本教程中使用的概念。
强化学习 (RL)
RL 通过经验、探索和反馈(而不是静态模仿)来训练模型。虽然预训练会教模型说什么,但基于人类反馈的强化学习 (RLHF) 会教模型如何提供帮助、确保安全和保持逻辑性。RL 充当基础模型与针对特定用例微调的模型之间的桥梁。
如需了解详情,请参阅 什么是强化学习?
群组相对策略优化 (GRPO)
GRPO 是一种由 DeepSeek 推广的算法,它通过移除 Critic 模型,为 LLM 对齐提供了一种内存高效的 替代方案,即近端策略优化 (PPO)。GRPO 不使用 Critic 网络,而是为同一提示生成一组响应,并使用该组的平均奖励作为基准。
如需了解详情,请参阅 GRPO。
NVIDIA NeMo RL
NeMo RL 是 NVIDIA 的开源后训练库,专为可伸缩的 RL 而设计。作为更广泛的 NeMo 框架生态系统的一部分,NeMo RL 既支持在单个 GPU 上进行小规模实验,也支持跨数千个 GPU 进行多节点部署。
如需了解详情,请参阅 NVIDIA NeMo RL。
GSM8k 数据集
在本教程中,您将使用 GSM8k 数据集,其中包含 8,500 个高质量、语言多样的中小学数学文字题。
通过使用 GSM8k 和 GRPO,模型会针对同一问题生成一组 n 个不同的响应。GRPO 会将这些响应与群组平均值进行比较。与群组中的其他路径相比,模型对于始终正确且逻辑合理的路径会获得更多奖励。随着时间的推移,模型会了解到,清晰地阐述步骤是最大限度提高奖励的最可靠方法,从而有效地减少低性能答案的奖励。
如需了解详情,请参阅 GSM8k。
目标
本教程介绍如何通过完成以下步骤,使用 NeMo RL 在 GKE 上设置 RL:
- 准备环境。
- 设置具有 B200 或 H200 GPU 的 GKE 集群。
- 配置 KubeRay 以管理分布式 Ray 集群。
- 使用 Managed Lustre 实现高性能存储。
- 运行使用 NeMo RL 的 GRPO 训练作业。
准备工作
- 登录您的 Google Cloud 账号。如果您是 Google Cloud的新用户, 请创建一个账号,以评估我们的产品在 实际场景中的表现。新客户还可获享 $300 赠金,用于 运行、测试和部署工作负载。
-
安装 Google Cloud CLI。
-
如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI。
-
如需初始化 gcloud CLI,请运行以下命令:
gcloud init -
选择或创建项目所需角色
- 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
-
创建项目:如需创建项目,您需要拥有 Project Creator 角色
(
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 项目名称。
-
验证是否已为您的 Google Cloud 项目启用结算功能。
启用必需的 API:
启用 API 所需的角色
如需启用 API,您需要拥有 Service Usage Admin IAM 角色 (
roles/serviceusage.serviceUsageAdmin),该角色包含serviceusage.services.enable权限。了解如何授予 角色。gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
安装 Google Cloud CLI。
-
如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI。
-
如需初始化 gcloud CLI,请运行以下命令:
gcloud init -
选择或创建项目所需角色
- 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
-
创建项目:如需创建项目,您需要拥有 Project Creator 角色
(
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 项目名称。
-
验证是否已为您的 Google Cloud 项目启用结算功能。
启用必需的 API:
启用 API 所需的角色
如需启用 API,您需要拥有 Service Usage Admin IAM 角色 (
roles/serviceusage.serviceUsageAdmin),该角色包含serviceusage.services.enable权限。了解如何授予 角色。gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
向您的用户账号授予角色。对以下每个 IAM 角色运行以下命令一次:
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 和 H200 GPU 配额。如需了解 详情,请参阅 规划 GPU 配额 和 GPU 配额。
准备环境
在本教程中,您将使用 Cloud Shell。
前往 Google Cloud 控制台。
在 Google Cloud 控制台窗口顶部,点击 激活 Cloud Shell 按钮。
设置以下环境变量:
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/16为 RDMA 创建 VPC 网络和子网,其中包括 8 个 GPU 的 8 个子网:
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 或 Standard 集群中设置 NeMo RL。我们建议您使用 Autopilot 集群获得全代管式 Kubernetes 体验。如需选择最适合您的工作负载的 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-7安装 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 存储分区和 Managed Lustre 实例,该实例会预配 RL 工作负载所需的高性能存储空间。
创建 Cloud Storage 存储桶:
gcloud storage buckets create gs://${GS_BUCKET} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-hierarchical-namespace \ --uniform-bucket-level-access创建 Kubernetes 服务账号 (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/nemoRL检查
values.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在本教程中,您将使用两个工作器节点。如果您想更改工作器节点的数量,请更改
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 33h验证 Ray 集群是否正在运行:
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此命令会在您的本地机器与 GKE 集群中的 Ray 头节点之间启动端口转发。请注意,此会话处于活跃状态时,您的终端将 被占用;如需继续操作,请打开单独的 终端实例。
修改
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 会将检查点存储在配置的路径中。
安装 apt tree 实用程序:
apt install tree如需监控 GRPO 作业的运行状况,请检查 Ray 头节点的日志:
kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -c ray-head -- bash输出类似于以下内容:
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}