In dieser Anleitung wird gezeigt, wie Sie eine verteilte Trainingsumgebung für Reinforcement Learning in Google Kubernetes Engine (GKE) orchestrieren. Sie verwenden Ray und das Framework verl (Volcano Engine Reinforcement Learning), um eine Umgebung für verteiltes Training einzurichten, in der Sie ein Qwen2.5-32B-Instruct-Modell für das GSM8K-Dataset abstimmen.
In dieser Anleitung geht es um die Trainingspipeline für die Group Relative Policy Optimization (GRPO) in GKE mit Ray und verl. GRPO ist ein Reinforcement-Learning-Algorithmus, der die Fähigkeit eines Modells zum logischen Denken verbessern soll. Dieser speichereffiziente Algorithmus vereinfacht den Prozess des bestärkenden Lernens (Reinforcement Learning, RL), indem er den Critic oder das Wertmodell eliminiert und stattdessen eine relative gruppenbasierte Berechnung verwendet.
Dieses Tutorial ist ein guter Ausgangspunkt, wenn Sie eine Umgebung für verteiltes Training einrichten müssen, in der Daten, Modellgewichte und die Trainings-Engine zur Effizienzsteigerung entkoppelt sind.
Diese Anleitung unterstützt die folgenden GPU-Architekturen:
- GPU-Knoten auf Intel- oder AMD-Basis: Einrichten und Skalieren mit NVIDIA B200- oder H200-GPUs.
- Arm-basierte A4X-Knoten (GB200): Einrichten und skalieren mit NVIDIA GB200 Grace Blackwell-Superchips mit dynamischer Ressourcenzuweisung (Dynamic Resource Allocation, DRA) von GKE und Multi-Node NVLink (IMEX).
Hintergrund
In den folgenden Abschnitten erhalten Sie einen kurzen Überblick über die in diesem Tutorial verwendeten Konzepte.
Bestärkendes Lernen (Reinforcement Learning, RL)
Beim bestärkenden Lernen werden Modelle durch Erfahrung, Erkundung und Feedback trainiert, anstatt durch statische Imitation. Beim Vortraining wird einem Modell beigebracht, was es sagen soll. Beim bestärkenden Lernen durch menschliches Feedback (Reinforcement Learning from Human Feedback, RLHF) wird ihm beigebracht, wie es hilfreich, sicher und logisch sein kann. RL dient als Brücke zwischen einem Basismodell und einem feinabgestimmten Modell für einen speziellen Anwendungsfall.
Weitere Informationen finden Sie unter Was ist bestärkendes Lernen?
Gruppenrelative Richtlinienoptimierung (Group Relative Policy Optimization, GRPO)
GRPO, ein von DeepSeek entwickelter Algorithmus, bietet eine speichereffiziente Alternative zur Proximal Policy Optimization (PPO) für die LLM-Abstimmung, da das Critic-Modell entfernt wird. Anstelle eines Critic-Netzwerks generiert GRPO eine Gruppe von Antworten für denselben Prompt und verwendet die durchschnittliche Belohnung dieser Gruppe als Baseline.
Weitere Informationen finden Sie unter GRPO.
Volcano Engine Reinforcement Learning (VERL)
verl ist ein leistungsstarkes Framework, das für die komplexen Speicher- und Rechenmuster von LLM-basiertem RL entwickelt wurde.
Weitere Informationen finden Sie unter verl.
Ziele
In dieser Anleitung erfahren Sie, wie Sie mit verl Reinforcement Learning in GKE einrichten. Dazu führen Sie die folgenden Schritte aus:
- Richten Sie einen GKE-Cluster mit A4X-Superchips (GB200), A4-GPUs (B200) oder A3 Ultra-GPUs (H200) ein.
- KubeRay zum Verwalten eines verteilten Ray-Clusters konfigurieren
- Stellen Sie einen Cloud Storage-Bucket mit Cloud Storage FUSE auf allen Knoten bereit.
- Führen Sie einen GRPO-Trainingsjob mit verl aus, um das Modell Qwen2.5-32B-Instruct mit dem GSM8K-Dataset abzustimmen.
Hinweis
- Melden Sie sich in Ihrem Google Cloud -Konto an. Wenn Sie mit Google Cloudnoch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
-
Installieren Sie die Google Cloud CLI.
-
Wenn Sie einen externen Identitätsanbieter (IdP) verwenden, müssen Sie sich zuerst mit Ihrer föderierten Identität in der gcloud CLI anmelden.
-
Führen Sie den folgenden Befehl aus, um die gcloud CLI zu initialisieren:
gcloud init -
Erstellen Sie ein Google Cloud Projekt oder wählen Sie eines aus.
Rollen, die zum Auswählen oder Erstellen eines Projekts erforderlich sind
- Projekt auswählen: Für die Auswahl eines Projekts ist keine bestimmte IAM-Rolle erforderlich. Sie können jedes Projekt auswählen, für das Ihnen eine Rolle zugewiesen wurde.
-
Projekt erstellen: Zum Erstellen eines Projekts benötigen Sie die Rolle „Projektersteller“ (
roles/resourcemanager.projectCreator), die die Berechtigungresourcemanager.projects.createenthält. Weitere Informationen zum Zuweisen von Rollen
-
So erstellen Sie ein Google Cloud Projekt:
gcloud projects create PROJECT_ID
Ersetzen Sie
PROJECT_IDdurch einen Namen für das Google Cloud Projekt, das Sie erstellen. -
Wählen Sie das von Ihnen erstellte Google Cloud Projekt aus:
gcloud config set project PROJECT_ID
Ersetzen Sie
PROJECT_IDdurch den Namen Ihres Projekts in Google Cloud .
-
Prüfen Sie, ob die Abrechnung für Ihr Google Cloud Projekt aktiviert ist.
Aktivieren Sie die erforderlichen APIs:
Rollen, die zum Aktivieren von APIs erforderlich sind
Zum Aktivieren von APIs benötigen Sie die IAM-Rolle „Service Usage-Administrator“ (
roles/serviceusage.serviceUsageAdmin), die die Berechtigungserviceusage.services.enableenthält. Weitere Informationen zum Zuweisen von Rollengcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Installieren Sie die Google Cloud CLI.
-
Wenn Sie einen externen Identitätsanbieter (IdP) verwenden, müssen Sie sich zuerst mit Ihrer föderierten Identität in der gcloud CLI anmelden.
-
Führen Sie den folgenden Befehl aus, um die gcloud CLI zu initialisieren:
gcloud init -
Erstellen Sie ein Google Cloud Projekt oder wählen Sie eines aus.
Rollen, die zum Auswählen oder Erstellen eines Projekts erforderlich sind
- Projekt auswählen: Für die Auswahl eines Projekts ist keine bestimmte IAM-Rolle erforderlich. Sie können jedes Projekt auswählen, für das Ihnen eine Rolle zugewiesen wurde.
-
Projekt erstellen: Zum Erstellen eines Projekts benötigen Sie die Rolle „Projektersteller“ (
roles/resourcemanager.projectCreator), die die Berechtigungresourcemanager.projects.createenthält. Weitere Informationen zum Zuweisen von Rollen
-
So erstellen Sie ein Google Cloud Projekt:
gcloud projects create PROJECT_ID
Ersetzen Sie
PROJECT_IDdurch einen Namen für das Google Cloud Projekt, das Sie erstellen. -
Wählen Sie das von Ihnen erstellte Google Cloud Projekt aus:
gcloud config set project PROJECT_ID
Ersetzen Sie
PROJECT_IDdurch den Namen Ihres Projekts in Google Cloud .
-
Prüfen Sie, ob die Abrechnung für Ihr Google Cloud Projekt aktiviert ist.
Aktivieren Sie die erforderlichen APIs:
Rollen, die zum Aktivieren von APIs erforderlich sind
Zum Aktivieren von APIs benötigen Sie die IAM-Rolle „Service Usage-Administrator“ (
roles/serviceusage.serviceUsageAdmin), die die Berechtigungserviceusage.services.enableenthält. Weitere Informationen zum Zuweisen von Rollengcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Weisen Sie Ihrem Nutzerkonto Rollen zu. Führen Sie den folgenden Befehl für jede der folgenden IAM-Rollen einmal aus:
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Ersetzen Sie Folgendes:
PROJECT_ID: Ihre Projekt-ID.USER_IDENTIFIER: Die Kennung für Ihr Nutzerkonto . Beispiel:myemail@example.comROLE: Die IAM-Rolle, die Sie Ihrem Nutzerkonto zuweisen.
- Erstellen Sie ein Hugging Face-Konto, falls Sie noch keines haben.
- Sie benötigen ein Hugging Face-Token.
- Prüfen Sie, ob Ihr Projekt ein ausreichendes Kontingent für A4X-Superchips (GB200), A4-GPUs (B200) oder A3 Ultra-GPUs (H200) hat. Weitere Informationen finden Sie unter GPU-Kontingent planen und GPU-Kontingent.
- Achten Sie darauf, dass Sie eine aktive Kapazitätsreservierung für Ihren GPU-Maschinentyp haben. Weitere Informationen finden Sie unter Kapazität über Ihr Account-Management-Team reservieren.
- Für die Einrichtung von A4X (GB200) muss Helm installiert sein.
Umgebung vorbereiten
In dieser Anleitung verwenden Sie Cloud Shell.
Rufen Sie die Google Cloud Console auf.
Klicken Sie oben im Google Cloud Console-Fenster auf den Button Cloud Shell aktivieren.
Legen Sie die Umgebungsvariablen fest:
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=ddbcdb7Ersetzen Sie die folgenden Werte:
CONTROL_PLANE_REGION: die Compute Engine-Region für die GKE-Cluster-Steuerungsebene.NODE_ZONE: die Zone, in der die Knoten reserviert sind. Weitere Informationen finden Sie unter GPU-Verfügbarkeit.CLUSTER_NAME: Name Ihres GKE-Clusters.KSA_NAME: Der Name Ihres Kubernetes-Dienstkontos.BUCKET_NAME: Der Basisname für Ihren Cloud Storage-Bucket. Sie müssen das Präfixgs://nicht angeben.GPU_TYPE: der Beschleuniger, den Sie in der Compute Engine-Kapazitätsreservierung reserviert haben. Muss einer der folgenden Werte sein:nvidia-gb200: A4X (GB200 Superchips)nvidia-b200: A4 (B200-GPUs)nvidia-h200-141gb: A3 Ultra (H200-GPUs)
MACHINE_TYPE: der zu verwendende Maschinentyp:- Verwenden Sie für A4X-Superchips (GB200)
a4x-highgpu-4g. - Verwenden Sie für A4-GPUs (B200)
a4-highgpu-8goder höher. - Für A3 Ultra (H200-GPUs) verwenden Sie
a3-ultragpu-8goder höher.
- Verwenden Sie für A4X-Superchips (GB200)
RESERVATION: Der Name Ihrer Kapazitätsreservierung.YOUR_HUGGING_FACE_TOKEN: Ihr Hugging Face-Token.GVNIC_NAME(nur A4 oder A3 Ultra): Das Präfix für den gVNIC-Netzwerknamen. Sie können ein beliebiges Präfix verwenden.RDMA_NAME(nur A4 oder A3 Ultra): Das Präfix für das RDMA-Netzwerk (Remote Direct Memory Access). Sie können ein beliebiges Präfix verwenden.
Infrastruktur einrichten
In diesem Abschnitt erstellen Sie Standard-VPC-Netzwerke und den GKE-Cluster.
RDMA-Netzwerk und ‑Subnetze erstellen (nur A4 und A3 Ultra)
Dieser Abschnitt ist nur für A4- und A3 Ultra-GPUs erforderlich.
Wenn Sie A4X-GPUs (GB200) verwenden, überspringen Sie diesen Abschnitt und fahren Sie direkt mit GKE-Cluster erstellen fort. Bei A4X-GPUs (GB200) erstellt GKE die Netzwerke automatisch, wenn für den Knotenpool das Accelerator-Netzwerkprofil auto verwendet wird. Im Cluster Toolkit-Blueprint wird dieses Profil mit dem Flag enable_dranet:true aktiviert.
VPC-Netzwerk für die gVNIC-Schnittstelle erstellen:
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/16Erstellen Sie ein VPC-Netzwerk und Subnetze für RDMA mit 8 Subnetzen für 8 GPUs:
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 waitKlonen Sie das Beispiel-Repository:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samplesWechseln Sie zum Arbeitsverzeichnis:
cd ai-ml/verl-on-gke
GKE-Cluster erstellen
Erstellen Sie den GKE-Cluster, der Ihrer GPU-Architektur entspricht:
A4 und A3 Ultra
Wählen Sie den gewünschten GKE-Clustermodus aus:
Autopilot
Autopilot-Cluster erstellen:
gcloud container clusters create-auto ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --enable-multi-networking \ --enable-ray-operatorRufen Sie Anmeldedaten für Ihren Cluster ab:
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION}Installieren Sie das NCCL RDMA-Installationsprogramm für Autopilot:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer-autopilot.yaml
Standard
Standardcluster erstellen:
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-autoscalingRufen Sie Anmeldedaten für Ihren Cluster ab:
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}Erstellen Sie den GPU-Knotenpool. In diesen Knotenpools wird Ihre Reservierung verwendet, um die Verfügbarkeit zu gewährleisten. Wir beginnen mit zwei Knoten:
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-7Installieren Sie das NCCL RDMA-Installationsprogramm, das für Standardcluster verwendet wird:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
A4X
Erstellen Sie den GKE-Cluster und den Knotenpool mit dem Cluster Toolkit
gke-a4x-Blueprint. Mit dem Blueprint wird der GKE-Cluster bereitgestellt, einschließlich des A4X-Knotenpools, der an Ihre Reservierung gebunden ist, der Beschleunigernetzwerke (ein zusätzliches gVNIC plus vier RDMA-Rails) und des verwalteten DRANET-Treibers, der die CX-7-NICs als DRA-Geräte verfügbar macht.Konfigurieren Sie die Parameter (z. B.
PROJECT_ID,CONTROL_PLANE_REGION,NODE_ZONE, Reservierung undNUM_GPU_NODES) anhand der Bereitstellungsanleitung des Blueprints und stellen Sie dann den Cluster bereit. Alternativ können Sie den Cluster manuell erstellen. Folgen Sie dazu der Anleitung zum Erstellen von GKE-Cluster-Clustern.Rufen Sie Anmeldedaten für Ihren Cluster ab:
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}Prüfen Sie, ob der Cluster RDMA-NICs über DRA bereitstellt:
kubectl get deviceclassesDie Ausgabe muss
mrdma.google.comenthalten.Prüfen Sie, ob die A4X-Knoten vorhanden sind:
kubectl get nodes -l cloud.google.com/gke-accelerator=nvidia-gb200Installieren Sie das gIB-NCCL-Plug-in (A4X-Variante):
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-rdma/nccl-rdma-installer-a4x.yamlInstallieren Sie den NVIDIA DRA-Treiber, der
ComputeDomain-Kanäle (IMEX) für Multi-Node-NVLink bereitstellt: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=ExistsInstallieren Sie den KubeRay-Operator, der auf den Arbeitslast-Namespace beschränkt ist:
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}}"
Netzwerkzuordnungen konfigurieren (nur A4- und A3 Ultra-Instanzen)
Dieser Schritt ist nur für Standard-GPU-Konfigurationen (nur A4 und A3 Ultra) erforderlich. Wenn Sie A4X (GB200) verwenden, verwaltet GKE Netzwerkschnittstellen automatisch. Überspringen Sie diesen Abschnitt.
Prüfen Sie das
network-mapping.yaml-Manifest:Wenden Sie das Manifest an:
envsubst < network-mapping.yaml > network-mapping-updated.yaml kubectl apply -f network-mapping-updated.yaml
Daten und Speicher vorbereiten
Cloud Storage- und Kubernetes-Ressourcen konfigurieren:
Erstellen Sie einen Cloud Storage-Bucket:
gcloud storage buckets create gs://${GS_BUCKET} \ --location=${CONTROL_PLANE_REGION} \ --enable-hierarchical-namespace \ --uniform-bucket-level-accessErstellen Sie ein Kubernetes-Dienstkonto (Kubernetes Service Account, KSA) und binden Sie es an den 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"Secret für Hugging Face erstellen:
kubectl create secret generic hf-secret --from-literal=hf_api_token=${HF_TOKEN}Prüfen Sie das
gcsfuse-storage.yaml-Manifest:Wenden Sie das Manifest an:
envsubst < gcsfuse-storage.yaml > gcsfuse-storage-updated.yaml kubectl apply -f gcsfuse-storage-updated.yaml
Modell und Daten vorbereiten
Füllen Sie Ihren Cloud Storage-Bucket mit den Modellgewichten und Datasets. Sie können diese Befehle lokal oder in einem GKE-Pod ausführen, um den Bucket zu füllen:
Klonen Sie das verl-Repository, bereiten Sie die virtuelle Umgebung vor und verarbeiten Sie das GSM8K-Dataset:
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/gsm8kLaden Sie das Modell Qwen2.5-32B-Instruct mit der Hugging Face-CLI herunter (dazu sind etwa 66 GB Speicherplatz erforderlich):
hf download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-InstructLaden Sie das Modell, die Daten und den verl-Code in Ihren Cloud Storage-Bucket hoch:
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/
Benutzerdefinierte RayCluster-Ressource bereitstellen
Stellen Sie eine benutzerdefinierte RayCluster-Ressource bereit, die aus einem System-Head-Pod und mehreren GPU-gestützten Worker-Pods besteht.
A4 und A3 Ultra
Wählen Sie den GKE-Clustermodus aus, den Sie zum Erstellen Ihres Clusters verwendet haben:
Autopilot
Stellen Sie den Ray-Cluster bereit. Speichern Sie den folgenden Code in
ray-cluster-auto.yaml:Wenden Sie den RayCluster an:
envsubst < ray-cluster-auto.yaml > ray-cluster-auto-updated.yaml kubectl apply -f ray-cluster-auto-updated.yaml
Standard
Stellen Sie den Ray-Cluster bereit. Speichern Sie die folgende Konfiguration in
ray-cluster-standard.yaml:Wenden Sie den RayCluster an:
envsubst < ray-cluster-standard.yaml > ray-cluster-updated.yaml kubectl apply -f ray-cluster-updated.yaml
A4X
Erstellen Sie das RDMA-
ResourceClaimTemplateund das NVIDIA-ComputeDomain. Jeder GPU-Worker-Pod beansprucht vier RDMA-NICs (alle Rails des Knotens) und einen IMEX-Channel. Speichern Sie das folgende Manifest untercompute-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-channelWenden Sie das Manifest an:
kubectl apply -f compute-domain-a4x.yamlStellen Sie den Ray-Cluster bereit. Der Ray-Head-Pod wird auf einem A4X-Knoten ausgeführt, ohne GPUs anzufordern, da das Image nur
arm64ist. Speichern Sie die folgenden Konfigurationen inray-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-pvcWenden Sie das RayCluster-Manifest an:
envsubst < ray-cluster-a4x.yaml | kubectl apply -f -Warten Sie, bis sich ein Head-Pod und vier Worker-Pods im Status
Runningbefinden:kubectl get pods -w
GRPO-Job starten
Konfigurieren und senden Sie den Trainingsjob für das bestärkende Lernen:
A4 und A3 Ultra
Richten Sie die Portweiterleitung zum Ray-Dashboard-Knoten ein. Verwenden Sie dafür ein separates Terminalfenster, da dieser Befehl das Terminal blockiert, solange er ausgeführt wird. Drücken Sie Strg + C, um den Vorgang zu beenden:
kubectl port-forward svc/b200-ray-cluster-head-svc 8265:8265Prüfen Sie das
runtime-env.yaml-Manifest:Wenn Sie H200-GPUs verwenden, ändern Sie
NCCL_TUNER_CONFIG_PATHin/usr/local/gib/configs/tuner_config_a3u.txtpb.Diese Datei wird vom Ray-Client verwendet. Sie müssen dieses Manifest nicht auf den Cluster anwenden.
Senden Sie den Job mit
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"Behalten Sie die Logs im Ray-Dashboard oder in der Konsolenausgabe im Blick. Suchen Sie nach
critic/score/mean, um eine Steigerung zu sehen, die auf Lernen hindeutet.Nach Abschluss des Trainings befinden sich die Prüfpunkte des trainierten Modells in
gs://$GS_BUCKET/verl/checkpoints.
A4X
Rufen Sie den Namen des Ray-Head-Pods ab:
export HEAD_POD=$(kubectl get pod -n ${NAMESPACE} -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}')Konfigurieren Sie die Ray-Laufzeitumgebungsdatei direkt im Haupt-Pod:
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'Senden Sie den GRPO-Trainingsjob, indem Sie ihn auf dem Ray-Head-Pod ausführen:
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'Job-Logs überwachen (mit der eindeutigen ID, die von
ray job submitzurückgegeben wird):kubectl exec ${HEAD_POD} -c ray-head -- ray job logs <var>JOB_ID</var> --followErsetzen Sie
JOB_ID. Prüfen Sie, ob die NVLink-Verbindung zwischen Knoten aktiv ist. Suchen Sie dazu in Logs, dievia P2P/MNNVLenthalten, nach NCCL-Zeilen.
Bereinigen
Löschen Sie die Ressourcen, um Gebühren zu vermeiden:
A4 und 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}
Nächste Schritte
- Informationen zu Ray on GKE
- Informationen zum Erstellen von A4X-Clustern in GKE
- Dokumentation zu Verl ansehen