Entrena un modelo con GPU en el modo GKE Standard


En este instructivo de inicio rápido, se muestra cómo implementar un modelo de entrenamiento con GPU en Google Kubernetes Engine (GKE) y almacenar las predicciones en Cloud Storage. En este instructivo, se usa un modelo de TensorFlow y clústeres de GKE Standard. También puedes ejecutar estas cargas de trabajo en clústeres de Autopilot con menos pasos de configuración.

Este documento está dirigido a los administradores de GKE que tienen clústeres Standard existentes y desean ejecutar cargas de trabajo de GPU por primera vez.

Antes de comenzar

  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.

    Go to project selector

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

  4. Enable the Kubernetes Engine and Cloud Storage APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

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

  7. Enable the Kubernetes Engine and Cloud Storage APIs.

    Enable the APIs

  8. 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.

Clone el repositorio de muestra

En Cloud Shell, ejecuta el siguiente comando:

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

Crea un clúster de modo Standard y un grupo de nodos de GPU

Usa Cloud Shell para realizar las siguientes acciones:

  1. Crea un clúster de Standard que use la federación de identidades para cargas de trabajo para GKE e instale el controlador de Cloud Storage FUSE:

    gcloud container clusters create gke-gpu-cluster \
        --addons GcsFuseCsiDriver \
        --location=us-central1 \
        --num-nodes=1 \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    Reemplaza PROJECT_ID por el ID del proyecto de Google Cloud.

    La creación del clúster puede tomar varios minutos.

  2. Crea un grupo de nodos de GPU

    gcloud container node-pools create gke-gpu-pool-1 \
        --accelerator=type=nvidia-tesla-t4,count=1,gpu-driver-version=default \
        --machine-type=n1-standard-16 --num-nodes=1 \
        --location=us-central1 \
        --cluster=gke-gpu-cluster
    

Crea un bucket de Cloud Storage

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

    Ir a Crear un bucket

  2. En el campo Asigna un nombre a tu bucket, ingresa el siguiente nombre:

    PROJECT_ID-gke-gpu-bucket
    
  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 Elegir una clase de almacenamiento para tus datos, haz clic en Continuar.

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

  8. Haz clic en Crear.

  9. En el diálogo Se evitará el acceso público, asegúrate de que la casilla de verificación Aplicar la prevención de acceso público a este bucket esté seleccionada y haz clic en Confirmar.

Configura tu clúster a fin de acceder al bucket mediante la federación de identidades para cargas de trabajo para GKE

Para permitir que tu clúster acceda al bucket de Cloud Storage, haz lo siguiente:

  1. Crea una cuenta de servicio de Google Cloud.
  2. Crea una ServiceAccount de Kubernetes en tu clúster.
  3. Vincula la ServiceAccount de Kubernetes a la cuenta de servicio de Google Cloud.

Crea una cuenta de servicio de Google Cloud.

  1. En la consola de Google Cloud, ve a la página Crear cuenta de servicio:

    Ve a Crear cuenta de servicio

  2. En el campo ID de cuenta de servicio, ingresa gke-ai-sa.

  3. Haz clic en Crear y continuar.

  4. En la lista Rol, selecciona el rol Cloud Storage > Servicio de recopilador de Storage Insights.

  5. Haz clic en Agregar otro rol.

  6. En la lista Seleccionar un rol, selecciona el rol Cloud Storage > Administrador de objetos de almacenamiento.

  7. Haz clic en Continuar y, luego, en Listo.

Crea una ServiceAccount de Kubernetes en tu clúster

En Cloud Shell, haz lo siguiente:

  1. Crea un espacio de nombres de Kubernetes:

    kubectl create namespace gke-ai-namespace
    
  2. Crea una ServiceAccount de Kubernetes en el espacio de nombres:

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

Vincula la ServiceAccount de Kubernetes a la cuenta de servicio de Google Cloud

En Cloud Shell, ejecute los siguientes comandos:

  1. Agrega una vinculación de IAM a la cuenta de servicio de Google Cloud:

    gcloud iam service-accounts add-iam-policy-binding gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-ai-namespace/gpu-k8s-sa]"
    

    La marca --member proporciona la identidad completa de la ServiceAccount de Kubernetes en Google Cloud.

  2. Anota la ServiceAccount de Kubernetes:

    kubectl annotate serviceaccount gpu-k8s-sa \
        --namespace gke-ai-namespace \
        iam.gke.io/gcp-service-account=gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com
    

Verifica que los Pods puedan acceder al bucket 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
    

    Reemplaza PROJECT_ID por el ID del proyecto de Google Cloud.

  2. Crea un Pod que tenga un contenedor de TensorFlow:

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

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

  3. Crea un archivo de muestra en el bucket:

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

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

    Cuando el Pod está listo, el resultado es el siguiente:

    pod/test-tensorflow-pod condition met
    
  5. Abre una shell en el contenedor de TensorFlow:

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

    ls /data
    

    El resultado muestra el archivo de muestra.

  7. Verifica 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 adjunta al Pod, similar a lo siguiente:

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

    exit
    
  9. Borra el Pod de muestra:

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

Entrena y realiza predicciones con 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 bucket 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 el trabajo 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. Implementa el trabajo de entrenamiento:

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

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

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

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

    El resultado es similar a este:

    job.batch/mnist-training-job condition met
    
  6. Verifica los registros del contenedor de Tensorflow:

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

    En el resultado, se muestran los siguientes eventos:

    • Instala los paquetes obligatorios de Python
    • Descarga el conjunto de datos de MNIST
    • Entrena 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. Borra la carga de trabajo de entrenamiento:

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

Implementa una carga de trabajo de inferencia

En esta sección, implementarás una carga de trabajo de inferencia que tome un conjunto de datos de muestra como entrada y muestre predicciones.

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

    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. Implementa la carga de trabajo de inferencia:

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

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

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

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

    El resultado es similar a este:

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

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

    El resultado es la predicción para cada imagen y la confianza del modelo en la predicción, que es similar a lo siguiente:

    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.
    

Limpia

Para evitar que se generen cargos en tu cuenta de Google Cloud por los recursos que creaste en esta guía, lleva a cabo una de las siguientes acciones:

  • Mantén el clúster de GKE: Borra los recursos de Kubernetes en el clúster y los recursos de Google Cloud
  • Mantén el proyecto de Google Cloud: Borra el clúster de GKE y los recursos de Google Cloud.
  • Borra el proyecto

Borra los recursos de Kubernetes en el clúster y los recursos de Google Cloud

  1. Borra el espacio de nombres de Kubernetes y las cargas de trabajo que implementaste:

    kubectl -n gke-ai-namespace delete -f src/gke-config/standard-tf-mnist-batch-predict.yaml
    kubectl delete namespace gke-ai-namespace
    
  2. Borra el bucket de Cloud Storage:

    1. Ve a la página Buckets:

      Ir a Buckets

    2. Selecciona la casilla de verificación correspondiente a PROJECT_ID-gke-gpu-bucket.

    3. Haz clic en Borrar.

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

  3. Borra la cuenta de servicio de Google Cloud:

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

      Ir a Cuentas de servicio

    2. Selecciona tu proyecto.

    3. Selecciona la casilla de verificación correspondiente a gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com.

    4. Haz clic en Borrar.

    5. Para confirmar la eliminación, haz clic en Borrar.

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

  1. Borra el clúster de GKE:

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

      Ir a los clústeres

    2. Selecciona la casilla de verificación correspondiente a gke-gpu-cluster.

    3. Haz clic en Borrar.

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

  2. Borra el bucket de Cloud Storage:

    1. Ve a la página Buckets:

      Ir a Buckets

    2. Selecciona la casilla de verificación correspondiente a PROJECT_ID-gke-gpu-bucket.

    3. Haz clic en Borrar.

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

  3. Borra la cuenta de servicio de Google Cloud:

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

      Ir a Cuentas de servicio

    2. Selecciona tu proyecto.

    3. Selecciona la casilla de verificación correspondiente a gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com.

    4. Haz clic en Borrar.

    5. Para confirmar la eliminación, haz clic en Borrar.

Borra 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.

¿Qué sigue?