En este instructivo, se muestra cómo ajustar un modelo de Gemma 3 con el framework de Ray en un clúster de GKE de varios nodos. El clúster usa dos instancias de máquina virtual (VM) A4, cada una con ocho GPUs NVIDIA B200 conectadas.
El contenido de este instructivo se divide en dos partes:
- Preparar el clúster de Ray sobre un clúster de Autopilot de GKE
- Ejecuta un trabajo de entrenamiento distribuido que utiliza 2 instancias A4, cada una con 8 GPUs B200.
Este instructivo está dirigido a ingenieros e investigadores de aprendizaje automático (AA), administradores y operadores de plataformas, y especialistas en datos y en IA que deseen distribuir una carga de trabajo de IA en varios nodos y GPUs.
Objetivos
Accede a un modelo de Gemma 3 con Hugging Face.
Prepara tu entorno.
Crea un clúster de GKE Autopilot con el operador de Ray instalado.
Configura el clúster de Ray en el clúster de GKE para que acepte trabajos de Ray.
Configurar y ejecutar un trabajo de Ray que ajuste el modelo Gemma 3 en función de la entrada visual
Supervisa tu carga de trabajo.
Realizar una limpieza
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto,
usa la calculadora de precios.
Antes de comenzar
- Accede a tu cuenta de Google Cloud . Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
-
Instala Google Cloud CLI.
-
Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.
-
Para inicializar gcloud CLI, ejecuta el siguiente comando:
gcloud init -
Crea o selecciona un Google Cloud proyecto.
Roles necesarios para seleccionar o crear un proyecto
- Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
-
Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (
roles/resourcemanager.projectCreator), que contiene el permisoresourcemanager.projects.create. Obtén más información para otorgar roles.
-
Crea un proyecto de Google Cloud :
gcloud projects create PROJECT_ID
Reemplaza
PROJECT_IDpor un nombre para el proyecto Google Cloud que estás creando. -
Selecciona el proyecto Google Cloud que creaste:
gcloud config set project PROJECT_ID
Reemplaza
PROJECT_IDpor el nombre de tu proyecto de Google Cloud .
-
Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .
Habilita la API necesaria:
Roles necesarios para habilitar las APIs
Para habilitar APIs, necesitas el permiso
serviceusage.services.enable. Si creaste el proyecto, es probable que ya tengas este permiso a través del rol de propietario (roles/owner). De lo contrario, puedes obtener este permiso a través del rol de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin). Obtén más información para otorgar roles.gcloud services enable compute.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com container.googleapis.com
-
Instala Google Cloud CLI.
-
Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.
-
Para inicializar gcloud CLI, ejecuta el siguiente comando:
gcloud init -
Crea o selecciona un Google Cloud proyecto.
Roles necesarios para seleccionar o crear un proyecto
- Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
-
Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (
roles/resourcemanager.projectCreator), que contiene el permisoresourcemanager.projects.create. Obtén más información para otorgar roles.
-
Crea un proyecto de Google Cloud :
gcloud projects create PROJECT_ID
Reemplaza
PROJECT_IDpor un nombre para el proyecto Google Cloud que estás creando. -
Selecciona el proyecto Google Cloud que creaste:
gcloud config set project PROJECT_ID
Reemplaza
PROJECT_IDpor el nombre de tu proyecto de Google Cloud .
-
Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .
Habilita la API necesaria:
Roles necesarios para habilitar las APIs
Para habilitar APIs, necesitas el permiso
serviceusage.services.enable. Si creaste el proyecto, es probable que ya tengas este permiso a través del rol de propietario (roles/owner). De lo contrario, puedes obtener este permiso a través del rol de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin). Obtén más información para otorgar roles.gcloud services enable compute.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com container.googleapis.com
-
Otorga roles a tu cuenta de usuario. Ejecuta el siguiente comando una vez para cada uno de los siguientes roles de IAM:
roles/compute.admin, roles/iam.serviceAccountUser, roles/file.editor, roles/storage.admin, roles/container.clusterAdmin, roles/serviceusage.serviceUsageAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Reemplaza lo siguiente:
PROJECT_ID: ID del proyectoUSER_IDENTIFIER: Es el identificador de tu cuenta de usuario de . Por ejemplo,myemail@example.com.ROLE: Es el rol de IAM que otorgas a tu cuenta de usuario.
- Habilita la cuenta de servicio predeterminada para tu proyecto Google Cloud :
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --project=PROJECT_ID
Reemplaza PROJECT_NUMBER por el número del proyecto. Para revisar el número de tu proyecto, consulta Cómo obtener un proyecto existente.
- Otorga el rol de editor (
roles/editor) a la cuenta de servicio predeterminada:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role=roles/editor
- Crea credenciales de autenticación locales para tu cuenta de usuario:
gcloud auth application-default login
- Accede a tu cuenta de Hugging Face o crea una.
Accede a Gemma 3 con Hugging Face
Para usar Hugging Face y acceder a Gemma 3, haz lo siguiente:
Copia y guarda el valor del token
read access. La usarás más adelante en este instructivo.
Prepara el entorno
Prepara tu entorno configurando los parámetros necesarios y estableciendo las variables de entorno.
Ejecuta lo siguiente:
Reemplaza lo siguiente:
YOUR_PROJECT_ID: Es el nombre del Google Cloud proyecto en el que deseas crear el clúster de GKE.YOUR_RESERVATION_ID: Es la URL de la reserva que deseas usar para crear tu clúster. Según el proyecto en el que existe la reserva, especifica uno de los siguientes valores:- La reserva existe en tu proyecto: Especifica el nombre de la reserva (p.ej.,
my-reservation). - La reserva existe en otro proyecto: Especifica la ruta completa en el formato
projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME.
- La reserva existe en tu proyecto: Especifica el nombre de la reserva (p.ej.,
YOUR_REGION: Es la región en la que deseas crear tu clúster de GKE. Solo puedes crear el clúster en la región en la que existe tu reserva.YOUR_CLUSTER_NAME: Es el nombre del clúster de GKE que se creará.YOUR_HF_TOKEN: El token de Hugging Face que creaste en un paso anteriorYOUR_RAY_SA: Es el nombre de la cuenta de servicio dentro del clúster de Kubernetes.YOUR_GSA_NAME: Es el nombre de la cuenta de servicio de Google.YOUR_GCS_BUCKET: Es el nombre del bucket en el que almacenas los resultados del punto de control del entrenamiento.
Crea un clúster de GKE en modo Autopilot
Para crear un clúster de GKE en modo Autopilot, ejecuta el siguiente comando:
La creación del clúster de GKE puede tardar un tiempo en completarse. Para verificar si Google Cloud terminó de crear tu clúster, ve a Clústeres de Kubernetes en la consola de Google Cloud .
Crea un secreto de Kubernetes para las credenciales de Hugging Face
En Cloud Shell, para crear un secreto de Kubernetes para las credenciales de Hugging Face, haz lo siguiente:
Configura
kubectlpara conectarte a tu clúster:Crea un Secret de Kubernetes para almacenar tu token de Hugging Face:
Crea el bucket de Cloud Storage
Si deseas usar un bucket nuevo para almacenar tus artefactos de entrenamiento, ejecuta el siguiente comando:
Si quieres usar un bucket existente, puedes omitir este paso. Sin embargo, debes asegurarte de que tu bucket esté en la misma región que tu clúster.
Crea una cuenta de servicio de IAM
En Cloud Shell, para crear una cuenta de servicio de IAM (también conocida como cuenta de servicio de Google o GSA) y otorgarle permisos para acceder a tu bucket de Cloud Storage, haz lo siguiente:
Crea una cuenta de servicio de IAM:
Otorga el rol de administrador de almacenamiento (
roles/storage.admin) a tu cuenta de servicio de IAM para tu bucket de Cloud Storage:
Crea una cuenta de servicio de Kubernetes
En Cloud Shell, crea una cuenta de servicio de Kubernetes y configura Workload Identity para otorgar acceso a los Pods de Ray a los recursos de Google Cloud :
Crea una cuenta de servicio de Kubernetes:
Vincula tu cuenta de servicio de Kubernetes a la cuenta de servicio de IAM que creaste anteriormente para habilitar Workload Identity:
Anota tu cuenta de servicio de Kubernetes con la dirección de correo electrónico de la cuenta de servicio de IAM:
Guarda tu código de entrenamiento como un ConfigMap
Para evitar la necesidad de incorporar tu secuencia de comandos de entrenamiento en una imagen de contenedor, la almacenas como un ConfigMap en tu clúster. Este ConfigMap se activa en los sistemas de archivos de Pod, lo que te permite actualizar la secuencia de comandos de entrenamiento sin tener que volver a crear todo el clúster de Ray.
Para almacenar tu secuencia de comandos de entrenamiento como un ConfigMap en tu clúster, completa los siguientes pasos:
Crea un directorio con el nombre
codey, en ese directorio, crea un archivo con el nombrevision_train.py.Copia el siguiente código en el archivo
vision_train.py:Guarda el archivo.
Crea un objeto ConfigMap en tu clúster:
Para actualizar el script de entrenamiento, vuelve a ejecutar el comando anterior. Es posible que tarde un minuto en propagarse a todos los pods.
Configura el clúster de Ray
Para crear un clúster de Ray en tu clúster de GKE, guarda el siguiente archivo YAML como un archivo con el nombre
ray_cluster.yaml.Aplica esta definición de YAML a tu clúster con el siguiente comando:
La marca$RESERVATIONse reemplaza automáticamente por el nombre que configuraste como variable de entorno.Ray Operator crea los Pods de raylet, lo que, a su vez, activa el ajuste de escala automático del clúster para proporcionar a esos Pods los nodos adecuados. Se crean tres pods en tu clúster: un nodo principal y dos nodos trabajadores. Los nodos trabajadores están equipados con las GPU B200.
Para verificar que los tres Pods estén listos, ejecuta el siguiente comando:
La lista de pods de un clúster de Ray listo es similar a la siguiente:NAME READY STATUS RESTARTS AGE gemma3-tuning-gpu-group-worker-s4h8f 2/2 Running 0 16m gemma3-tuning-gpu-group-worker-stg5f 2/2 Running 0 5m34s gemma3-tuning-head-zbdvp 2/2 Running 0 16m
Programa un trabajo de entrenamiento
Guarda lo siguiente como un archivo
ray_job.yaml:Envía la definición de RayJob a tu RayCluster:
Verifica que haya un Pod nuevo en tu clúster:
Toma nota del nombre completo del Pod
test-ray-job-que ves en el resultado. Este nombre es único para tu trabajo.Inspecciona el progreso de tu entrenamiento. Reemplaza
gemma-training-ray-job-UNIQUE_IDpor el nombre único del Pod que anotaste en el paso anterior.El resultado que ves es similar al siguiente:
2025-08-20 08:29:34,966 INFO cli.py:41 -- Job submission server address: http://gemma3-tuning-head-svc.default.svc.cluster.local:8265 2025-08-20 08:29:34,991 SUCC cli.py:65 -- ----------------------------------------------- 2025-08-20 08:29:34,991 SUCC cli.py:66 -- Job 'test-ray-job-82mm7' submitted successfully 2025-08-20 08:29:34,991 SUCC cli.py:67 -- ----------------------------------------------- 2025-08-20 08:29:34,992 INFO cli.py:291 -- Next steps 2025-08-20 08:29:34,992 INFO cli.py:292 -- Query the logs of the job: 2025-08-20 08:29:34,992 INFO cli.py:294 -- ray job logs test-ray-job-82mm7 2025-08-20 08:29:34,992 INFO cli.py:296 -- Query the status of the job: 2025-08-20 08:29:34,992 INFO cli.py:298 -- ray job status test-ray-job-82mm7 2025-08-20 08:29:34,992 INFO cli.py:300 -- Request the job to be stopped: 2025-08-20 08:29:34,992 INFO cli.py:302 -- ray job stop test-ray-job-82mm7 2025-08-20 08:29:35,003 INFO cli.py:312 -- Tailing logs until the job exits (disable with --no-wait): 2025-08-20 08:29:34,982 INFO job_manager.py:531 -- Runtime env is setting up. Starting training task! Commencing training! 2025-08-20 08:30:08,498 INFO worker.py:1606 -- Using address 10.76.0.17:6379 set in the environment variable RAY_ADDRESS 2025-08-20 08:30:08,506 INFO worker.py:1747 -- Connecting to existing Ray cluster at address: 10.76.0.17:6379... 2025-08-20 08:30:08,527 INFO worker.py:1918 -- Connected to Ray cluster. View the dashboard at 10.76.0.17:8265 2025-08-20 08:30:08,701 INFO tune.py:253 -- Initializing Ray automatically. For cluster usage or custom Ray initialization, call `ray.init(...)` before `<FrameworkTrainer>(...)`. 2025-08-20 08:30:08,951 WARNING tune_controller.py:2132 -- The maximum number of pending trials has been automatically set to the number of available cluster CPUs, which is high (519 CPUs/pending trials). If you're running an experiment with a large number of trials, this could lead to scheduling overhead. In this case, consider setting the `TUNE_MAX_PENDING_TRIALS_PG` environment variable to the desired maximum number of concurrent pending trials. 2025-08-20 08:30:08,953 WARNING tune_controller.py:2132 -- The maximum number of pending trials has been automatically set to the number of available cluster CPUs, which is high (519 CPUs/pending trials). If you're running an experiment with a large number of trials, this could lead to scheduling overhead. In this case, consider setting the `TUNE_MAX_PENDING_TRIALS_PG` environment variable to the desired maximum number of concurrent pending trials. View detailed results here: YOUR_GCS_BUCKET/gemma_vision_train_2025_08_20_08_30_07 To visualize your results with TensorBoard, run: `tensorboard --logdir /tmp/ray/session_2025-08-20_04-43-14_215096_1/artifacts/2025-08-20_08-30-08/gemma_vision_train_2025_08_20_08_30_07/driver_artifacts` Training started with configuration: ╭──────────────────────────────────────────────────────────────────────╮ │ Training config │ ├──────────────────────────────────────────────────────────────────────┤ │ train_loop_config/dataset_name ...-descriptions-vlm │ │ train_loop_config/gcs_bucket ...-bucket-yooo-west │ │ train_loop_config/gradient_accumulation_steps 4 │ │ train_loop_config/learning_rate 0.0002 │ │ train_loop_config/logging_steps 10 │ │ train_loop_config/lora_alpha 16 │ │ train_loop_config/lora_dropout 0.05 │ │ train_loop_config/lora_r 16 │ │ train_loop_config/max_seq_length 512 │ │ train_loop_config/model_id google/gemma-3-4b-it │ │ train_loop_config/num_train_epochs 3 │ │ train_loop_config/output_dir ...-4b-seo-optimized │ │ train_loop_config/per_device_train_batch_size 1 │ │ train_loop_config/push_to_hub False │ │ train_loop_config/save_steps 100 │ │ train_loop_config/save_strategy epoch │ ╰──────────────────────────────────────────────────────────────────────╯ (RayTrainWorker pid=45455, ip=10.76.0.71) Setting up process group for: env:// [rank=0, world_size=16] (TorchTrainer pid=45197, ip=10.76.0.71) Started distributed worker processes: (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45455) world_rank=0, local_rank=0, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45450) world_rank=1, local_rank=1, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45454) world_rank=2, local_rank=2, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45448) world_rank=3, local_rank=3, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45453) world_rank=4, local_rank=4, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45452) world_rank=5, local_rank=5, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45451) world_rank=6, local_rank=6, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=4c934ab2f646a578b03cc335586f30b943e811b645526a74c50bfca1, ip=10.76.0.71, pid=45449) world_rank=7, local_rank=7, node_rank=0 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45729) world_rank=8, local_rank=0, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45726) world_rank=9, local_rank=1, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45728) world_rank=10, local_rank=2, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45727) world_rank=11, local_rank=3, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45725) world_rank=12, local_rank=4, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45724) world_rank=13, local_rank=5, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45723) world_rank=14, local_rank=6, node_rank=1 (TorchTrainer pid=45197, ip=10.76.0.71) - (node_id=c0db52b44f891f3d6a1cedcbea4c6beb2c8434c66ef414dc15e65743, ip=10.76.0.135, pid=45722) world_rank=15, local_rank=7, node_rank=1 ... Training finished iteration 3 at 2025-08-20 08:40:43. Total running time: 10min 34s ╭─────────────────────────────────────────╮ │ Training result │ ├─────────────────────────────────────────┤ │ checkpoint_dir_name checkpoint_000002 │ │ time_this_iter_s 152.6374 │ │ time_total_s 525.88585 │ │ training_iteration 3 │ │ epoch 2.75294 │ │ grad_norm 47.27161 │ │ learning_rate 0.0002 │ │ loss 22.5275 │ │ mean_token_accuracy 0.90325 │ │ num_tokens 1583017. │ │ step 60 │ ╰─────────────────────────────────────────╯ ... Training completed after 3 iterations at 2025-08-20 08:40:52. Total running time: 10min 43s 2025-08-20 08:40:53,113 INFO tune.py:1009 -- Wrote the latest version of all result files and experiment state to 'YOUR_GCS_BUCKET/gemma_vision_train_2025_08_20_08_30_07' in 0.1663s. 2025-08-20 08:40:58,304 SUCC cli.py:65 -- ---------------------------------- 2025-08-20 08:40:58,305 SUCC cli.py:66 -- Job 'test-ray-job-82mm7' succeeded 2025-08-20 08:40:58,305 SUCC cli.py:67 -- ----------------------------------Supervisa tu carga de trabajo
Puedes usar el panel en Ray para supervisar las cargas de trabajo programadas en tu clúster.
Para acceder a este panel, debes configurar el reenvío de puertos a tu clúster ejecutando el siguiente comando en una ventana de terminal nueva:
Abre el siguiente vínculo en tu navegador:
http://localhost:8265.De manera opcional, si usas Cloud Shell, después de ejecutar el comando del paso anterior, puedes hacer clic en el botón Vista previa en la Web.
Selecciona la opción Cambiar puerto, ingresa
8265y, luego, haz clic en Cambiar y obtener vista previa. El panel de Ray se abrirá en una pestaña nueva.
Realiza una limpieza
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.
Borra tus recursos
Para borrar el clúster de Ray y liberar el nodo potenciado por GPU, ejecuta el siguiente comando:
GKE reduce automáticamente la escala de tu clúster y libera las máquinas A4 que usa Ray.Para borrar todo el clúster de GKE, ejecuta el siguiente comando:
Para borrar todo el bucket de Cloud Storage con todo su contenido, ejecuta el siguiente comando:
Borra tu proyecto
Borra un Google Cloud proyecto:
gcloud projects delete PROJECT_ID