Ce tutoriel explique comment affiner un modèle Gemma 3 à l'aide du framework Ray sur un cluster GKE à nœuds multiples. Le cluster utilise deux instances de machines virtuelles A4, chacune dotée de huit GPU NVIDIA B200.
Le contenu de ce tutoriel est divisé en deux parties :
- Préparer le cluster Ray sur un cluster GKE Autopilot.
- Exécution d'un job d'entraînement distribué, utilisant deux instances A4, avec huit GPU B200 chacune.
Ce tutoriel s'adresse aux ingénieurs et chercheurs en machine learning (ML), aux administrateurs et opérateurs de plate-forme, ainsi qu'aux spécialistes des données et de l'IA qui souhaitent distribuer une charge de travail d'IA sur plusieurs nœuds et GPU.
Objectifs
Accédez à un modèle Gemma 3 en utilisant Hugging Face.
Préparez votre environnement.
Créez un cluster GKE Autopilot sur lequel l'opérateur Ray est installé.
Configurez le cluster Ray sur le cluster GKE pour qu'il accepte les tâches Ray.
Configurez et exécutez un job Ray qui ajuste le modèle Gemma 3 en fonction de l'entrée visuelle.
Surveillez votre charge de travail.
Effectuer un nettoyage.
Coûts
Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :
Pour obtenir une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.
Avant de commencer
- Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits sans frais pour exécuter, tester et déployer des charges de travail.
-
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez l'API requise :
Rôles requis pour activer les API
Pour activer les API, vous devez disposer de l'autorisation
serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.gcloud services enable compute.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com container.googleapis.com
-
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez l'API requise :
Rôles requis pour activer les API
Pour activer les API, vous devez disposer de l'autorisation
serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.gcloud services enable compute.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com container.googleapis.com
-
Attribuez des rôles à votre compte utilisateur. Exécutez la commande suivante une fois pour chacun des rôles IAM suivants :
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
Remplacez les éléments suivants :
PROJECT_ID: ID de votre projetUSER_IDENTIFIER: identifiant de votre compte utilisateur . Par exemple,myemail@example.com.ROLE: rôle IAM que vous accordez à votre compte utilisateur.
- Activez le compte de service par défaut pour votre projet Google Cloud :
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --project=PROJECT_ID
Remplacez PROJECT_NUMBER par votre numéro de projet. Pour consulter le numéro de votre projet, consultez Obtenir un projet existant.
- Attribuez le rôle Éditeur (
roles/editor) au compte de service par défaut :gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role=roles/editor
- Créez des identifiants d'authentification locaux pour votre compte utilisateur :
gcloud auth application-default login
- Connectez-vous à votre compte Hugging Face ou créez-en un.
Accéder à Gemma 3 à l'aide de Hugging Face
Pour utiliser Hugging Face afin d'accéder à Gemma 3, procédez comme suit :
Copiez et enregistrez la valeur du jeton
read access. Vous en aurez besoin dans la suite de ce tutoriel.
Préparer votre environnement
Préparez votre environnement en configurant les paramètres nécessaires et en définissant les variables d'environnement.
Exécutez la commande suivante :
Remplacez les éléments suivants :
YOUR_PROJECT_ID: nom du Google Cloud projet dans lequel vous souhaitez créer le cluster GKE.YOUR_RESERVATION_ID: URL de la réservation que vous souhaitez utiliser pour créer votre cluster. En fonction du projet dans lequel la réservation existe, spécifiez l'une des valeurs suivantes :- La réservation existe dans votre projet : spécifiez le nom de la réservation (par exemple,
my-reservation). - La réservation existe dans un autre projet : spécifiez le chemin d'accès complet au format
projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME.
- La réservation existe dans votre projet : spécifiez le nom de la réservation (par exemple,
YOUR_REGION: région dans laquelle vous souhaitez créer votre cluster GKE. Vous ne pouvez créer le cluster que dans la région où se trouve votre réservation.YOUR_CLUSTER_NAME: nom du cluster GKE à créer.HUGGING_FACE_TOKEN: jeton Hugging Face que vous avez créé à une étape précédente.YOUR_RAY_SA: nom du compte de service dans le cluster Kubernetes.YOUR_GSA_NAME: nom du compte de service Google.YOUR_GCS_BUCKET: nom du bucket dans lequel vous stockez les résultats du point de contrôle de l'entraînement.
Créer un cluster GKE en mode Autopilot
Pour créer un cluster GKE en mode Autopilot, exécutez la commande suivante :
La création du cluster GKE peut prendre un certain temps. Pour vérifier si Google Cloud a terminé de créer votre cluster, accédez à Clusters Kubernetes dans la console Google Cloud .
Créer un secret Kubernetes pour les identifiants Hugging Face
Dans Cloud Shell, pour créer un secret Kubernetes pour les identifiants Hugging Face, procédez comme suit :
Configurez
kubectlpour vous connecter à votre cluster :Créez un secret Kubernetes pour stocker votre jeton Hugging Face :
Créer le bucket Cloud Storage
Si vous souhaitez utiliser un nouveau bucket pour stocker vos artefacts d'entraînement, exécutez la commande suivante :
Si vous souhaitez utiliser un bucket existant, vous pouvez ignorer cette étape. Toutefois, vous devez vous assurer que votre bucket se trouve dans la même région que votre cluster.
Créer un compte de service IAM
Dans Cloud Shell, pour créer un compte de service IAM (également appelé compte de service Google ou GSA) et lui accorder des autorisations d'accès à votre bucket Cloud Storage, procédez comme suit :
Créez un compte de service IAM :
Attribuez le rôle Administrateur de l'espace de stockage (
roles/storage.admin) à votre compte de service IAM pour votre bucket Cloud Storage :
Créer un compte de service Kubernetes
Dans Cloud Shell, créez un compte de service Kubernetes et configurez Workload Identity pour accorder aux pods Ray l'accès aux ressources Google Cloud :
Créez un compte de service Kubernetes :
Associez votre compte de service Kubernetes au compte de service IAM que vous avez créé précédemment pour activer Workload Identity :
Annotez votre compte de service Kubernetes avec l'adresse e-mail du compte de service IAM :
Enregistrer votre code d'entraînement en tant que ConfigMap
Pour éviter d'intégrer votre script d'entraînement dans une image de conteneur, stockez-le en tant que ConfigMap dans votre cluster. Cette ConfigMap est montée sur les systèmes de fichiers du pod, ce qui vous permet de mettre à jour le script d'entraînement sans avoir à recréer l'intégralité du cluster Ray.
Pour stocker votre script d'entraînement en tant que ConfigMap dans votre cluster, procédez comme suit :
Créez un répertoire nommé
code, puis créez un fichier nommévision_train.pydans ce répertoire.Copiez le code suivant dans le fichier
vision_train.py:Enregistrez le fichier.
Créez un objet ConfigMap dans votre cluster :
Pour mettre à jour le script d'entraînement, réexécutez la commande précédente. Il peut s'écouler une minute avant que les modifications ne soient propagées à tous les pods.
Configurer un cluster Ray
Pour créer un cluster Ray dans votre cluster GKE, enregistrez le fichier YAML suivant sous le nom
ray_cluster.yaml.Appliquez cette définition YAML à votre cluster à l'aide de la commande suivante :
L'indicateur$RESERVATIONest automatiquement remplacé par le nom que vous avez configuré en tant que variable d'environnement.L'opérateur Ray crée les pods raylet, ce qui déclenche l'autoscaling du cluster pour fournir à ces pods les nœuds appropriés. Trois pods sont créés dans votre cluster : un nœud principal et deux nœuds de calcul. Les nœuds de calcul sont équipés de GPU B200.
Pour vérifier que les trois pods sont prêts, exécutez la commande suivante :
La liste des pods d'un cluster Ray prêt ressemble à ce qui suit :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
Planifier un job d'entraînement
Enregistrez le code suivant dans un fichier
ray_job.yaml:Envoyez la définition RayJob à votre RayCluster :
Vérifiez qu'un nouveau pod se trouve dans votre cluster :
Notez le nom complet du pod
test-ray-job-qui s'affiche dans le résultat. Ce nom est propre à votre job.Inspectez la progression de votre entraînement. Remplacez
gemma-training-ray-job-UNIQUE_IDpar le nom unique du pod que vous avez noté à l'étape précédente.Le résultat renvoyé ressemble à ceci :
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 -- ----------------------------------Surveiller votre charge de travail
Vous pouvez utiliser le tableau de bord de Ray pour surveiller les charges de travail planifiées dans votre cluster.
Pour accéder à ce tableau de bord, vous devez configurer le transfert de port vers votre cluster en exécutant la commande suivante dans une nouvelle fenêtre de terminal :
Ouvrez le lien suivant dans votre navigateur :
http://localhost:8265.Si vous utilisez Cloud Shell, vous pouvez éventuellement cliquer sur le bouton Aperçu sur le Web après avoir exécuté la commande de l'étape précédente.
Sélectionnez l'option Modifier le port, saisissez
8265, puis cliquez sur Modifier et prévisualiser. Le tableau de bord Ray s'ouvre dans un nouvel onglet.
Effectuer un nettoyage
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.
Supprimer vos ressources
Pour supprimer le cluster Ray et libérer le nœud équipé d'un GPU, exécutez la commande suivante :
GKE réduit automatiquement la taille de votre cluster et libère les machines A4 utilisées par Ray.Pour supprimer l'intégralité du cluster GKE, exécutez la commande suivante :
Pour supprimer l'intégralité du bucket Cloud Storage et de son contenu, exécutez la commande suivante :
Supprimer votre projet
Supprimer un projet Google Cloud :
gcloud projects delete PROJECT_ID