Ce tutoriel explique comment orchestrer un environnement d'entraînement distribué pour l'apprentissage par renforcement sur Google Kubernetes Engine (GKE). Vous utilisez Ray et le framework verl (Volcano Engine Reinforcement Learning) pour configurer un environnement d'entraînement distribué afin d'affiner un modèle Qwen2.5-32B-Instruct sur l'ensemble de données GSM8K.
Ce tutoriel se concentre sur le pipeline d'entraînement Group Relative Policy Optimization (GRPO) sur GKE avec Ray et verl. GRPO est un algorithme d'apprentissage par renforcement conçu pour améliorer la capacité de raisonnement d'un modèle. Cet algorithme économe en mémoire simplifie le processus d'apprentissage par renforcement (RL) en éliminant le Critic, ou modèle de valeur, et en utilisant plutôt un calcul relatif basé sur des groupes.
Ce tutoriel est un bon point de départ si vous devez configurer un environnement d'entraînement distribué dans lequel les données, les pondérations du modèle et le moteur d'entraînement sont dissociés pour plus d'efficacité.
Ce tutoriel est compatible avec les architectures de GPU suivantes :
- Nœuds GPU basés sur Intel ou AMD : configurez et mettez à l'échelle à l'aide des GPU NVIDIA B200 ou H200.
- Nœuds A4X (GB200) basés sur Arm : configurez et mettez à l'échelle à l'aide des superchips NVIDIA GB200 Grace Blackwell, en utilisant l'allocation dynamique des ressources (DRA) et Multi-Node NVLink (IMEX) de GKE.
Arrière-plan
Les sections suivantes présentent brièvement les concepts utilisés dans ce tutoriel.
Apprentissage par renforcement
L'apprentissage par renforcement enseigne aux modèles par l'expérience, l'exploration et le retour d'informations plutôt que par l'imitation statique. Bien que le pré-entraînement apprenne à un modèle quoi dire, l'apprentissage par renforcement qui utilise le feedback humain (RLHF) lui apprend à être utile, sûr et logique. L'apprentissage par renforcement sert de pont entre un modèle de base et un modèle affiné pour un cas d'utilisation spécialisé.
Pour en savoir plus, consultez Qu'est-ce que l'apprentissage par renforcement ?
Optimisation des stratégies relatives aux groupes (GRPO)
GRPO, un algorithme popularisé par DeepSeek, offre une alternative économe en mémoire à l'optimisation de la politique proximale (PPO) pour l'alignement des LLM en supprimant le modèle Critic. Au lieu d'un réseau Critic, GRPO génère un groupe de réponses pour la même requête et utilise la récompense moyenne de ce groupe comme référence.
Pour en savoir plus, consultez GRPO.
Volcano Engine Reinforcement Learning (verl)
verl est un framework hautes performances conçu pour gérer les modèles complexes de mémoire et de calcul du RL basé sur les LLM.
Pour en savoir plus, consultez verl.
Objectifs
Ce tutoriel vous explique comment configurer l'apprentissage par renforcement sur GKE avec verl en suivant les étapes suivantes :
- Configurez un cluster GKE avec des GPU A4X (superchips GB200), A4 (GPU B200) ou A3 Ultra (GPU H200).
- Configurez KubeRay pour gérer un cluster Ray distribué.
- Utilisez Cloud Storage FUSE pour installer un bucket Cloud Storage sur tous les nœuds.
- Exécutez un job d'entraînement GRPO à l'aide de verl pour aligner le modèle Qwen2.5-32B-Instruct avec l'ensemble de données GSM8K.
Avant de commencer
- Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits sans frais pour exécuter, tester et déployer des charges de travail.
-
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez les API requises :
Rôles requis pour activer les API
Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (
roles/serviceusage.serviceUsageAdmin), qui contient l'autorisationserviceusage.services.enable. Découvrez comment attribuer des rôles.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez les API requises :
Rôles requis pour activer les API
Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (
roles/serviceusage.serviceUsageAdmin), qui contient l'autorisationserviceusage.services.enable. Découvrez comment attribuer des rôles.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Attribuez des rôles à votre compte utilisateur. Exécutez la commande suivante une fois pour chacun des rôles IAM suivants :
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Remplacez les éléments suivants :
PROJECT_ID: ID de votre projetUSER_IDENTIFIER: identifiant de votre compte utilisateur . Par exemple,myemail@example.com.ROLE: rôle IAM que vous accordez à votre compte utilisateur.
- Créez un compte Hugging Face si vous n'en possédez pas.
- Assurez-vous de disposer d'un jeton Hugging Face.
- Assurez-vous que votre projet dispose d'un quota suffisant pour les A4X (superchips GB200), les A4 (GPU B200) ou les A3 Ultra (GPU H200). Pour en savoir plus, consultez Planifier le quota de GPU et Quota de GPU.
- Assurez-vous de disposer d'une réservation de capacité active pour votre type de machine GPU. Pour en savoir plus, consultez Réserver de la capacité via l'équipe chargée de votre compte.
- Pour la configuration A4X (GB200), assurez-vous d'avoir installé Helm.
Préparer votre environnement
Dans ce tutoriel, vous utilisez Cloud Shell.
Accédez à la consoleGoogle Cloud .
En haut de la fenêtre de la console Google Cloud , cliquez sur le bouton Activer Cloud Shell.
Définissez les variables d'environnement :
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_REGION=CONTROL_PLANE_REGION export NODE_ZONE=NODE_ZONE export CLUSTER_NAME=CLUSTER_NAME export KSA_NAME=KSA_NAME export GS_BUCKET=BUCKET_NAME-${PROJECT_ID} export NAMESPACE=default export GPU_TYPE=GPU_TYPE export MACHINE_TYPE=MACHINE_TYPE export RESERVATION=RESERVATION export HF_TOKEN=YOUR_HUGGING_FACE_TOKEN # A4 (B200 GPUs) or A3 Ultra (H200 GPUs) only variables export GVNIC_NETWORK_PREFIX=YGVNIC_NAME export RDMA_NETWORK_PREFIX=RDMA_NAME # A4X (GB200 Superchips) only variables export NUM_GPU_NODES=4 export VERL_IMAGE=verlai/verl:vllm023.aarch64.dev1 export VERL_REF=ddbcdb7Remplacez les valeurs suivantes :
CONTROL_PLANE_REGION: région Compute Engine du plan de contrôle du cluster GKE.NODE_ZONE: zone où les nœuds sont réservés. Pour en savoir plus, consultez la section Disponibilité des GPU.CLUSTER_NAME: nom de votre cluster GKE.KSA_NAME: nom de votre compte de service Kubernetes.BUCKET_NAME: nom de base de votre bucket Cloud Storage. Vous n'avez pas besoin de spécifier le préfixegs://.GPU_TYPE: accélérateur que vous avez réservé dans la réservation de capacité Compute Engine. Il doit s'agir de l'une des options suivantes :nvidia-gb200: A4X (superchips GB200)nvidia-b200: A4 (GPU B200)nvidia-h200-141gb: A3 Ultra (GPU H200)
MACHINE_TYPE: type de machine à utiliser :- Pour les A4X (superchips GB200), utilisez
a4x-highgpu-4g. - Pour les A4 (GPU B200), utilisez
a4-highgpu-8gou version ultérieure. - Pour les A3 Ultra (GPU H200), utilisez
a3-ultragpu-8gou une version ultérieure.
- Pour les A4X (superchips GB200), utilisez
RESERVATION: nom de votre réservation de capacité.YOUR_HUGGING_FACE_TOKEN: votre jeton Hugging Face.GVNIC_NAME(A4 ou A3 Ultra uniquement) : préfixe du nom du réseau gVNIC. Vous pouvez utiliser le préfixe de votre choix.RDMA_NAME(A4 ou A3 Ultra uniquement) : préfixe du réseau RDMA (Remote Direct Memory Access). Vous pouvez utiliser le préfixe de votre choix.
Configurer l'infrastructure
Dans cette section, vous allez créer des réseaux VPC standards et le cluster GKE.
Créer un réseau et des sous-réseaux RDMA (A4 et A3 Ultra uniquement)
Cette section n'est obligatoire que pour les GPU A4 et A3 Ultra.
Si vous utilisez des GPU A4X (GB200), ignorez cette section et passez directement à Créer le cluster GKE. Pour les GPU A4X (GB200), GKE crée automatiquement les réseaux lorsque le pool de nœuds utilise le profil de réseau d'accélérateur auto. Le plan Cluster Toolkit active ce profil à l'aide de l'option enable_dranet:true.
Créez un réseau VPC pour l'interface gVNIC :
gcloud compute networks create ${GVNIC_NETWORK_PREFIX}-net \ --subnet-mode=custom \ --project=${PROJECT_ID} gcloud compute networks subnets create ${GVNIC_NETWORK_PREFIX}-sub \ --network=${GVNIC_NETWORK_PREFIX}-net \ --region=${CONTROL_PLANE_REGION} \ --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/16Créez un réseau VPC et des sous-réseaux pour RDMA avec huit sous-réseaux pour huit GPU :
gcloud beta compute networks create ${RDMA_NETWORK_PREFIX}-net \ --network-profile=${NODE_ZONE}-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 \ --region=${CONTROL_PLANE_REGION} \ --range=192.168.$((N+1)).0/24 & done waitClonez l'exemple de dépôt :
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samplesAccédez au répertoire de travail :
cd ai-ml/verl-on-gke
Créer le cluster GKE
Créez le cluster GKE correspondant à votre architecture GPU :
A4 et A3 Ultra
Sélectionnez le mode de cluster GKE que vous souhaitez utiliser :
Autopilot
Créez un cluster Autopilot :
gcloud container clusters create-auto ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --enable-multi-networking \ --enable-ray-operatorObtenez les identifiants de votre cluster :
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION}Installez le programme d'installation NCCL RDMA pour Autopilot :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer-autopilot.yaml
Standard
Créez un cluster standard :
gcloud container clusters create ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --enable-dataplane-v2 \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --enable-ip-alias \ --enable-multi-networking \ --addons=RayOperator,GcsFuseCsiDriver \ --machine-type=c2-standard-16 \ --num-nodes=1 \ --min-nodes=1 \ --max-nodes=5 \ --enable-autoscalingObtenez les identifiants de votre cluster :
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}Créez le pool de nœuds GPU. Ces pools de nœuds utilisent votre réservation pour garantir la disponibilité. Nous commençons par deux nœuds :
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --node-locations=${NODE_ZONE} \ --machine-type=${MACHINE_TYPE} \ --accelerator=type=${GPU_TYPE},count=8,gpu-driver-version=DEFAULT \ --reservation-affinity=specific \ --reservation=${RESERVATION} \ --enable-autoscaling \ --num-nodes=2 \ --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-7Installez le programme d'installation NCCL RDMA utilisé pour les clusters standards :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
A4X
Créez le cluster GKE et le pool de nœuds à l'aide du blueprint Cluster Toolkit
gke-a4x. Le blueprint provisionne le cluster GKE, y compris le pool de nœuds A4X lié à votre réservation, les réseaux d'accélérateurs (un gVNIC supplémentaire et quatre rails RDMA) et le pilote DRANET géré qui expose les cartes d'interface réseau CX-7 en tant que périphériques DRA.Suivez les instructions de déploiement du blueprint pour configurer vos paramètres (tels que
PROJECT_ID,CONTROL_PLANE_REGION,NODE_ZONE, la réservation etNUM_GPU_NODES), puis déployez le cluster. Vous pouvez également suivre le guide de création de cluster GKE A4X pour créer le cluster manuellement.Obtenez les identifiants de votre cluster :
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}Vérifiez que le cluster expose les cartes d'interface réseau RDMA via DRA :
kubectl get deviceclassesLe résultat doit inclure
mrdma.google.com.Vérifiez que les nœuds A4X sont présents :
kubectl get nodes -l cloud.google.com/gke-accelerator=nvidia-gb200Installez le plug-in NCCL gIB (variante A4X) :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-rdma/nccl-rdma-installer-a4x.yamlInstallez le pilote NVIDIA DRA, qui fournit des canaux
ComputeDomain(IMEX) pour NVLink multinœud :helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update kubectl create namespace nvidia-dra-driver-gpu kubectl apply -f - <<EOF apiVersion: v1 kind: ResourceQuota metadata: name: nvidia-dra-driver-gpu-quota namespace: nvidia-dra-driver-gpu spec: hard: pods: "$((2 * NUM_GPU_NODES + 1))" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: - system-node-critical - system-cluster-critical EOF helm upgrade --install nvidia-dra-driver-gpu nvidia/nvidia-dra-driver-gpu \ --version=25.3.1 --namespace nvidia-dra-driver-gpu \ --set nvidiaDriverRoot=/home/kubernetes/bin/nvidia \ --set resources.gpus.enabled=false \ --set kubeletPlugin.tolerations[0].key=nvidia.com/gpu \ --set kubeletPlugin.tolerations[0].operator=Exists \ --set kubeletPlugin.tolerations[1].key=kubernetes.io/arch \ --set kubeletPlugin.tolerations[1].operator=ExistsInstallez l'opérateur KubeRay, limité à l'espace de noms de la charge de travail :
kubectl create namespace ${NAMESPACE} helm repo add kuberay https://ray-project.github.io/kuberay-helm/ && helm repo update helm upgrade --install kuberay-operator kuberay/kuberay-operator \ --namespace ${NAMESPACE} \ --set singleNamespaceInstall=true --set "watchNamespace={${NAMESPACE}}"
Configurer les mappages réseau (A4 et A3 Ultra uniquement)
Cette étape est requise pour les configurations de GPU standards (A4 et A3 Ultra uniquement). Si vous utilisez A4X (GB200), GKE gère automatiquement les interfaces réseau. Vous pouvez donc ignorer cette section.
Inspectez le fichier manifeste
network-mapping.yaml:Appliquez le fichier manifeste :
envsubst < network-mapping.yaml > network-mapping-updated.yaml kubectl apply -f network-mapping-updated.yaml
Préparer les données et le stockage
Configurez les ressources Cloud Storage et Kubernetes :
Créez un bucket Cloud Storage :
gcloud storage buckets create gs://${GS_BUCKET} \ --location=${CONTROL_PLANE_REGION} \ --enable-hierarchical-namespace \ --uniform-bucket-level-accessCréez un compte de service Kubernetes (KSA) et associez-le au bucket :
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"Créez le Secret pour Hugging Face :
kubectl create secret generic hf-secret --from-literal=hf_api_token=${HF_TOKEN}Inspectez le fichier manifeste
gcsfuse-storage.yaml:Appliquez le fichier manifeste :
envsubst < gcsfuse-storage.yaml > gcsfuse-storage-updated.yaml kubectl apply -f gcsfuse-storage-updated.yaml
Préparer le modèle et les données
Remplissez votre bucket Cloud Storage avec les pondérations et les ensembles de données du modèle. Vous pouvez exécuter ces commandes en local ou sur un pod GKE pour remplir le bucket :
Clonez le dépôt verl, préparez l'environnement virtuel et traitez l'ensemble de données GSM8K :
git clone https://github.com/volcengine/verl.git git -C verl checkout ${VERL_REF} VENV_DIR=.venv python3 -m venv $VENV_DIR source $VENV_DIR/bin/activate pip install verl python verl/examples/data_preprocess/gsm8k.py --local_save_dir ~/data/gsm8kTéléchargez le modèle Qwen2.5-32B-Instruct à l'aide de la CLI Hugging Face (cela nécessite environ 66 Go d'espace disque) :
hf download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-InstructImportez le modèle, les données et le code Verl dans votre bucket 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://${GS_BUCKET}/gsm8k/
Déployer la ressource personnalisée RayCluster
Déployez une ressource personnalisée RayCluster, qui se compose d'un pod principal système et de plusieurs pods de nœuds de calcul compatibles avec les GPU.
A4 et A3 Ultra
Sélectionnez le mode de cluster GKE que vous avez utilisé pour créer votre cluster :
Autopilot
Déployez le RayCluster. Enregistrez le code suivant dans
ray-cluster-auto.yaml:Appliquez le RayCluster :
envsubst < ray-cluster-auto.yaml > ray-cluster-auto-updated.yaml kubectl apply -f ray-cluster-auto-updated.yaml
Standard
Déployez le RayCluster. Enregistrez la configuration suivante dans
ray-cluster-standard.yaml:Appliquez le RayCluster :
envsubst < ray-cluster-standard.yaml > ray-cluster-updated.yaml kubectl apply -f ray-cluster-updated.yaml
A4X
Créez le
ResourceClaimTemplateRDMA et leComputeDomainNVIDIA. Chaque pod de nœud de calcul GPU revendique quatre cartes d'interface réseau RDMA (tous les rails de son nœud) et un canal IMEX. Enregistrez le fichier manifeste suivant danscompute-domain-a4x.yaml:apiVersion: resource.k8s.io/v1 kind: ResourceClaimTemplate metadata: name: verl-rdma-nic namespace: ${NAMESPACE} spec: spec: devices: requests: - name: nic exactly: deviceClassName: mrdma.google.com allocationMode: ExactCount count: 1 --- apiVersion: resource.nvidia.com/v1beta1 kind: ComputeDomain metadata: name: verl-compute-domain namespace: ${NAMESPACE} spec: numNodes: ${NUM_GPU_NODES} channel: resourceClaimTemplate: name: verl-compute-domain-channelAppliquez le fichier manifeste :
kubectl apply -f compute-domain-a4x.yamlDéployez le RayCluster. Le pod principal Ray s'exécute sur un nœud A4X sans demander de GPU (car l'image est
arm64uniquement). Enregistrez les configurations suivantes dansray-cluster-a4x.yaml:apiVersion: ray.io/v1 kind: RayCluster metadata: name: gb200-ray-cluster namespace: ${NAMESPACE} spec: rayVersion: '2.49.0' headGroupSpec: rayStartParams: dashboard-host: '0.0.0.0' num-cpus: "0" template: metadata: annotations: gke-gcsfuse/volumes: "true" spec: serviceAccountName: ${KSA_NAME} nodeSelector: cloud.google.com/gke-accelerator: nvidia-gb200 tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule - key: kubernetes.io/arch operator: Exists effect: NoSchedule containers: - name: ray-head image: ${VERL_IMAGE} lifecycle: postStart: exec: command: - /bin/bash - -c - pip3 install --quiet TransferQueue==0.1.8 ports: - containerPort: 6379 name: gcs-server - containerPort: 8265 name: dashboard - containerPort: 10001 name: client resources: limits: cpu: "12" memory: 32Gi ephemeral-storage: 20Gi requests: cpu: "12" memory: 32Gi ephemeral-storage: 20Gi volumeMounts: - mountPath: /tmp/ray name: ray-logs - name: training-bucket-vol mountPath: /data volumes: - name: ray-logs emptyDir: {} - name: training-bucket-vol persistentVolumeClaim: claimName: training-bucket-pvc workerGroupSpecs: - replicas: ${NUM_GPU_NODES} minReplicas: ${NUM_GPU_NODES} maxReplicas: ${NUM_GPU_NODES} groupName: gpu-group rayStartParams: num-cpus: "120" template: metadata: annotations: gke-gcsfuse/volumes: "true" spec: serviceAccountName: ${KSA_NAME} nodeSelector: cloud.google.com/gke-accelerator: nvidia-gb200 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: ray.io/group: gpu-group topologyKey: kubernetes.io/hostname tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule - key: kubernetes.io/arch operator: Exists effect: NoSchedule containers: - name: ray-worker image: ${VERL_IMAGE} lifecycle: postStart: exec: command: - /bin/bash - -c - pip3 install --quiet TransferQueue==0.1.8 env: - name: LD_LIBRARY_PATH value: /usr/local/nvidia/lib64 resources: limits: cpu: "120" memory: 600Gi nvidia.com/gpu: "4" ephemeral-storage: 500Gi requests: cpu: "120" memory: 600Gi nvidia.com/gpu: "4" ephemeral-storage: 500Gi claims: - name: rdma-nic-0 - name: rdma-nic-1 - name: rdma-nic-2 - name: rdma-nic-3 - name: compute-domain-channel volumeMounts: - name: nvidia mountPath: /usr/local/nvidia - name: gib mountPath: /usr/local/gib - name: shared-memory mountPath: /dev/shm - name: ray-tmp-storage mountPath: /tmp - name: training-bucket-vol mountPath: /data resourceClaims: - name: rdma-nic-0 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-1 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-2 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-3 resourceClaimTemplateName: verl-rdma-nic - name: compute-domain-channel resourceClaimTemplateName: verl-compute-domain-channel volumes: - name: gib hostPath: path: /home/kubernetes/bin/gib - name: nvidia hostPath: path: /home/kubernetes/bin/nvidia - name: shared-memory emptyDir: medium: Memory sizeLimit: 200Gi - name: ray-tmp-storage emptyDir: {} - name: training-bucket-vol persistentVolumeClaim: claimName: training-bucket-pvcAppliquez le fichier manifeste RayCluster :
envsubst < ray-cluster-a4x.yaml | kubectl apply -f -Attendez qu'un pod principal et quatre pods de nœuds de calcul soient à l'état
Running:kubectl get pods -w
Lancer le job GRPO
Configurez et envoyez le job d'entraînement par apprentissage par renforcement :
A4 et A3 Ultra
Configurez le transfert de port vers le nœud du tableau de bord Ray. Utilisez une fenêtre de terminal distincte pour cela, car cette commande bloquera le terminal tant qu'elle sera en cours d'exécution. Utilisez Ctrl+C pour l'arrêter :
kubectl port-forward svc/b200-ray-cluster-head-svc 8265:8265Inspectez le fichier manifeste
runtime-env.yaml:Si vous utilisez des GPU H200, remplacez
NCCL_TUNER_CONFIG_PATHpar/usr/local/gib/configs/tuner_config_a3u.txtpb.Ce fichier est utilisé par le client Ray. Vous n'avez pas besoin d'appliquer ce fichier manifeste au cluster.
Envoyez le job à l'aide de
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=/data/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 \ trainer.default_local_dir=/data/verl/checkpoints \ algorithm.adv_estimator=grpo \ actor_rollout_ref.rollout.n=8 \ trainer.total_epochs=2"Surveillez les journaux dans le tableau de bord Ray ou dans la sortie de la console. Recherchez
critic/score/meanpour voir si la valeur augmente, ce qui indique un apprentissage.Une fois l'entraînement terminé, les points de contrôle du modèle entraîné se trouvent dans
gs://$GS_BUCKET/verl/checkpoints.
A4X
Obtenez le nom du pod principal Ray :
export HEAD_POD=$(kubectl get pod -n ${NAMESPACE} -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}')Configurez le fichier d'environnement d'exécution Ray directement sur le pod principal :
kubectl exec ${HEAD_POD} -c ray-head -- bash -c 'mkdir -p /tmp/submit && cat > /tmp/submit/runtime-env.yaml <<EOF working_dir: "." env_vars: PYTHONPATH: "/data/verl" LD_LIBRARY_PATH: "/usr/local/nvidia/lib64:/usr/local/gib/lib64" NCCL_DEBUG: "INFO" NCCL_ENV_PLUGIN: "gcp" HF_HOME: "/data/huggingface_cache" GLOO_SOCKET_IFNAME: "eth0" EOF'Envoyez la tâche d'entraînement GRPO en l'exécutant sur le pod principal Ray :
kubectl exec ${HEAD_POD} -c ray-head -- bash -c 'cd /tmp/submit && \ ray job submit --runtime-env runtime-env.yaml --no-wait -- \ python3 -m verl.trainer.main_ppo \ algorithm.adv_estimator=grpo \ 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=/data/Qwen2.5-32B-Instruct \ actor_rollout_ref.actor.optim.lr=1e-5 \ actor_rollout_ref.actor.ppo_mini_batch_size=64 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=8 \ actor_rollout_ref.actor.use_kl_loss=True \ actor_rollout_ref.actor.strategy=fsdp2 \ actor_rollout_ref.rollout.name=vllm \ actor_rollout_ref.rollout.tensor_model_parallel_size=4 \ actor_rollout_ref.rollout.gpu_memory_utilization=0.6 \ actor_rollout_ref.rollout.n=8 \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=16 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=16 \ algorithm.kl_ctrl.kl_coef=0.001 \ trainer.logger=console \ trainer.n_gpus_per_node=4 \ trainer.nnodes=4 \ trainer.save_freq=10 \ trainer.test_freq=10 \ trainer.total_epochs=2 \ trainer.default_local_dir=/data/verl/checkpoints'Surveillez les journaux des tâches (à l'aide de l'ID unique renvoyé par
ray job submit) :kubectl exec ${HEAD_POD} -c ray-head -- ray job logs <var>JOB_ID</var> --followRemplacez
JOB_ID. Vérifiez que NVLink inter-nœuds est actif en recherchant les lignes NCCL dans les journaux contenantvia P2P/MNNVL.
Effectuer un nettoyage
Pour éviter que des frais ne vous soient facturés, supprimez les ressources :
A4 et A3 Ultra
kubectl delete raycluster b200-ray-cluster
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}
gcloud storage rm -r gs://${GS_BUCKET}
A4X
kubectl delete raycluster gb200-ray-cluster
kubectl delete computedomain verl-compute-domain
gcloud storage rm -r gs://${GS_BUCKET}
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}
Étapes suivantes
- En savoir plus sur Ray sur GKE
- En savoir plus sur la création de clusters A4X sur GKE
- Consulter la documentation Verl