Treinar um modelo com GPUs no modo Autopilot do GKE


Neste guia de início rápido, mostramos como implantar um modelo de treinamento com GPUs no Google Kubernetes Engine (GKE) e armazenar as previsões no Cloud Storage. Este documento é destinado a administradores do GKE que já têm clusters no modo Autopilot e querem executar cargas de trabalho de GPU pela primeira vez.

Também é possível executar essas cargas de trabalho em clusters do Standard se você criar pools de nós de GPU separados nos clusters. Para instruções, consulte Treinar um modelo com GPUs no GKE Standard GKE.

Antes de começar

  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 GKE and Cloud Storage APIs.

    Enable the APIs

  5. Install the Google Cloud CLI.

  6. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.

  7. Para inicializar a gcloud CLI, execute o seguinte comando:

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

    Go to project selector

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

  10. Enable the GKE and Cloud Storage APIs.

    Enable the APIs

  11. Install the Google Cloud CLI.

  12. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.

  13. Para inicializar a gcloud CLI, execute o seguinte 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. clone o repositório de exemplo

    No Cloud Shell, execute este comando:

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

    Criar um cluster

    1. No Google Cloud console, acesse a página Criar um cluster do Autopilot:

      Acessar "Criar um cluster do Autopilot"

    2. No campo Nome, use gke-gpu-cluster.

    3. Na lista Região, selecione us-central1.

    4. Clique em Criar.

    Criar um bucket do Cloud Storage

    1. No console Google Cloud , acesse a página Criar um bucket:

      Acessar "Criar um bucket"

    2. No campo Nomeie seu bucket, insira o seguinte nome:

      PROJECT_ID-gke-gpu-bucket
      

      Substitua PROJECT_ID pelo ID do projeto Google Cloud.

    3. Clique em Continuar.

    4. Em Tipo de local, selecione Região.

    5. Na lista Região, selecione us-central1 (Iowa) e clique em Continuar.

    6. Na seção Escolha uma classe de armazenamento para seus dados, clique em Continuar.

    7. Na seção Escolha como controlar o acesso a objetos, em Controle de acesso, selecione Uniforme.

    8. Clique em Criar.

    9. Na caixa de diálogo O acesso público será impedido verifique se a caixa de seleção Aplicar a prevenção contra acesso público neste bucket está marcada e clique em Confirmar.

    Configurar o cluster para acessar o bucket usando a federação de identidade da carga de trabalho do GKE

    Para permitir que o cluster acesse o bucket do Cloud Storage, faça o seguinte:

    1. Crie uma conta de serviço do Kubernetes no cluster.
    2. Crie uma política de permissão do IAM que permita à ServiceAccount acessar o bucket.

    Criar uma conta de serviço do Kubernetes no cluster

    No Cloud Shell, faça o seguinte:

    1. Conecte-se ao cluster:

      gcloud container clusters get-credentials gke-gpu-cluster \
          --location=us-central1
      
    2. Crie um namespace do Kubernetes:

      kubectl create namespace gke-gpu-namespace
      
    3. Crie uma conta de serviço do Kubernetes no namespace:

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

    Criar uma política de permissão do IAM no bucket

    Conceda o papel de administrador de objetos do Storage (roles/storage.objectAdmin) no bucket à conta de serviço do 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
    

    Substitua PROJECT_NUMBER pelo número do seu projeto Google Cloud.

    Verifique se os pods podem acessar o bucket do Cloud Storage

    1. No Cloud Shell, crie as seguintes variáveis de ambiente:

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

      Substitua PROJECT_ID pelo ID do projeto Google Cloud.

    2. Crie um pod que tenha um contêiner do TensorFlow:

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

      Esse comando insere as variáveis de ambiente que você criou nas referências correspondentes no manifesto. Também é possível abrir o manifesto em um editor de texto e substituir $K8S_SA_NAME e $BUCKET_NAME pelos valores correspondentes.

    3. Crie um arquivo de amostra no bucket:

      touch sample-file
      gcloud storage cp sample-file gs://PROJECT_ID-gke-gpu-bucket
      
    4. Aguarde até que o pod esteja pronto:

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

      Quando o pod estiver pronto, a saída será a seguinte:

      pod/test-tensorflow-pod condition met
      

      Se o comando expirar, o GKE ainda poderá estar criando novos nós para executar os pods. Execute o comando novamente e aguarde o pod ficar pronto.

    5. Abra um shell no contêiner do TensorFlow:

      kubectl -n gke-gpu-namespace exec --stdin --tty test-tensorflow-pod --container tensorflow -- /bin/bash
      
    6. Tente ler o arquivo de amostra que você criou:

      ls /data
      

      A saída mostra o arquivo de amostra.

    7. Verifique os registros para identificar a GPU anexada ao pod:

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

      A saída mostra a GPU anexada ao pod, semelhante à seguinte:

      ...
      PhysicalDevice(name='/physical_device:GPU:0',device_type='GPU')
      
    8. Saia do contêiner:

      exit
      
    9. Exclua o pod de amostra:

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

    Treinar e prever usando o conjunto de dados MNIST

    Nesta seção, você executará uma carga de trabalho de treinamento no conjunto de dados de exemplo MNIST.

    1. Copie os dados de exemplo para o bucket do Cloud Storage:

      gcloud storage cp src/tensorflow-mnist-example gs://PROJECT_ID-gke-gpu-bucket/ --recursive
      
    2. Crie as variáveis de ambiente a seguir:

      export K8S_SA_NAME=gpu-k8s-sa
      export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
      
    3. Revise o job de treinamento:

      # 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. Implante o job de treinamento:

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

      Esse comando substitui as variáveis de ambiente que você criou nas referências correspondentes no manifesto. Também é possível abrir o manifesto em um editor de texto e substituir $K8S_SA_NAME e $BUCKET_NAME pelos valores correspondentes.

    5. Aguarde até que o job tenha o status Completed:

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

      Quando o job estiver pronto, a saída será semelhante a esta:

      job.batch/mnist-training-job condition met
      

      Se o comando expirar, o GKE ainda poderá estar criando novos nós para executar os pods. Execute o comando novamente e aguarde até que o job fique pronto.

    6. Verifique os registros do contêiner do TensorFlow:

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

      A saída mostra que os seguintes eventos ocorrem:

      • Instalar os pacotes Python necessários
      • Fazer o download do conjunto de dados MNIST
      • Treinar o modelo usando uma GPU
      • Salvar o modelo
      • Avalie o 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. Exclua a carga de trabalho de treinamento:

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

    Implantar uma carga de trabalho de inferência

    Nesta seção, você implantará uma carga de trabalho de inferência que usa um conjunto de dados de amostra como entrada e retorna previsões.

    1. Copie as imagens para predição para o bucket:

      gcloud storage cp data/mnist_predict gs://PROJECT_ID-gke-gpu-bucket/ --recursive
      
    2. Revise a carga de trabalho de inferência:

      # 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. Implante a carga de trabalho de inferência:

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

      Esse comando substitui as variáveis de ambiente que você criou nas referências correspondentes no manifesto. Também é possível abrir o manifesto em um editor de texto e substituir $K8S_SA_NAME e $BUCKET_NAME pelos valores correspondentes.

    4. Aguarde até que o job tenha o status Completed:

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

      O resultado será assim:

      job.batch/mnist-batch-prediction-job condition met
      
    5. Verifique os registros do contêiner do TensorFlow:

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

      A saída é a previsão para cada imagem e a confiança do modelo na previsão, semelhante ao seguinte:

      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.
      

    Limpar

    Para evitar cobranças na sua conta do Google Cloud pelos recursos criados neste guia, faça o seguinte:

    • Manter o cluster do GKE:exclua os recursos do Kubernetes no cluster e os recursos do Google Cloud .
    • Manter o projeto Google Cloud :exclua o cluster do GKE e os recursos Google Cloud .
    • Excluir o projeto

    Excluir os recursos do Kubernetes no cluster e os recursos do Google Cloud

    1. Exclua o namespace do Kubernetes e as cargas de trabalho implantadas:

      kubectl -n gke-gpu-namespace delete -f src/gke-config/standard-tf-mnist-batch-predict.yaml
      kubectl delete namespace gke-gpu-namespace
      
    2. Exclua o bucket do Cloud Storage:

      1. Acessar a página Buckets:

        Acessar buckets

      2. Marque a caixa de seleção de PROJECT_ID-gke-gpu-bucket.

      3. Clique em Excluir.

      4. Para confirmar a exclusão, digite DELETE e clique em Excluir.

    3. Exclua a conta de serviço Google Cloud :

      1. Acessar a página Contas de serviço

        Acesse as Contas de serviço

      2. Selecione o projeto.

      3. Marque a caixa de seleção de gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com.

      4. Clique em Excluir.

      5. Para confirmar a exclusão, clique em Excluir.

    Excluir o cluster do GKE e os recursos do Google Cloud

    1. Exclua o cluster do GKE:

      1. Acessar a página de clusters:

        Acessar Clusters

      2. Marque a caixa de seleção de gke-gpu-cluster.

      3. Clique em Excluir.

      4. Para confirmar a exclusão, digite gke-gpu-cluster e clique em Excluir.

    2. Exclua o bucket do Cloud Storage:

      1. Acessar a página Buckets:

        Acessar buckets

      2. Marque a caixa de seleção de PROJECT_ID-gke-gpu-bucket.

      3. Clique em Excluir.

      4. Para confirmar a exclusão, digite DELETE e clique em Excluir.

    3. Exclua a conta de serviço Google Cloud :

      1. Acessar a página Contas de serviço

        Acesse as Contas de serviço

      2. Selecione o projeto.

      3. Marque a caixa de seleção de gke-gpu-sa@PROJECT_ID.iam.gserviceaccount.com.

      4. Clique em Excluir.

      5. Para confirmar a exclusão, clique em Excluir.

    Excluir o projeto

    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.

    A seguir