1. מבוא
אם אתם מעדיפים להריץ את הסקריפטים הארוזים ישירות בלי להשתמש במדריך המפורט, תוכלו למצוא אותם במאגר GoogleCloudPlatform/devrel-demos.
ב-Codelab הזה תלמדו איך לפרוס צינור עיבוד נתונים לאימון ביצועים גבוהים ללמידת חיזוק (RL) באמצעות Google Kubernetes Engine (GKE) ו-Managed Lustre.
עומסי עבודה של למידת חיזוק, במיוחד כאלה שמשתמשים באלגוריתמים כמו Group Relative Policy Optimization (GRPO), יוצרים כמויות עצומות של נתונים במהלך 'יצירת חוויה' ודורשים יצירת נקודות ביקורת לעיתים קרובות. אחסון אובייקטים רגיל עלול לגרום לצווארי בקבוק במהלך פרצי קלט/פלט כאלה, ולהשאיר מאיצים יקרים ללא פעולה.
כדי למנוע את צווארי הבקבוק האלה ולהשיג תפוקת אימון גבוהה יותר, תשתמשו ב-Managed Lustre, מערכת קבצים מקבילה.
הפעולות שתבצעו:
- הגדרת משתני סביבה עבור אשכול Ray מבוסס-GPU.
- הקצאת אשכול GPU מסוג Spot ב-GKE ומופע Managed Lustre באמצעות Cluster Toolkit.
- פורסים אשכול KubeRay ומטמיעים את מערכת הקבצים של Lustre.
- שליחה של עומס עבודה לאימון של NeMo-RL.
- התפוקה גבוהה והחביון של נקודות הבדיקה נמוך באמצעות Cloud Monitoring.

הדרישות
- דפדפן אינטרנט כמו Chrome.
- פרויקט ב-Google Cloud שהחיוב בו מופעל.
ה-Codelab הזה מיועד למשתמשים טכניים מתקדמים, למהנדסי פלטפורמות ולחוקרי AI שמכירים את GKE ואת מושגי האחסון.
משך זמן כולל משוער: 45 עד 60 דקות בתוספת שעתיים של זמן הדרכה
2. לפני שמתחילים
יצירת פרויקט ב-Google Cloud
- במסוף Google Cloud, בוחרים או יוצרים פרויקט בענן של Google.
- הקפידו לוודא שהחיוב מופעל בפרויקט שלכם ב-Cloud.
הפעלת Cloud Shell
Cloud Shell היא סביבת שורת פקודה שפועלת ב-Google Cloud וכוללת מראש את הכלים הנדרשים.
- לוחצים על Activate Cloud Shell בחלק העליון של מסוף Google Cloud.
- אחרי שמתחברים ל-Cloud Shell, מאמתים את האימות:
gcloud auth list - מוודאים שהפרויקט מוגדר:
gcloud config get project - אם הפרויקט לא מוגדר כמו שציפיתם, מגדירים אותו:
export PROJECT_ID=<YOUR_PROJECT_ID> gcloud config set project $PROJECT_ID
התקנת Cluster Toolkit
בשיעור הזה נשתמש ב-Cluster Toolkit (gcluster) כדי לפרוס את אשכול GKE. הוראות להגדרת Cluster Toolkit מופיעות במדריך ההגדרה של Cluster Toolkit.
הפעלת ממשקי ה-API
מריצים את הפקודה הזו ב-Cloud Shell כדי להפעיל את כל ממשקי ה-API הנדרשים:
gcloud services enable \
container.googleapis.com \
lustre.googleapis.com \
compute.googleapis.com \
servicenetworking.googleapis.com
3. הגדרת משתני סביבה
כדי לשמור על עקביות הפקודות ב-codelab הזה, צריך להגדיר כמה משתני סביבה.
יוצרים קובץ בשם env.sh וממלאים אותו בהגדרות. אפשר להשתמש בתבנית הבאה:
# Environment Variables for the RL Demo execution
export PROJECT_ID="{{'<var>'}}PROJECT_ID{{'</var>'}}"
export ZONE="us-east1-b"
export REGION="us-east1"
export CLUSTER_NAME="ray-a4-gpu-spot"
export HF_TOKEN="{{'<var>'}}YOUR_HF_TOKEN{{'</var>'}}" # Required for downloading models
export WANDB_API_KEY="{{'<var>'}}YOUR_WANDB_API_KEY{{'</var>'}}" # Optional
# Topology defaults
export NUM_NODES="8"
export GPUS_PER_NODE="8" # Fixed for A4/B200 architecture
מחליפים את <YOUR_PROJECT_ID> ואת <YOUR_HF_TOKEN> בערכים האמיתיים.
מריצים את הקובץ כדי לטעון את המשתנים לסשן הנוכחי:
source env.sh
4. פריסת אשכול GKE ו-Managed Lustre באמצעות Cluster Toolkit
בשלב הזה, משתמשים ב-Cluster Toolkit (gcluster) כדי לפרוס אשכול GKE עם Spot GPU ולספק באופן אוטומטי אחסון Managed Lustre באמצעות מנהל התקנים של Lustre CSI ו-PersistentVolumeClaim (lustre-pvc) שהוגדר מראש.
הכנת ה-Blueprint
לפני הפריסה, כדאי לעיין בתוכנית האב examples/gke-a4/gke-a4.yaml (פרטים נוספים זמינים במאמר יצירת אשכול A4):
- הפעלת Lustre מנוהל: מבטלים את ההערה בקטעי המודולים
managed-lustreו-lustre-pvcב-gke-a4.yaml. - הפעלת התוסף RayOperator: מגדירים את
enable_ray_operator: trueבהגדרות המודולgke_clusterב-gke-a4.yaml.
פריסת תשתית
מגדירים את ה-CIDR המורשה לגישה ל-Cloud Shell ומבצעים פריסה באמצעות gcluster deploy:
export AUTHORIZED_CIDR="$(curl -s ifconfig.me)/32"
gcluster deploy examples/gke-a4/gke-a4.yaml \
--vars project_id=${PROJECT_ID},deployment_name=${CLUSTER_NAME},region=${REGION},zone=${ZONE},static_node_count=${NUM_NODES},authorized_cidr=${AUTHORIZED_CIDR},spot=true
מחכים שהפריסה תסתיים. Cluster Toolkit מקצה באופן אוטומטי את רשת ה-VPC, את הקישור בין רשתות שכנות (peering) של Private Service Access (PSA), את Managed Lustre filesystem, את Lustre CSI driver, את התוסף RayOperator ואת בקשת האחסון של Kubernetes (lustre-pvc) בפריסה מתואמת אחת.
5. פריסת אשכול Ray ב-GKE
בשלב הזה תפרסו אשכול KubeRay בצמתי GKE ותתקינו את מערכת הקבצים Lustre באמצעות PersistentVolumeClaim (lustre-pvc) שהוקצה אוטומטית על ידי Cluster Toolkit.
יצירת הגדרה של RayCluster
יוצרים קובץ בשם ray-cluster.yaml. הפקודה הזו מציינת את הצמתים הראשיים והצמתים של העובדים ב-KubeRay, באמצעות סוג המאיץ nvidia-b200 והרכבת נפח האחסון של Lustre ב-/lustre.
cat << EOF > ray-cluster.yaml
apiVersion: ray.io/v1
kind: RayCluster
metadata:
name: ${CLUSTER_NAME}
namespace: default
spec:
rayVersion: '2.54.0'
headGroupSpec:
rayStartParams:
dashboard-host: '0.0.0.0'
template:
spec:
nodeSelector:
cloud.google.com/gke-accelerator: nvidia-b200
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
containers:
- name: ray-head
image: nvcr.io/nvidia/nemo-rl:v0.4.0
ports:
- containerPort: 6379
name: gcs-server
- containerPort: 8265
name: dashboard
- containerPort: 10001
name: client
resources:
limits:
cpu: "32"
memory: "1000Gi"
requests:
cpu: "8"
memory: "64Gi"
volumeMounts:
- mountPath: /lustre
name: lustre-storage
volumes:
- name: lustre-storage
persistentVolumeClaim:
claimName: lustre-pvc
workerGroupSpecs:
- groupName: gpu-worker-group
replicas: ${NUM_NODES}
minReplicas: ${NUM_NODES}
maxReplicas: ${NUM_NODES}
rayStartParams: {}
template:
spec:
nodeSelector:
cloud.google.com/gke-accelerator: nvidia-b200
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
containers:
- name: ray-worker
image: nvcr.io/nvidia/nemo-rl:v0.4.0
resources:
limits:
nvidia.com/gpu: "8"
cpu: "100"
memory: "1000Gi"
requests:
nvidia.com/gpu: "8"
cpu: "100"
memory: "1000Gi"
volumeMounts:
- mountPath: /lustre
name: lustre-storage
- mountPath: /dev/shm
name: dshm
volumes:
- name: lustre-storage
persistentVolumeClaim:
claimName: lustre-pvc
- name: dshm
emptyDir:
medium: Memory
EOF
חיבור לאשכול
מוודאים שהסשן של Cloud Shell מאומת באשכול GKE:
gcloud container clusters get-credentials ${CLUSTER_NAME} \
--region ${REGION} \
--project ${PROJECT_ID}
החלת הגדרות RayCluster
החלת ההגדרה של אשכול Ray:
kubectl apply -f ray-cluster.yaml
אימות סטטוס האשכול
עוקבים אחרי יצירת ה-Pods:
kubectl get pods -w
מחכים עד שהפודים של ה-head וה-worker יהיו במצב Running.
6. שליחת עומס עבודה של למידה עם חיזוקים
בשלב הזה, תגישו את משימת האימון של NeMo-RL GRPO לאשכול Ray.
התחברות ללוח הבקרה של Ray
כדי לשלוח משימות ולראות מדדים, צריך להתחבר ללוח הבקרה של Ray. מכיוון שהלוח נמצא ב-GKE, צריך להשתמש בהעברת פורטים כדי לגשת אליו מ-Cloud Shell:
# Run this in a separate Cloud Shell tab or in the background
kubectl port-forward service/${CLUSTER_NAME}-head-svc 8265:8265 &
יצירת סקריפט ההפעלה
יוצרים קובץ בשם run_nemo_rl.sh. הסקריפט הזה יופעל על העובדים של אשכול Ray. אנחנו משתמשים ב-cat << EOF כדי למלא את משתני הסביבה שהגדרתם קודם.
cat << EOF > run_nemo_rl.sh
#!/bin/bash
set -ex
# Override job runtime conflicts (NeMo-RL passes os.environ to ray.init)
export RAY_OVERRIDE_JOB_RUNTIME_ENV=1
echo "--- Running on Ray Cluster ---"
cd /opt/nemo-rl
# Ensure directories exist on the high-speed Lustre drive
mkdir -p /lustre/huggingface_cache
mkdir -p /lustre/nemo_rl_qwen_72b_ds_cp
echo "Launching NeMo-RL GRPO training..."
uv run python examples/run_grpo_math.py \
--config examples/configs/grpo_math_70B_megatron.yaml \
policy.model_name='Qwen/Qwen2.5-72B-Instruct' \
policy.megatron_cfg.converter_type='Qwen2ForCausalLM' \
logger.wandb_enabled=False \
cluster.num_nodes=${NUM_NODES} \
cluster.gpus_per_node=${GPUS_PER_NODE} \
logger.wandb.name='nemo-rl-grpo-test1' \
grpo.max_num_steps=20 \
grpo.num_generations_per_prompt=8 \
grpo.num_prompts_per_step=32 \
policy.train_global_batch_size=256 \
checkpointing.enabled=True \
checkpointing.save_period=2 \
checkpointing.keep_top_k=2 \
checkpointing.metric_name=null \
checkpointing.checkpoint_dir=/lustre/nemo_rl_qwen_72b_ds_cp/nemo-rl-grpo-test1 \
data.dataset_name='DeepScaler'
EOF
chmod +x run_nemo_rl.sh
יצירת קובץ להתעלמות מ-Ray
כדי למנוע מ-Ray להעלות ספריות גדולות או לא נחוצות, יוצרים קובץ .rayignore:
cat << EOF > .rayignore
cluster-toolkit/
.git/
*.sh.log
EOF
יצירת הגדרה של סביבת זמן ריצה
יוצרים קובץ JSON כדי להעביר משתני סביבה למשימת Ray:
cat << EOF > ray_runtime_env_nemo.json
{
"env_vars": {
"HF_TOKEN": "${HF_TOKEN}",
"WANDB_API_KEY": "${WANDB_API_KEY}",
"HF_HOME": "/lustre/huggingface_cache",
"GLOO_SOCKET_IFNAME": "eth0",
"NCCL_SOCKET_IFNAME": "eth0"
}
}
EOF
שליחת המשרה
משתמשים ב-Ray CLI כדי לשלוח את העבודה לנקודת הקצה של מרכז הבקרה. אם הפקודה ray לא נמצאת ב-Cloud Shell, אפשר להתקין אותה באמצעות pip install ray:
ray job submit \
--address="http://localhost:8265" \
--working-dir . \
--runtime-env ray_runtime_env_nemo.json \
-- bash run_nemo_rl.sh
יומנים יזרמו לטרמינל של Cloud Shell. העבודה תטען את המודל, תפעיל את עובדי Ray ותתחיל את לולאת האימון של GRPO.
7. מעקב אחרי ביצועי האימון
בשלב הזה, תצפו בביצועים של מערכת הקבצים Lustre במהלך האימון והסימון של נקודות ביקורת.
בדיקת יומני האימון
במהלך האימון, יומנים יציינו שנקודות ביקורת נשמרות ב-/lustre/nemo_rl_qwen_72b_ds_cp/nemo-rl-grpo-test1. שימו לב ששמירת נקודות הביקורת מתבצעת באופן אסינכרוני ולא חוסמת את עובדי Ray למשך זמן רב מדי.
כדי לראות את המהירות של יצירת נקודות ביקורת, מחפשים שורות ביומן שמציינות נקודות ביקורת שנשמרו.
צפייה במדדים של Lustre ב-Cloud Console
כדי לראות את המדדים של מכונת Lustre:
- ב-מסוף Google Cloud, מחפשים את Managed Service for Lustre.
- לוחצים על שם המכונה (לדוגמה,
${CLUSTER_NAME}-lustreאוrl-demo-gpu-lustre). - לוחצים על הכרטיסייה מעקב.
כאן אפשר לראות:
- קצב העברת נתונים (בייט לשנייה): אפשר לראות את העליות החדות במהלך יצירת נקודות ביקורת.
- קיבולת: מעקב אחרי נפח האחסון שמשמש לנקודות בקרה.
Lustre יכול לכתוב במהירות גבוהה מאוד, ולכתוב נקודות ביקורת בזמן מינימלי
8. מחיקת משאבי הבדיקה
כדי להרוס את כל התשתית שהוקצתה (אשכול GKE, מאגרי צמתים של GPU, מכונת Lustre מנוהלת ורשת VPC) בפעולה אחת, מריצים את הפקודה הבאה ב-Cloud Shell:
gcluster destroy "${CLUSTER_NAME}"
הפקודה הזו פועלת באופן סינכרוני בחזית, ומפרקת את כל התשתית שמנוהלת על ידי הפריסה. יומני ההתקדמות מוצגים במסוף. צריך לחכות שהפקודה תסתיים לגמרי לפני שסוגרים את סשן Cloud Shell.
9. מזל טוב
סיימתם בהצלחה את ה-codelab Scale Reinforcement Learning with GKE and Managed Lustre.
מה למדתם
- איך משתמשים ב-Cluster Toolkit כדי להקצות אשכול GPU ב-GKE עם מכונות Spot ואחסון Managed Lustre.
- איך פורסים אשכול KubeRay וטוענים אחסון Lustre.
- איך שולחים עומס עבודה לאימון של NeMo-RL GRPO.
- איך בודקים את ביצועי האחסון במהלך האימון.
השלבים הבאים
- כדאי לעיין בתכונות נוספות של NVIDIA NeMo-RL.
- מידע נוסף על Google Cloud AI Hypercomputer
- מעיינים במסמכי העזרה של Managed Service for Lustre.