이 튜토리얼에서는 Google Kubernetes Engine (GKE)에서 강화 학습을 위한 분산 학습 환경을 조정하는 방법을 보여줍니다. Ray 및 verl (Volcano Engine 강화 학습) 프레임워크를 사용하여 GSM8K 데이터 세트에서 Qwen2.5-32B-Instruct 모델을 미세 조정하는 분산 학습 환경을 설정합니다.
이 튜토리얼에서는 Ray 및 verl을 사용하여 GKE에서 그룹 상대 정책 최적화 (GRPO) 학습 파이프라인에 중점을 둡니다. GRPO는 모델의 추론 능력을 향상하도록 설계된 강화 학습 알고리즘입니다. 이 메모리 효율적인 알고리즘은 Critic 또는 가치 모델을 제거하고 대신 상대적인 그룹 기반 계산을 사용하여 강화 학습 (RL) 프로세스를 간소화합니다.
이 튜토리얼은 효율성을 위해 데이터, 모델 가중치, 학습 엔진이 분리된 분산 학습 환경을 설정해야 하는 경우 좋은 출발점이 될 수 있습니다.
이 튜토리얼에서는 다음 GPU 아키텍처를 지원합니다.
- Intel 또는 AMD 기반 GPU 노드: Autopilot 경로에 GKE 동적 리소스 할당 (DRA)을 사용하여 NVIDIA B200 또는 H200 GPU를 사용하여 설정하고 확장합니다.
- Arm 기반 A4X (GB200) 노드: GKE 동적 리소스 할당 (DRA) 및 멀티 노드 NVLink (IMEX)를 사용하여 NVIDIA GB200 Grace Blackwell Superchips를 통해 설정하고 확장합니다.
배경
다음 섹션에서는 이 튜토리얼에서 사용되는 개념을 간략하게 설명합니다.
강화 학습 (RL)
RL은 정적 모방이 아닌 경험, 탐색, 피드백을 통해 모델을 학습시킵니다. 사전 학습은 모델에 무엇을 말해야 하는지 가르치지만, 인간 피드백 기반 강화 학습 (RLHF)은 모델에 유용하고 안전하며 논리적인 방법을 가르칩니다. RL은 기본 모델과 특수 사용 사례를 위한 파인 튜닝된 모델을 연결하는 다리 역할을 합니다.
자세한 내용은 강화 학습이란 무엇인가요?를 참조하세요.
그룹 상대 정책 최적화 (GRPO)
DeepSeek에서 대중화한 알고리즘인 GRPO는 비평가 모델을 삭제하여 LLM 정렬을 위한 근위 정책 최적화 (PPO)에 대한 메모리 효율적인 대안을 제공합니다. GRPO는 비평가 네트워크 대신 동일한 프롬프트에 대한 응답 그룹을 생성하고 해당 그룹의 평균 보상을 기준선으로 사용합니다.
자세한 내용은 GRPO를 참고하세요.
Volcano Engine 강화 학습 (verl)
verl은 LLM 기반 RL의 복잡한 메모리 및 컴퓨팅 패턴을 처리하도록 설계된 고성능 프레임워크입니다.
자세한 내용은 verl을 참고하세요.
목표
이 튜토리얼에서는 다음 단계를 완료하여 verl을 사용하여 GKE에서 강화 학습을 설정하는 방법을 보여줍니다.
- A4X (GB200 Superchips), A4 (B200 GPU) 또는 A3 Ultra (H200 GPU)로 GKE 클러스터를 설정합니다.
- 분산 Ray 클러스터를 관리하도록 KubeRay를 구성합니다.
- Cloud Storage FUSE를 사용하여 모든 노드에 Cloud Storage 버킷을 마운트합니다.
- verl을 사용하여 GRPO 학습 작업을 실행하여 Qwen2.5-32B-Instruct 모델을 GSM8K 데이터 세트와 정렬합니다.
시작하기 전에
- 이 튜토리얼에서는 Google Cloud CLI 및
kubectl가 사전 설치된 Cloud Shell을 사용합니다. Cloud Shell을 사용하지 않는 경우 Google Cloud CLI를 설치하고 초기화한 후kubectl를 설치합니다.
- Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체 (IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
Google Cloud 프로젝트를 만들거나 선택합니다.
프로젝트를 선택하거나 만드는 데 필요한 역할
- 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
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를 사용 설정하려면
serviceusage.services.enable권한이 필요합니다. 프로젝트를 만든 경우 소유자 역할 (roles/owner)을 통해 이 권한이 이미 있을 수 있습니다. 그렇지 않으면 서비스 사용량 관리자 역할 (roles/serviceusage.serviceUsageAdmin)을 통해 이 권한을 얻을 수 있습니다. 역할 부여 방법 알아보기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 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
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를 사용 설정하려면
serviceusage.services.enable권한이 필요합니다. 프로젝트를 만든 경우 소유자 역할 (roles/owner)을 통해 이 권한이 이미 있을 수 있습니다. 그렇지 않으면 서비스 사용량 관리자 역할 (roles/serviceusage.serviceUsageAdmin)을 통해 이 권한을 얻을 수 있습니다. 역할 부여 방법 알아보기gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
사용자 계정에 역할을 부여합니다. 다음 각 IAM 역할에 대해 다음 명령어를 한 번씩 실행합니다.
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admin, roles/iam.serviceAccountUsergcloud 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 토큰이 있는지 확인합니다.
- 프로젝트에 A4X (GB200 Superchip), A4 (B200 GPU) 또는 A3 Ultra (H200 GPU) 할당량이 충분한지 확인합니다. 자세한 내용은 GPU 할당량 계획 및 GPU 할당량을 참조하세요.
- GPU 머신 유형에 대한 활성 용량 예약이 있는지 확인합니다. 자세한 내용은 계정팀을 통해 용량 예약을 참조하세요.
- A4X (GB200) 설정의 경우 Helm이 설치되어 있는지 확인합니다.
개발 환경 준비
이 튜토리얼에서는 Cloud Shell을 사용합니다.
Google Cloud 콘솔로 이동합니다.
Google Cloud 콘솔 창 상단에서 Cloud Shell 활성화 버튼을 클릭합니다.
환경 변수를 설정합니다.
A4 및 A3 Ultra
Autopilot
표준
A4X
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_REGION=YOUR_REGION export NODE_ZONE=YOUR_ZONE export CLUSTER_NAME=YOUR_CLUSTER_NAME export KSA_NAME=YOUR_KSA_NAME export GS_BUCKET=YOUR_GCS_BUCKET-${PROJECT_ID} export NAMESPACE=default export GPU_TYPE=YOUR_GPU_TYPE export MACHINE_TYPE=YOUR_MACINE_TYPE export RESERVATION=YOUR_RESERVATION_NAME export HF_TOKEN=YOUR_HF_TOKEN # A4X (GB200 Superchips) only variables export NUM_GPU_NODES=4 export VERL_IMAGE=verlai/verl:vllm023.aarch64.dev1 export VERL_REF=ddbcdb7다음 값을 바꿉니다.
YOUR_REGION: GKE 클러스터 컨트롤 플레인의 Compute Engine 리전입니다.YOUR_ZONE: 노드가 예약된 영역입니다. 자세한 내용은 GPU 가용성을 참조하세요.YOUR_CLUSTER_NAME: GKE 클러스터의 이름입니다. 이 이름은 40자 이하여야 하며 소문자 영숫자 문자와 하이픈으로 구성되어야 합니다.YOUR_KSA_NAME: Kubernetes 서비스 계정의 이름YOUR_GCS_BUCKET: Cloud Storage 버킷의 기본 이름입니다.gs://프리픽스를 지정할 필요가 없습니다.YOUR_GPU_TYPE: Compute Engine 용량 예약에서 예약한 가속기. 다음 값 중 하나여야 합니다.nvidia-gb200: A4X (GB200 Superchips)nvidia-b200: A4 (B200 GPU)nvidia-h200-141gb: A3 Ultra (H200 GPU)
YOUR_MACHINE_TYPE: 사용할 머신 유형입니다.- A4X (GB200 Superchips)의 경우
a4x-highgpu-4g를 사용합니다. - A4 (B200 GPU)의 경우
a4-highgpu-8g이상을 사용합니다. - A3 Ultra (H200 GPU)의 경우
a3-ultragpu-8g이상을 사용합니다.
- A4X (GB200 Superchips)의 경우
YOUR_CPU_MACHINE_TYPE: CPU 기본 노드 풀의 Compute Engine 머신 유형입니다. 클러스터 영역에서 지원되는 vCPU가 16개 이상인highmem머신 유형(예:n4-highmem-16또는n2d-highmem-16)을 사용합니다.YOUR_RESERVATION_NAME: 용량 예약의 이름입니다.YOUR_HF_TOKEN: Hugging Face 토큰입니다.- GKE Standard 클러스터에서 환경을 설정할 때는 다음 변수를 사용하세요.
YOUR_GVNIC_NAME(A4 또는 A3 Ultra만 해당): gVNIC 네트워크 이름의 프리픽스입니다. 원하는 접두사를 사용할 수 있습니다.YOUR_RDMA_NAME(A4 또는 A3 Ultra만 해당): 원격 직접 메모리 액세스 (RDMA) 네트워크의 프리픽스입니다. 원하는 프리픽스를 사용할 수 있습니다.
샘플 저장소를 클론합니다.
튜토리얼의 나머지 부분에서는 샘플 저장소의 클론을 살펴보고 검사하거나 적용해야 하는 특정 파일을 찾습니다.
선택한 GKE 모드의 작업 디렉터리로 이동합니다.
A4 및 A3 Ultra
Autopilot
표준
A4X
디렉터리를 변경할 필요가 없습니다. 다음 섹션으로 바로 진행할 수 있습니다.
인프라 설정
이 섹션에서는 표준 VPC 네트워크와 GKE 클러스터를 만듭니다.
RDMA 네트워크 및 서브넷 만들기 (GKE Standard - A4 및 A3 Ultra만 해당)
A4 및 A3 Ultra
Autopilot
이 섹션은 GKE Standard A4 및 A3 Ultra GPU에만 필요합니다.
Autopilot을 사용하는 경우 이 섹션을 건너뛰고 GKE 클러스터 만들기로 바로 이동하세요. GKE는 필요한 VPC 네트워크와 서브넷을 자동으로 프로비저닝하고 GKE 관리형 DRANET을 사용하여 이러한 리소스를 포드에 할당합니다. 네트워크 인프라를 수동으로 만들 필요가 없습니다.
표준
gVNIC 인터페이스의 VPC 네트워크를 만듭니다.
RDMA용 VPC 네트워크를 만듭니다.
GPU 8개에 대해 RDMA 서브넷 8개를 만듭니다.
A4X
이 섹션은 GKE Standard A4 및 A3 Ultra GPU에만 필요합니다.
A4X (GB200) GPU를 사용하는 경우 이 섹션을 건너뛰고 GKE 클러스터 만들기로 바로 이동하세요. A4X (GB200) GPU 또는 Autopilot의 경우 노드 풀에서 auto 액셀러레이터 네트워크 프로필을 사용하면 GKE에서 네트워크를 자동으로 만듭니다. Cluster Toolkit 청사진은 enable_dranet:true 플래그를 사용하여 이 프로필을 사용 설정합니다.
GKE 클러스터 만들기
GPU 아키텍처에 해당하는 GKE 클러스터를 만듭니다.
A4 및 A3 Ultra
사용할 GKE 클러스터 모드를 선택합니다.
Autopilot
Autopilot 클러스터를 만듭니다.
클러스터의 사용자 인증 정보를 가져옵니다.
표준
표준 클러스터 만들기
클러스터의 사용자 인증 정보를 가져옵니다.
GPU 노드 풀을 만듭니다. 이러한 노드 풀은 예약을 사용하여 가용성을 보장합니다. 두 개의 노드로 시작합니다.
Standard 클러스터에 사용되는 NCCL RDMA 설치 프로그램을 설치합니다.
A4X
클러스터 툴킷
gke-a4x블루프린트를 사용하여 GKE 클러스터 및 노드 풀을 만듭니다. 블루프린트는 예약에 바인딩된 A4X 노드 풀, 가속기 네트워크 (추가 gVNIC 1개와 RDMA 레일 4개), CX-7 NIC를 DRA 기기로 노출하는 관리형 DRANET 드라이버를 비롯한 GKE 클러스터를 프로비저닝합니다.청사진의 배포 안내를 사용하여 파라미터(예:
PROJECT_ID,CONTROL_PLANE_REGION,NODE_ZONE, 예약,NUM_GPU_NODES)를 구성한 후 클러스터를 배포합니다. 또는 A4X GKE 클러스터 만들기 가이드에 따라 클러스터를 수동으로 만들 수 있습니다.- 클러스터의 사용자 인증 정보를 가져옵니다.
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}클러스터가 DRA를 통해 RDMA NIC를 노출하는지 확인합니다.
kubectl get deviceclasses출력에는
mrdma.google.com이 포함되어야 합니다.A4X 노드가 있는지 확인합니다.
kubectl get nodes -l cloud.google.com/gke-accelerator=nvidia-gb200gIB NCCL 플러그인 (A4X 변형)을 설치합니다.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-rdma/nccl-rdma-installer-a4x.yaml멀티 노드 NVLink에
ComputeDomain(IMEX) 채널을 제공하는 NVIDIA DRA 드라이버를 설치합니다.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=Exists워크로드 네임스페이스로 범위가 지정된 KubeRay 연산자를 설치합니다.
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}}"
네트워크 매핑 구성 (GKE Standard - A4 및 A3 Ultra만 해당)
A4 및 A3 Ultra
Autopilot
이 단계는 GKE Standard GPU 설정 (A4 및 A3 Ultra만 해당)에 필요합니다. A4X (GB200)를 사용하는 경우 GKE가 네트워크 인터페이스를 자동으로 관리하므로 이 섹션을 건너뛰세요.
표준
network-mapping.yaml매니페스트를 검사합니다.매니페스트를 적용합니다.
A4X
이 단계는 GKE Standard GPU 설정 (A4 및 A3 Ultra만 해당)에 필요합니다. A4X (GB200)를 사용하는 경우 GKE가 네트워크 인터페이스를 자동으로 관리하므로 이 섹션을 건너뛰세요.
데이터 및 스토리지 준비
Cloud Storage 및 Kubernetes 리소스를 구성합니다.
Cloud Storage 버킷을 만듭니다.
Kubernetes 서비스 계정 (KSA)을 만들고 버킷에 바인딩합니다.
Hugging Face의 보안 비밀을 만듭니다.
gcsfuse-storage.yaml매니페스트를 검사합니다.매니페스트를 적용합니다.
DRANET 설정
DRANET을 구성합니다.
A4 및 A3 Ultra
Autopilot
ComputeClass 매니페스트를 만듭니다.
이전 단계에서 만든
computeclass-dranet.yaml매니페스트와 샘플 저장소에 포함된resourceclaim-dranet.yaml매니페스트를 모두 적용합니다.
표준
DRANET 설정이 필요하지 않습니다. 다음 섹션으로 바로 진행할 수 있습니다.
A4X
DRANET은 Cluster Toolkit에 의해 설정됩니다. 다음 섹션으로 바로 진행하면 됩니다.
모델 및 데이터 준비
Cloud Storage 버킷에 모델 가중치와 데이터 세트를 채웁니다. 이러한 명령어를 로컬에서 또는 GKE 포드에서 실행하여 버킷을 채울 수 있습니다.
A4 및 A3 Ultra
Autopilot
데이터 준비 작업을 구성하는
data-prep-job.yaml매니페스트를 검사합니다.작업을 시작합니다.
포드 상태를 확인합니다.
data-prep-job포드가Running상태에 도달하면 Control+C를 눌러 감시를 중지합니다.작업을 모니터링합니다.
kubectl logs명령어는 포드가Running상태에 도달할 때까지 출력을 최소한으로 반환하거나 출력을 반환하지 않습니다.
표준
데이터 준비 작업을 구성하는
data-prep-job.yaml매니페스트를 검사합니다.작업을 실행합니다.
작업을 모니터링합니다.
A4X
verl 저장소를 클론하고 가상 환경을 준비하고 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/gsm8kHugging Face CLI를 사용하여 Qwen2.5-32B-Instruct 모델을 다운로드합니다(이 다운로드에는 약 66GB의 디스크 공간이 필요함).
hf download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-Instruct모델, 데이터, 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://${GS_BUCKET}/gsm8k/
RayCluster 커스텀 리소스 배포
하나의 시스템 헤드 포드와 여러 GPU 지원 작업자 포드로 구성된 RayCluster 커스텀 리소스를 배포합니다.
A4 및 A3 Ultra
클러스터를 만드는 데 사용한 GKE 클러스터 모드를 선택합니다.
Autopilot
RayCluster 워크로드를 검사합니다.
RayCluster를 적용합니다.
표준
RayCluster 워크로드를 검사합니다.
RayCluster를 적용합니다.
A4X
RDMA
ResourceClaimTemplate및 NVIDIAComputeDomain를 만듭니다. 각 GPU 작업자 포드는 RDMA NIC 4개 (노드의 모든 레일)와 IMEX 채널 1개를 요청합니다. 다음 매니페스트를compute-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-channel매니페스트를 적용합니다.
kubectl apply -f compute-domain-a4x.yamlRayCluster를 배포합니다. Ray 헤드 포드는 GPU를 요청하지 않고 A4X 노드에서 실행됩니다 (이미지가
arm64전용이므로). 다음 구성을ray-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-pvcRayCluster 매니페스트를 적용합니다.
envsubst < ray-cluster-a4x.yaml | kubectl apply -f -하나의 헤드 포드와 네 개의 작업자 포드가
Running상태가 될 때까지 기다립니다.kubectl get pods -w
GRPO 작업 실행
강화 학습 학습 작업을 구성하고 제출합니다.
A4 및 A3 Ultra
클러스터를 만드는 데 사용한 GKE 클러스터 모드를 선택합니다.
Autopilot
Ray 클라이언트를 설정합니다.
Ray 헤드 서비스를 복구합니다.
Ray 대시보드 노드로의 포트 전달을 설정합니다. 이 프로세스는 백그라운드에서 실행되므로 동일한 터미널 세션에서 명령어를 계속 실행할 수 있습니다.
포트 전달 루프를 중지하려면
kill ${PF_LOOP_PID}명령어를 사용합니다.runtime-env.yaml매니페스트를 검사합니다.H200 GPU를 사용하는 경우
NCCL_CONF_FILE환경 변수 값을/usr/local/gib/configs/nccl.a3u.conf로 변경합니다.이 파일은 Ray 클라이언트에서 사용합니다. 이 매니페스트를 클러스터에 적용할 필요가 없습니다.
ray job submit명령어를 사용하여 작업을 제출합니다.학습 작업 로그를 모니터링하고 모델이 학습 중임을 나타내는
critic/score/mean측정항목이 증가하는지 확인합니다.- Ray 대시보드:
- 브라우저에서
http://localhost:8265을 엽니다. Cloud Shell을 사용하는 경우 웹 미리보기를 클릭하고 포트 변경을 선택한 후8265을 입력합니다. - 작업 탭으로 이동합니다.
- 작업 ID를 클릭합니다.
critic키워드로 로그를 필터링하여critic/score/mean를 검사합니다.
- 브라우저에서
터미널: 작업이
--no-wait플래그를 사용하여 비동기식으로 제출되므로 다음 명령어를 실행하여 터미널에서 작업 로그를 스트리밍합니다.
- Ray 대시보드:
학습이 완료되면 디렉터리 콘텐츠를 나열하여 모델 체크포인트가 Cloud Storage 버킷에 저장되었는지 확인합니다.
또는 Google Cloud 콘솔에서 Cloud Storage > 버킷으로 이동하고
YOUR_GCS_BUCKET를 선택한 다음verl/checkpoints폴더를 열어 체크포인트를 확인할 수 있습니다.
표준
Ray 클라이언트를 설정합니다.
Ray 헤드 서비스를 복구합니다.
Ray 대시보드 노드로의 포트 전달을 설정합니다. 프로세스가 백그라운드에서 실행되므로 동일한 터미널 세션에서 명령어를 계속 실행할 수 있습니다.
포트 포워딩 루프를 중지하려면
kill ${PF_PID}명령어를 사용합니다.runtime-env.yaml매니페스트를 검사합니다.H200 GPU를 사용하는 경우
NCCL_TUNER_CONFIG_PATH환경 변수 값을/usr/local/gib/configs/tuner_config_a3u.txtpb로 변경합니다.이 파일은 Ray 클라이언트에서 사용합니다. 이 매니페스트를 클러스터에 적용할 필요는 없습니다.
작업을 제출합니다.
학습 작업 로그를 모니터링하고 모델이 학습 중임을 나타내는
critic/score/mean측정항목이 증가하는지 확인합니다.- Ray 대시보드:
- 브라우저에서
http://localhost:8265을 엽니다. Cloud Shell을 사용하는 경우 웹 미리보기를 클릭하고 포트 변경을 선택한 후8265을 입력합니다. - 작업 탭으로 이동합니다.
- 작업 ID를 클릭합니다.
critic키워드로 로그를 필터링하여critic/score/mean측정항목을 검사합니다.
- 브라우저에서
콘솔 출력:
--no-wait플래그를 사용하여 비동기식으로 작업이 제출되므로 다음 명령어를 실행하여 터미널에서 작업 로그를 스트리밍합니다.
- Ray 대시보드:
학습이 완료된 후 디렉터리 콘텐츠를 나열하여 모델 체크포인트가 Cloud Storage 버킷에 저장되었는지 확인합니다.
또는 Cloud Storage > 버킷으로 이동하고
YOUR_GCS_BUCKET를 선택하고verl/checkpoints폴더를 열어 Google Cloud 콘솔에서 체크포인트를 확인합니다.
A4X
Ray 헤드 포드 이름을 가져옵니다.
export HEAD_POD=$(kubectl get pod -n ${NAMESPACE} -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}')헤드 포드에서 직접 Ray 런타임 환경 파일을 구성합니다.
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'Ray 헤드 포드에서 실행하여 GRPO 학습 작업을 제출합니다.
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'ray job submit에서 반환된 고유 ID를 사용하여 작업 로그를 모니터링합니다.kubectl exec ${HEAD_POD} -c ray-head -- ray job logs <var>JOB_ID</var> --followJOB_ID을 바꿉니다.via P2P/MNNVL가 포함된 로그에서 NCCL 줄을 찾아 교차 노드 NVLink가 활성 상태인지 확인합니다.
삭제
요금이 청구되지 않도록 하려면 리소스를 삭제합니다.
A4 및 A3 Ultra
Autopilot
포트 전달 루프가 백그라운드 세션에서 계속 실행 중이면 종료합니다.
Ray 클러스터를 삭제합니다.
Cloud Storage FUSE를 삭제합니다.
DRANET 리소스를 삭제합니다.
Cloud Storage 버킷을 삭제합니다.
GKE 클러스터를 삭제합니다.
표준
포트 전달 루프가 백그라운드 세션에서 여전히 실행 중인 경우 이를 종료합니다.
Ray 클러스터를 삭제합니다.
Cloud Storage FUSE를 삭제합니다.
Cloud Storage 버킷을 삭제합니다.
GKE 클러스터를 삭제합니다.
VPC 네트워크 및 서브넷을 삭제합니다.
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}