Neste tutorial, mostramos como orquestrar um ambiente de treinamento distribuído para aprendizado por reforço no Google Kubernetes Engine (GKE). Você vai usar o Ray e a estrutura verl (Volcano Engine Reinforcement Learning) para configurar um ambiente de treinamento distribuído e ajustar um modelo Qwen2.5-32B-Instruct.
Este tutorial se concentra no pipeline de treinamento da otimização de política relativa de grupo (GRPO) no GKE com Ray e verl. O GRPO é um algoritmo de aprendizado por reforço projetado para melhorar a capacidade de raciocínio de um modelo. Esse algoritmo com eficiência de memória simplifica o processo de aprendizado por reforço (RL) ao eliminar o Critic, ou modelo de valor, e usar um cálculo relativo baseado em grupo.
Este tutorial é um bom ponto de partida se você precisar configurar um ambiente de treinamento distribuído em que os dados, as ponderações do modelo e o mecanismo de treinamento sejam dissociados para aumentar a eficiência.
Contexto
As seções a seguir oferecem uma breve visão geral dos conceitos usados neste tutorial.
Aprendizado por reforço (RL)
A RL ensina modelos por experiência, exploração e feedback, em vez de imitação estática. Embora o pré-treinamento ensine um modelo a falar, o aprendizado por reforço com feedback humano (RLHF) ensina como ser útil, seguro e lógico. O RL serve como ponte entre um modelo de base e um modelo refinado para um caso de uso especializado.
Para mais informações, consulte O que é aprendizado por reforço?
Otimização de política relativa a grupos (GRPO)
O GRPO, um algoritmo popularizado pela DeepSeek, oferece uma alternativa com uso eficiente de memória à otimização de política proximal (PPO, na sigla em inglês) para o alinhamento de LLMs ao remover o modelo de crítica. Em vez de uma rede de críticos, o GRPO gera um grupo de respostas para o mesmo comando e usa a recompensa média desse grupo como base.
Para mais informações, consulte GRPO.
Aprendizado por reforço do Volcano Engine (verl)
verl é um framework de alto desempenho projetado para processar os padrões complexos de memória e computação da RL baseada em LLM.
Para mais informações, consulte verl.
Objetivos
Neste tutorial, mostramos como configurar o aprendizado por reforço no GKE com o verl. Para isso, siga estas etapas:
- Configure um cluster do GKE com GPUs B200 ou H200.
- Configure o KubeRay para gerenciar um cluster distribuído do Ray.
- Use o Cloud Storage FUSE para ativar um bucket do Cloud Storage em todos os nós.
- Execute um job de treinamento de GRPO usando verl para alinhar o modelo Qwen2.5-32B-Instruct com o conjunto de dados GSM8K.
Antes de começar
- Faça login na sua conta do Google Cloud . Se você começou a usar o Google Cloud, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
-
Instale a CLI do Google Cloud.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init -
Crie ou selecione um Google Cloud projeto.
Funções necessárias para selecionar ou criar um projeto
- Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
-
Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos
(
roles/resourcemanager.projectCreator), que contém a permissãoresourcemanager.projects.create. Saiba como conceder papéis.
-
Crie um projeto do Google Cloud :
gcloud projects create PROJECT_ID
Substitua
PROJECT_IDpor um nome para o projeto Google Cloud que você está criando. -
Selecione o projeto Google Cloud que você criou:
gcloud config set project PROJECT_ID
Substitua
PROJECT_IDpelo nome do projeto do Google Cloud .
-
Verifique se o faturamento está ativado para o projeto do Google Cloud .
Ative as APIs necessárias:
Funções necessárias para ativar APIs
Para ativar as APIs, é necessário ter o papel do IAM de administrador de uso do serviço (
roles/serviceusage.serviceUsageAdmin), que contém a permissãoserviceusage.services.enable. Saiba como conceder papéis.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Instale a CLI do Google Cloud.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init -
Crie ou selecione um Google Cloud projeto.
Funções necessárias para selecionar ou criar um projeto
- Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
-
Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos
(
roles/resourcemanager.projectCreator), que contém a permissãoresourcemanager.projects.create. Saiba como conceder papéis.
-
Crie um projeto do Google Cloud :
gcloud projects create PROJECT_ID
Substitua
PROJECT_IDpor um nome para o projeto Google Cloud que você está criando. -
Selecione o projeto Google Cloud que você criou:
gcloud config set project PROJECT_ID
Substitua
PROJECT_IDpelo nome do projeto do Google Cloud .
-
Verifique se o faturamento está ativado para o projeto do Google Cloud .
Ative as APIs necessárias:
Funções necessárias para ativar APIs
Para ativar as APIs, é necessário ter o papel do IAM de administrador de uso do serviço (
roles/serviceusage.serviceUsageAdmin), que contém a permissãoserviceusage.services.enable. Saiba como conceder papéis.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Atribua papéis à sua conta de usuário. Execute uma vez o seguinte comando para cada um dos seguintes papéis do IAM:
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Substitua:
PROJECT_ID: o ID do projeto.USER_IDENTIFIER: o identificador da sua conta de usuário . Por exemplo,myemail@example.com.ROLE: o papel do IAM concedido à sua conta de usuário.
- Crie uma conta do Hugging Face caso ainda não tenha uma.
- Verifique se você tem um token do Hugging Face.
- Verifique se o projeto tem cota suficiente para GPUs B200 e H200. Para saber mais, consulte Planejar a cota de GPU e Cota de GPU.
Preparar o ambiente
Neste tutorial, você vai usar o Cloud Shell.
Acesse o console doGoogle Cloud .
Na parte de cima da janela do console do Google Cloud , clique no botão Ativar Cloud Shell.
Configure as variáveis de ambiente a seguir:
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export GPU_TYPE=GPU_TYPE export CONTROL_PLANE_REGION=CONTROL_PLANE_REGION export NODE_ZONE=NODE_ZONE export CLUSTER_NAME=CLUSTER_NAME export KSA_NAME=CLUSTER_NAME export GS_BUCKET=BUCKET_NAME-${PROJECT_ID} export NAMESPACE=default export HF_TOKEN=YOUR_HUGGING_FACE_TOKEN export MACHINE_TYPE=MACHINE_TYPE export RESERVATION=RESERVATIONSubstitua os seguintes valores:
CONTROL_PLANE_REGION: a região do Compute Engine para o plano de controle do cluster do GKE.GPU_TYPE: o acelerador que você reservou na reserva de capacidade do Compute Engine. Precisa ser um dos valores abaixo:nvidia-b200: NVIDIA B200 (180GB)nvidia-h200-141gb: NVIDIA H200 (141GB)
NODE_ZONE: a zona dos nós do GKE. Selecione uma zona em que as GPUs NVIDIA B200 ou H200 estejam disponíveis.CLUSTER_NAME: o nome do cluster do GKE.BUCKET_NAME: o nome base do bucket do Cloud Storage. Não é necessário especificar o prefixogs://.YOUR_HUGGING_FACE_TOKEN: seu token do Hugging Face para acesso ao modelo.MACHINE_TYPE: o tipo de máquina a ser usado:- Para GPUs NVIDIA B200 (180 GB), use
a4-highgpu-8gou mais recente. - Para GPUs NVIDIA H200 (141 GB), use
a3-ultragpu-8gou mais recente.
- Para GPUs NVIDIA B200 (180 GB), use
RESERVATION: o nome da sua reserva de GPU.
Crie as seguintes variáveis de ambiente para a rede:
export GVNIC_NETWORK_PREFIX="GVNIC-NAME" export RDMA_NETWORK_PREFIX="RDMA-NAME"Substitua os seguintes valores:
GVNIC-NAME: o prefixo do nome da rede gVNIC. Você pode usar qualquer prefixo.RDMA-NAME: o prefixo da rede de acesso direto à memória (RDMA) remota. Você pode usar qualquer prefixo.
Configurar a infraestrutura
Nesta seção, você vai criar uma rede RDMA e um cluster do GKE.
Criar rede e sub-redes RDMA
Crie uma rede VPC para a 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/16Crie uma rede VPC e sub-redes para RDMA com oito sub-redes para oito 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 waitClone o repositório de amostra:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samplesNavegue até o diretório de trabalho:
cd ai-ml/verl-on-gke
Criar o cluster do GKE
É possível definir o verl em um cluster do GKE Autopilot ou Standard. Recomendamos que você use um cluster do Autopilot para ter uma experiência totalmente gerenciada do Kubernetes. Para escolher o modo de operação do GKE mais adequado para suas cargas de trabalho, consulte Escolher um modo de operação do GKE.
Piloto automático
Criar um cluster do Autopilot:
gcloud container clusters create-auto ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --enable-multi-networking \ --enable-ray-operatorReceba as credenciais do cluster:
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION}Instale o instalador do NCCL RDMA para o Autopilot:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer-autopilot.yaml
Padrão
Criar um cluster padrão
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-autoscalingReceba as credenciais do cluster:
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}Crie o pool de nós de GPU. Esses pools de nós usam sua reserva para garantir a disponibilidade. Começamos com dois nós:
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-7Instale o instalador do NCCL RDMA usado para clusters Standard:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
Configurar mapeamentos de rede
Inspecione o manifesto
network-mapping.yaml:Aplique o manifesto:
envsubst < network-mapping.yaml > network-mapping-updated.yaml kubectl apply -f network-mapping-updated.yaml
Preparar dados e armazenamento
Crie um bucket do Cloud Storage:
gcloud storage buckets create gs://${GS_BUCKET} --location=${REGION} --enable-hierarchical-namespace --uniform-bucket-level-accessCrie uma conta de serviço do Kubernetes (KSA) e vincule-a ao 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"Crie o secret para o Hugging Face:
kubectl create secret generic hf-secret --from-literal=hf_api_token=${HF_TOKEN}Inspecione o manifesto
gcsfuse-storage.yaml:Aplique o manifesto:
envsubst < gcsfuse-storage.yaml > gcsfuse-storage-updated.yaml kubectl apply -f gcsfuse-storage-updated.yaml
Preparar o modelo e os dados
É possível executar esses comandos localmente ou em um pod do GKE para preencher o bucket.
Clone o repositório verl, prepare o ambiente virtual e processe o conjunto de dados GSM8K:
git clone https://github.com/volcengine/verl.git 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/gsm8kFaça o download do modelo Qwen2.5-32B-Instruct usando a CLI do Hugging Face. Isso requer cerca de 66 GB de espaço em disco:
hf download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-InstructFaça upload do modelo, dos dados e do código do Verilog para o bucket do 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/
Implantar o recurso personalizado RayCluster
Implante um recurso personalizado do RayCluster, que geralmente consiste em um pod do sistema e vários pods de worker.
Piloto automático
Implante o RayCluster. Salve o seguinte em
ray-cluster-auto.yaml:Aplique o RayCluster:
envsubst < ray-cluster-auto.yaml > ray-cluster-auto-updated.yaml kubectl apply -f ray-cluster-updated.yaml
Padrão
Implante o RayCluster. Salve o seguinte em
ray-cluster-standard.yaml:Aplique o RayCluster:
envsubst < ray-cluster-standard.yaml > ray-cluster-updated.yaml kubectl apply -f ray-cluster-updated.yaml
Iniciar o job do GRPO
Configure o encaminhamento de portas para o nó do painel do Ray. Use uma janela de terminal separada para isso, já que esse comando vai bloquear o terminal enquanto estiver em execução. Use Ctrl+C para interromper:
kubectl port-forward svc/b200-ray-cluster-head-svc 8265:8265Inspecione o manifesto
runtime-env.yaml:Se você usar GPUs H200, mude
NCCL_TUNER_CONFIG_PATHpara/usr/local/gib/configs/tuner_config_a3u.txtpb.Esse arquivo é usado pelo cliente do Ray. Não é necessário aplicar esse manifesto ao cluster.
Envie o job usando
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"Monitore os registros no painel ou na saída do Ray. Procure por
critic/score/meanpara aumentar, indicando aprendizado.Depois que o treinamento for concluído, os pontos de verificação do modelo treinado poderão ser encontrados em
gs://$GS_BUCKET/verl/checkpoints.
Limpar
Para evitar cobranças, exclua os recursos:
kubectl delete raycluster b200-ray-cluster # change to variables
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}
gcloud storage rm -r gs://${GS_BUCKET}