Entrena un modelo con GPUs en el modo Autopilot de GKE


En esta guía de inicio rápido se muestra cómo desplegar un modelo de entrenamiento con GPUs en Google Kubernetes Engine (GKE) y almacenar las predicciones en Cloud Storage. Este documento está dirigido a administradores de GKE que tengan clústeres en modo Autopilot y quieran ejecutar cargas de trabajo de GPU por primera vez.

También puedes ejecutar estas cargas de trabajo en clústeres estándar si creas grupos de nodos de GPU independientes en tus clústeres. Para obtener instrucciones, consulta el artículo Entrenar un modelo con GPUs en el modo GKE Standard.

Antes de empezar

  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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the GKE and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. Install the Google Cloud CLI.

  6. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  7. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  9. Verify that billing is enabled for your Google Cloud project.

  10. Enable the GKE and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  11. Install the Google Cloud CLI.

  12. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  13. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  14. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  15. Clonar el repositorio de muestra

    En Cloud Shell, ejecuta el siguiente comando:

    git clone https://github.com/GoogleCloudPlatform/ai-on-gke && \
    cd ai-on-gke/tutorials-and-examples/gpu-examples/training-single-gpu
    

    Crear un clúster

    1. En la Google Cloud consola, ve a la página Crear un clúster de Autopilot:

      Ir a Crear un clúster de Autopilot

    2. En el campo Name (Nombre), introduce gke-gpu-cluster.

    3. En la lista Región, selecciona us-central1.

    4. Haz clic en Crear.

    Crea un segmento de Cloud Storage

    1. En la Google Cloud consola, ve a la página Crear un bucket:

      Ir a Crear un segmento

    2. En el campo Name your bucket (Ponle nombre al contenedor), introduce el siguiente nombre:

      PROJECT_ID-gke-gpu-bucket
      

      Sustituye PROJECT_ID por el ID de tu proyecto. Google Cloud

    3. Haz clic en Continuar.

    4. En Tipo de ubicación, selecciona Región.

    5. En la lista Región, selecciona us-central1 (Iowa) y haz clic en Continuar.

    6. En la sección Elige una clase de almacenamiento para tus datos, haz clic en Continuar.

    7. En la sección Selecciona cómo controlar el acceso a los objetos, en Control de acceso, selecciona Uniforme.

    8. Haz clic en Crear.

    9. En el cuadro de diálogo Se impedirá el acceso público, asegúrate de que la casilla Aplicar la prevención del acceso público a este segmento esté marcada y haz clic en Confirmar.

    Configurar el clúster para acceder al bucket mediante Workload Identity Federation for GKE

    Para que tu clúster pueda acceder al segmento de Cloud Storage, haz lo siguiente:

    1. Crea una cuenta de servicio de Kubernetes en tu clúster.
    2. Crea una política de gestión de identidades y accesos que permita a ServiceAccount acceder al segmento.

    Crear una cuenta de servicio de Kubernetes en tu clúster

    En Cloud Shell, haz lo siguiente:

    1. Conéctate al clúster:

      gcloud container clusters get-credentials gke-gpu-cluster \
          --location=us-central1
      
    2. Crea un espacio de nombres de Kubernetes:

      kubectl create namespace gke-gpu-namespace
      
    3. Crea una cuenta de servicio de Kubernetes en el espacio de nombres:

      kubectl create serviceaccount gpu-k8s-sa --namespace=gke-gpu-namespace
      

    Crear una política de gestión de identidades y accesos de permiso en el bucket

    Concede el rol Administrador de objetos de Storage (roles/storage.objectAdmin) en el bucket a la cuenta de servicio de Kubernetes:

    gcloud storage buckets add-iam-policy-binding gs://PROJECT_ID-gke-gpu-bucket \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/gke-gpu-namespace/sa/gpu-k8s-sa \
        --role=roles/storage.objectAdmin \
        --condition=None
    

    Sustituye PROJECT_NUMBER por el número de tu proyecto. Google Cloud

    Verificar que los pods pueden acceder al segmento de Cloud Storage

    1. En Cloud Shell, crea las siguientes variables de entorno:

      export K8S_SA_NAME=gpu-k8s-sa
      export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
      

      Sustituye PROJECT_ID por el ID de tu proyecto. Google Cloud

    2. Crea un pod que tenga un contenedor TensorFlow:

      envsubst < src/gke-config/standard-tensorflow-bash.yaml | kubectl --namespace=gke-gpu-namespace apply -f -
      

      Este comando inserta las variables de entorno que has creado en las referencias correspondientes del manifiesto. También puedes abrir el archivo de manifiesto en un editor de texto y sustituir $K8S_SA_NAME y $BUCKET_NAME por los valores correspondientes.

    3. Crea un archivo de muestra en el segmento:

      touch sample-file
      gcloud storage cp sample-file gs://PROJECT_ID-gke-gpu-bucket
      
    4. Espera a que tu Pod esté listo:

      kubectl wait --for=condition=Ready pod/test-tensorflow-pod -n=gke-gpu-namespace --timeout=180s
      

      Cuando el pod esté listo, el resultado será el siguiente:

      pod/test-tensorflow-pod condition met
      

      Si el comando agota el tiempo de espera, es posible que GKE siga creando nodos para ejecutar los pods. Vuelve a ejecutar el comando y espera a que el pod esté listo.

    5. Abre un shell en el contenedor de TensorFlow:

      kubectl -n gke-gpu-namespace exec --stdin --tty test-tensorflow-pod --container tensorflow -- /bin/bash
      
    6. Intenta leer el archivo de muestra que has creado:

      ls /data
      

      En el resultado se muestra el archivo de ejemplo.

    7. Consulta los registros para identificar la GPU conectada al pod:

      python -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
      

      El resultado muestra la GPU conectada al Pod, de forma similar a lo siguiente:

      ...
      PhysicalDevice(name='/physical_device:GPU:0',device_type='GPU')
      
    8. Sal del contenedor:

      exit
      
    9. Elimina el pod de ejemplo:

      kubectl delete -f src/gke-config/standard-tensorflow-bash.yaml \
          --namespace=gke-gpu-namespace
      

    Entrenar y predecir usando el conjunto de datos MNIST

    En esta sección, ejecutarás una carga de trabajo de entrenamiento en el conjunto de datos de ejemplo MNIST.

    1. Copia los datos de ejemplo en el segmento de Cloud Storage:

      gcloud storage cp src/tensorflow-mnist-example gs://PROJECT_ID-gke-gpu-bucket/ --recursive
      
    2. Crea las siguientes variables de entorno:

      export K8S_SA_NAME=gpu-k8s-sa
      export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
      
    3. Revisa la tarea de entrenamiento:

      # Copyright 2023 Google LLC
      #
      # Licensed under the Apache License, Version 2.0 (the "License");
      # you may not use this file except in compliance with the License.
      # You may obtain a copy of the License at
      #
      #      http://www.apache.org/licenses/LICENSE-2.0
      #
      # Unless required by applicable law or agreed to in writing, software
      # distributed under the License is distributed on an "AS IS" BASIS,
      # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      # See the License for the specific language governing permissions and
      # limitations under the License.
      
      apiVersion: batch/v1
      kind: Job
      metadata:
        name: mnist-training-job
      spec:
        template:
          metadata:
            name: mnist
            annotations:
              gke-gcsfuse/volumes: "true"
          spec:
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-tesla-t4
            tolerations:
            - key: "nvidia.com/gpu"
              operator: "Exists"
              effect: "NoSchedule"
            containers:
            - name: tensorflow
              image: tensorflow/tensorflow:latest-gpu 
              command: ["/bin/bash", "-c", "--"]
              args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_train_distributed.py"]
              resources:
                limits:
                  nvidia.com/gpu: 1
                  cpu: 1
                  memory: 3Gi
              volumeMounts:
              - name: gcs-fuse-csi-vol
                mountPath: /data
                readOnly: false
            serviceAccountName: $K8S_SA_NAME
            volumes:
            - name: gcs-fuse-csi-vol
              csi:
                driver: gcsfuse.csi.storage.gke.io
                readOnly: false
                volumeAttributes:
                  bucketName: $BUCKET_NAME
                  mountOptions: "implicit-dirs"
            restartPolicy: "Never"
    4. Despliega la tarea de entrenamiento:

      envsubst < src/gke-config/standard-tf-mnist-train.yaml | kubectl -n gke-gpu-namespace apply -f -
      

      Este comando sustituye las variables de entorno que has creado por las referencias correspondientes en el manifiesto. También puedes abrir el archivo de manifiesto en un editor de texto y sustituir $K8S_SA_NAME y $BUCKET_NAME por los valores correspondientes.

    5. Espera hasta que el trabajo tenga el estado Completed:

      kubectl wait -n gke-gpu-namespace --for=condition=Complete job/mnist-training-job --timeout=180s
      

      Cuando la tarea esté lista, el resultado será similar al siguiente:

      job.batch/mnist-training-job condition met
      

      Si el comando agota el tiempo de espera, es posible que GKE siga creando nodos para ejecutar los pods. Vuelve a ejecutar el comando y espera a que el trabajo esté listo.

    6. Consulta los registros del contenedor de TensorFlow:

      kubectl logs -f jobs/mnist-training-job -c tensorflow -n gke-gpu-namespace
      

      En el resultado se muestran los siguientes eventos:

      • Instalar los paquetes de Python necesarios
      • Descargar el conjunto de datos MNIST
      • Entrenar el modelo con una GPU
      • Guarda el modelo
      • Evaluar el modelo
      ...
      Epoch 12/12
      927/938 [============================>.] - ETA: 0s - loss: 0.0188 - accuracy: 0.9954
      Learning rate for epoch 12 is 9.999999747378752e-06
      938/938 [==============================] - 5s 6ms/step - loss: 0.0187 - accuracy: 0.9954 - lr: 1.0000e-05
      157/157 [==============================] - 1s 4ms/step - loss: 0.0424 - accuracy: 0.9861
      Eval loss: 0.04236088693141937, Eval accuracy: 0.9861000180244446
      Training finished. Model saved
      
    7. Elimina la carga de trabajo de entrenamiento:

      kubectl -n gke-gpu-namespace delete -f src/gke-config/standard-tf-mnist-train.yaml
      

    Desplegar una carga de trabajo de inferencia

    En esta sección, implementarás una carga de trabajo de inferencia que toma un conjunto de datos de ejemplo como entrada y devuelve predicciones.

    1. Copia las imágenes para la predicción en el segmento:

      gcloud storage cp data/mnist_predict gs://PROJECT_ID-gke-gpu-bucket/ --recursive
      
    2. Revisa la carga de trabajo de inferencia:

      # Copyright 2023 Google LLC
      #
      # Licensed under the Apache License, Version 2.0 (the "License");
      # you may not use this file except in compliance with the License.
      # You may obtain a copy of the License at
      #
      #      http://www.apache.org/licenses/LICENSE-2.0
      #
      # Unless required by applicable law or agreed to in writing, software
      # distributed under the License is distributed on an "AS IS" BASIS,
      # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      # See the License for the specific language governing permissions and
      # limitations under the License.
      
      apiVersion: batch/v1
      kind: Job
      metadata:
        name: mnist-batch-prediction-job
      spec:
        template:
          metadata:
            name: mnist
            annotations:
              gke-gcsfuse/volumes: "true"
          spec:
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-tesla-t4
            tolerations:
            - key: "nvidia.com/gpu"
              operator: "Exists"
              effect: "NoSchedule"
            containers:
            - name: tensorflow
              image: tensorflow/tensorflow:latest-gpu 
              command: ["/bin/bash", "-c", "--"]
              args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_batch_predict.py"]
              resources:
                limits:
                  nvidia.com/gpu: 1
                  cpu: 1
                  memory: 3Gi
              volumeMounts:
              - name: gcs-fuse-csi-vol
                mountPath: /data
                readOnly: false
            serviceAccountName: $K8S_SA_NAME
            volumes:
            - name: gcs-fuse-csi-vol
              csi:
                driver: gcsfuse.csi.storage.gke.io
                readOnly: false
                volumeAttributes:
                  bucketName: $BUCKET_NAME
                  mountOptions: "implicit-dirs"
            restartPolicy: "Never"
    3. Despliega la carga de trabajo de inferencia:

      envsubst < src/gke-config/standard-tf-mnist-batch-predict.yaml | kubectl -n gke-gpu-namespace apply -f -
      

      Este comando sustituye las variables de entorno que has creado por las referencias correspondientes en el manifiesto. También puedes abrir el archivo de manifiesto en un editor de texto y sustituir $K8S_SA_NAME y $BUCKET_NAME por los valores correspondientes.

    4. Espera hasta que el trabajo tenga el estado Completed:

      kubectl wait -n gke-gpu-namespace --for=condition=Complete job/mnist-batch-prediction-job --timeout=180s
      

      El resultado debería ser similar al siguiente:

      job.batch/mnist-batch-prediction-job condition met
      
    5. Consulta los registros del contenedor de TensorFlow:

      kubectl logs -f jobs/mnist-batch-prediction-job -c tensorflow -n gke-gpu-namespace
      

      El resultado es la predicción de cada imagen y la confianza del modelo en la predicción, como se muestra a continuación:

      Found 10 files belonging to 1 classes.
      1/1 [==============================] - 2s 2s/step
      The image /data/mnist_predict/0.png is the number 0 with a 100.00 percent confidence.
      The image /data/mnist_predict/1.png is the number 1 with a 99.99 percent confidence.
      The image /data/mnist_predict/2.png is the number 2 with a 100.00 percent confidence.
      The image /data/mnist_predict/3.png is the number 3 with a 99.95 percent confidence.
      The image /data/mnist_predict/4.png is the number 4 with a 100.00 percent confidence.
      The image /data/mnist_predict/5.png is the number 5 with a 100.00 percent confidence.
      The image /data/mnist_predict/6.png is the number 6 with a 99.97 percent confidence.
      The image /data/mnist_predict/7.png is the number 7 with a 100.00 percent confidence.
      The image /data/mnist_predict/8.png is the number 8 with a 100.00 percent confidence.
      The image /data/mnist_predict/9.png is the number 9 with a 99.65 percent confidence.
      

    Limpieza

    Para evitar que se apliquen cargos en tu cuenta de Google Cloud por los recursos que has creado en esta guía, haz una de las siguientes acciones:

    • Mantener el clúster de GKE: elimina los recursos de Kubernetes del clúster y los recursos de Google Cloud .
    • Mantener el Google Cloud proyecto: elimina el clúster de GKE y los Google Cloud recursos.
    • Eliminar el proyecto

    Elimina los recursos de Kubernetes del clúster y los recursos de Google Cloud .

    1. Elimina el espacio de nombres de Kubernetes y las cargas de trabajo que hayas desplegado:

      kubectl -n gke-gpu-namespace delete -f src/gke-config/standard-tf-mnist-batch-predict.yaml
      kubectl delete namespace gke-gpu-namespace
      
    2. Elimina el segmento de Cloud Storage:

      1. Ve a la página Segmentos:

        Ir a Contenedores

      2. Marca la casilla de PROJECT_ID-gke-gpu-bucket.

      3. Haz clic en Eliminar.

      4. Para confirmar la eliminación, escribe DELETE y haz clic en Eliminar.

    3. Elimina la cuenta de servicio Google Cloud :

      1. Ve a la página Cuentas de servicio:

        Ir a Cuentas de servicio

      2. Selecciona el proyecto.

      3. Marca la casilla de gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com.

      4. Haz clic en Eliminar.

      5. Para confirmar que quieres eliminarlo, haz clic en Eliminar.

    Eliminar el clúster de GKE y los recursos de Google Cloud

    1. Elimina el clúster de GKE:

      1. Ve a la página Clústeres:

        Ir a Clústeres

      2. Marca la casilla de gke-gpu-cluster.

      3. Haz clic en Eliminar.

      4. Para confirmar la eliminación, escribe gke-gpu-cluster y haz clic en Eliminar.

    2. Elimina el segmento de Cloud Storage:

      1. Ve a la página Segmentos:

        Ir a Contenedores

      2. Marca la casilla de PROJECT_ID-gke-gpu-bucket.

      3. Haz clic en Eliminar.

      4. Para confirmar la eliminación, escribe DELETE y haz clic en Eliminar.

    3. Elimina la cuenta de servicio Google Cloud :

      1. Ve a la página Cuentas de servicio:

        Ir a Cuentas de servicio

      2. Selecciona el proyecto.

      3. Marca la casilla de gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com.

      4. Haz clic en Eliminar.

      5. Para confirmar que quieres eliminarlo, haz clic en Eliminar.

    Eliminar el proyecto

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Siguientes pasos