Addestrare un modello con Ray e PyTorch su Google Kubernetes Engine (GKE)


Questa guida mostra come addestrare un modello su Google Kubernetes Engine (GKE) utilizzando Ray, PyTorch e il componente aggiuntivo Ray Operator.

Informazioni su Ray

Ray è un framework di calcolo scalabile open source per applicazioni AI/ML. Ray Train è un componente di Ray progettato per l'addestramento e l'ottimizzazione dei modelli distribuiti. Puoi utilizzare l'API Ray Train per scalare l'addestramento su più macchine e per integrarla con librerie di machine learning come PyTorch.

Puoi eseguire il deployment dei job di addestramento Ray utilizzando la risorsa RayCluster o RayJob. Devi utilizzare una risorsa RayJob quando esegui il deployment dei job Ray in produzione per i seguenti motivi

  • La risorsa RayJob crea un cluster Ray temporaneo che può essere eliminato automaticamente al termine di un job.
  • La risorsa RayJob supporta i criteri di ripetizione per l'esecuzione resiliente dei job.
  • Puoi gestire i job Ray utilizzando pattern API Kubernetes familiari.

Obiettivi

Questa guida è destinata ai clienti di Generative AI, agli utenti nuovi o esistenti di GKE, agli ingegneri ML, agli ingegneri MLOps (DevOps) o agli amministratori della piattaforma interessati a utilizzare le funzionalità di orchestrazione dei container Kubernetes per la gestione dei modelli utilizzando Ray.

  • Creare un cluster GKE.
  • Crea un cluster Ray utilizzando la risorsa personalizzata RayCluster.
  • Addestra un modello utilizzando un job Ray.
  • Esegui il deployment di un job Ray utilizzando la risorsa personalizzata RayJob.

Costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova gratuita.

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, vedi Pulizia.

Prima di iniziare

Cloud Shell è preinstallato con il software necessario per questo tutorial, tra cui kubectl e gcloud CLI. Se non utilizzi Cloud Shell, devi installare gcloud CLI.

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.

  4. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API:

    gcloud services enable container.googleapis.com
  8. Install the Google Cloud CLI.

  9. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.

  10. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Make sure that billing is enabled for your Google Cloud project.

  13. Enable the GKE API:

    gcloud services enable container.googleapis.com
  14. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/container.clusterAdmin, roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.
  15. prepara l'ambiente

    Per preparare l'ambiente:

    1. Avvia una sessione di Cloud Shell dalla console Google Cloud facendo clic su Icona di attivazione di Cloud Shell Attiva Cloud Shell nella consoleGoogle Cloud . Viene avviata una sessione nel riquadro inferiore della console Google Cloud .

    2. Imposta le variabili di ambiente:

      export PROJECT_ID=PROJECT_ID
      export CLUSTER_NAME=ray-cluster
      export COMPUTE_REGION=us-central1
      export COMPUTE_ZONE=us-central1-c
      export CLUSTER_VERSION=CLUSTER_VERSION
      export TUTORIAL_HOME=`pwd`
      

      Sostituisci quanto segue:

      • PROJECT_ID: il tuo Google Cloud ID progetto.
      • CLUSTER_VERSION: la versione di GKE da utilizzare. Deve essere 1.30.1 o successiva.
    3. Clona il repository GitHub:

      git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
      
    4. Passa alla directory di lavoro:

      cd kubernetes-engine-samples/ai-ml/gke-ray/raytrain/pytorch-mnist
      
    5. Crea un ambiente virtuale Python:

      python -m venv myenv && \
      source myenv/bin/activate
      
    6. Installa Ray.

    Crea un cluster GKE

    Crea un cluster GKE Autopilot o Standard:

    Autopilot

    Crea un cluster Autopilot:

    gcloud container clusters create-auto ${CLUSTER_NAME}  \
        --enable-ray-operator \
        --cluster-version=${CLUSTER_VERSION} \
        --location=${COMPUTE_REGION}
    

    Standard

    Crea un cluster Standard:

    gcloud container clusters create ${CLUSTER_NAME} \
        --addons=RayOperator \
        --cluster-version=${CLUSTER_VERSION}  \
        --machine-type=e2-standard-8 \
        --location=${COMPUTE_ZONE} \
        --num-nodes=4
    

    Esegui il deployment di una risorsa RayCluster

    Esegui il deployment di una risorsa RayCluster nel tuo cluster:

    1. Esamina il seguente manifest:

      apiVersion: ray.io/v1
      kind: RayCluster
      metadata:
        name: pytorch-mnist-cluster
      spec:
        rayVersion: '2.37.0'
        headGroupSpec:
          rayStartParams:
            dashboard-host: '0.0.0.0'
          template:
            metadata:
            spec:
              containers:
              - name: ray-head
                image: rayproject/ray:2.37.0
                ports:
                - containerPort: 6379
                  name: gcs
                - containerPort: 8265
                  name: dashboard
                - containerPort: 10001
                  name: client
                resources:
                  limits:
                    cpu: "2"
                    ephemeral-storage: "9Gi"
                    memory: "4Gi"
                  requests:
                    cpu: "2"
                    ephemeral-storage: "9Gi"
                    memory: "4Gi"
        workerGroupSpecs:
        - replicas: 4
          minReplicas: 1
          maxReplicas: 5
          groupName: worker-group
          rayStartParams: {}
          template:
            spec:
              containers:
              - name: ray-worker
                image: rayproject/ray:2.37.0
                resources:
                  limits:
                    cpu: "4"
                    ephemeral-storage: "9Gi"
                    memory: "8Gi"
                  requests:
                    cpu: "4"
                    ephemeral-storage: "9Gi"
                    memory: "8Gi"

      Questo manifest descrive una risorsa personalizzata RayCluster.

    2. Applica il manifest al cluster GKE:

      kubectl apply -f ray-cluster.yaml
      
    3. Verifica che la risorsa RayCluster sia pronta:

      kubectl get raycluster
      

      L'output è simile al seguente:

      NAME                    DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
      pytorch-mnist-cluster   2                 2                   6      20Gi     0      ready    63s
      

      In questo output, ready nella colonna STATUS indica che la risorsa RayCluster è pronta.

    Connettiti alla risorsa RayCluster

    Connettiti alla risorsa RayCluster per inviare un job Ray.

    1. Verifica che GKE abbia creato il servizio RayCluster:

      kubectl get svc pytorch-mnist-cluster-head-svc
      

      L'output è simile al seguente:

      NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                AGE
      pytorch-mnist-cluster-head-svc   ClusterIP   34.118.238.247   <none>        10001/TCP,8265/TCP,6379/TCP,8080/TCP   109s
      
    2. Stabilisci una sessione di port forwarding verso la testa di Ray:

      kubectl port-forward svc/pytorch-mnist-cluster-head-svc 8265:8265 2>&1 >/dev/null &
      
    3. Verifica che il client Ray possa connettersi al cluster Ray utilizzando localhost:

      ray list nodes --address http://localhost:8265
      

      L'output è simile al seguente:

      Stats:
      ------------------------------
      Total: 3
      
      Table:
      ------------------------------
          NODE_ID                                                   NODE_IP     IS_HEAD_NODE    STATE    NODE_NAME    RESOURCES_TOTAL                 LABELS
      0  1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2  10.28.1.21  False           ALIVE    10.28.1.21   CPU: 2.0                        ray.io/node_id: 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2
      # Several lines of output omitted
      

    Addestra un modello

    Addestra un modello PyTorch utilizzando il set di dati Fashion MNIST:

    1. Invia un job Ray e attendi il completamento:

      ray job submit --submission-id pytorch-mnist-job --working-dir . --runtime-env-json='{"pip": ["torch", "torchvision"], "excludes": ["myenv"]}' --address http://localhost:8265 -- python train.py
      

      L'output è simile al seguente:

      Job submission server address: http://localhost:8265
      
      --------------------------------------------
      Job 'pytorch-mnist-job' submitted successfully
      --------------------------------------------
      
      Next steps
        Query the logs of the job:
          ray job logs pytorch-mnist-job
        Query the status of the job:
          ray job status pytorch-mnist-job
        Request the job to be stopped:
          ray job stop pytorch-mnist-job
      
      Handling connection for 8265
      Tailing logs until the job exits (disable with --no-wait):
      ...
      ...
      
    2. Verifica lo stato del job:

      ray job status pytorch-mnist
      

      L'output è simile al seguente:

      Job submission server address: http://localhost:8265
      Status for job 'pytorch-mnist-job': RUNNING
      Status message: Job is currently running.
      

      Attendi che Status for job sia COMPLETE. L'operazione potrebbe richiedere 15 minuti o più.

    3. Visualizza i log dei job Ray:

      ray job logs pytorch-mnist
      

      L'output è simile al seguente:

      Training started with configuration:
      ╭─────────────────────────────────────────────────╮
      │ Training config                                  │
      ├──────────────────────────────────────────────────┤
      │ train_loop_config/batch_size_per_worker       8  │
      │ train_loop_config/epochs                     10  │
      │ train_loop_config/lr                      0.001  │
      ╰─────────────────────────────────────────────────╯
      
      # Several lines omitted
      
      Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
      ╭───────────────────────────────╮
      │ Training result                │
      ├────────────────────────────────┤
      │ checkpoint_dir_name            │
      │ time_this_iter_s      25.7394  │
      │ time_total_s          351.233  │
      │ training_iteration         10  │
      │ accuracy               0.8656  │
      │ loss                  0.37827  │
      ╰───────────────────────────────╯
      
      # Several lines omitted
      -------------------------------
      Job 'pytorch-mnist' succeeded
      -------------------------------
      

    Esegui il deployment di un RayJob

    La risorsa personalizzata RayJob gestisce il ciclo di vita di una risorsa RayCluster durante l'esecuzione di un singolo job Ray.

    1. Esamina il seguente manifest:

      apiVersion: ray.io/v1
      kind: RayJob
      metadata:
        name: pytorch-mnist-job
      spec:
        shutdownAfterJobFinishes: true
        entrypoint: python ai-ml/gke-ray/raytrain/pytorch-mnist/train.py
        runtimeEnvYAML: |
          pip:
            - torch
            - torchvision
          working_dir: "https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/archive/main.zip"
          env_vars:
            NUM_WORKERS: "4"
            CPUS_PER_WORKER: "2"
        rayClusterSpec:
          rayVersion: '2.37.0'
          headGroupSpec:
            rayStartParams: {}
            template:
              spec:
                containers:
                  - name: ray-head
                    image: rayproject/ray:2.37.0
                    ports:
                      - containerPort: 6379
                        name: gcs-server
                      - containerPort: 8265
                        name: dashboard
                      - containerPort: 10001
                        name: client
                    resources:
                      limits:
                        cpu: "2"
                        ephemeral-storage: "9Gi"
                        memory: "4Gi"
                      requests:
                        cpu: "2"
                        ephemeral-storage: "9Gi"
                        memory: "4Gi"
          workerGroupSpecs:
            - replicas: 4
              minReplicas: 1
              maxReplicas: 5
              groupName: small-group
              rayStartParams: {}
              template:
                spec:
                  containers:
                    - name: ray-worker
                      image: rayproject/ray:2.37.0
                      resources:
                        limits:
                          cpu: "4"
                          ephemeral-storage: "9Gi"
                          memory: "8Gi"
                        requests:
                          cpu: "4"
                          ephemeral-storage: "9Gi"
                          memory: "8Gi"

      Questo manifest descrive una risorsa personalizzata RayJob.

    2. Applica il manifest al cluster GKE:

      kubectl apply -f ray-job.yaml
      
    3. Verifica che la risorsa RayJob sia in esecuzione:

      kubectl get rayjob
      

      L'output è simile al seguente:

      NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME   AGE
      pytorch-mnist-job   RUNNING      Running             2024-06-19T15:43:32Z              2m29s
      

      In questo output, la colonna DEPLOYMENT STATUS indica che la risorsa RayJob è Running.

    4. Visualizza lo stato della risorsa RayJob:

      kubectl logs -f -l job-name=pytorch-mnist-job
      

      L'output è simile al seguente:

      Training started with configuration:
      ╭─────────────────────────────────────────────────╮
      │ Training config                                  │
      ├──────────────────────────────────────────────────┤
      │ train_loop_config/batch_size_per_worker       8  │
      │ train_loop_config/epochs                     10  │
      │ train_loop_config/lr                      0.001  │
      ╰─────────────────────────────────────────────────╯
      
      # Several lines omitted
      
      Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
      ╭───────────────────────────────╮
      │ Training result                │
      ├────────────────────────────────┤
      │ checkpoint_dir_name            │
      │ time_this_iter_s      25.7394  │
      │ time_total_s          351.233  │
      │ training_iteration         10  │
      │ accuracy               0.8656  │
      │ loss                  0.37827  │
      ╰───────────────────────────────╯
      
      # Several lines omitted
      -------------------------------
      Job 'pytorch-mnist' succeeded
      -------------------------------
      
    5. Verifica che il job Ray sia completato:

      kubectl get rayjob
      

      L'output è simile al seguente:

      NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME               AGE
      pytorch-mnist-job   SUCCEEDED    Complete            2024-06-19T15:43:32Z   2024-06-19T15:51:12Z   9m6s
      

      In questo output, la colonna DEPLOYMENT STATUS indica che la risorsa RayJob è Complete.

    Esegui la pulizia

    Elimina il progetto

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    Elimina singole risorse

    Se hai utilizzato un progetto esistente e non vuoi eliminarlo, puoi eliminare le singole risorse. Per eliminare il cluster, digita:

    gcloud container clusters delete ${CLUSTER_NAME}
    

    Passaggi successivi

    • Esplora architetture di riferimento, diagrammi e best practice su Google Cloud. Consulta il nostro Cloud Architecture Center.