Como implantar uma carga de trabalho de machine learning em lote


Neste tutorial, demonstramos como usar o Google Kubernetes Engine (GKE) para gerenciar cargas de trabalho em lote tolerantes a falhas e manter seus custos baixos. Siga este tutorial para saber como usar jobs e VMs do Spot otimizadas para custos, além de como configurar uma fila de jobs do Redis no cluster no GKE.

Experiência

Uma carga de trabalho em lote é um processo geralmente criado para ter um ponto de partida e de conclusão. Considere as cargas de trabalho em lote no GKE se a arquitetura envolver a ingestão, o processamento e a saída de dados em vez de usar dados brutos. Áreas como machine learning, inteligência artificial, e computação de alto desempenho (HPC) apresentam diferentes tipos de cargas de trabalho em lote, como treinamento de modelos off-line, previsão em lote, análise de dados, simulação de sistemas físicos e processamento de vídeo.

Ao projetar cargas de trabalho em lote em contêineres, é possível aproveitar os seguintes benefícios do GKE:

  • Uma comunidade ampla, um padrão aberto e um serviço gerenciado.
  • Eficiência de custos com orquestração efetiva de cargas de trabalho e infraestrutura e recursos computacionais especializados.
  • Isolamento e portabilidade de contentorização, permitindo o uso da nuvem como capacidade excedente, mantendo a segurança dos dados.
  • Disponibilidade da capacidade de burst, seguida pela redução rápida do escalonamento dos clusters do GKE.

Objetivos

Este tutorial é voltado a engenheiros de machine learning ou cientistas de dados que querem executar cargas de trabalho de machine learning em lote no GKE com a seguinte arquitetura econômica e escalonável:

Diagrama da arquitetura

Este tutorial inclui as etapas a seguir:

  1. Criar um cluster do GKE com pools de nós de VM do Spot e do Standard.
  2. Criar um volume NFS do Filestore.
  3. Criar uma fila de jobs do Redis no cluster.
  4. Transferir conjuntos de dados para o volume NFS e enfileirá-los para serem consumidos pela carga de trabalho.
  5. Executar uma carga de trabalho de machine learning em lote no cluster do GKE.

Custos

Neste tutorial, usamos os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

Crie o projeto

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No console do Google Cloud, na página do seletor de projetos, clique em Criar projeto para começar a criar um novo projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como verificar se o faturamento está ativado em um projeto.

  4. Ative as APIs Compute Engine, GKE, and Filestore.

    Ative as APIs

  5. No console do Google Cloud, na página do seletor de projetos, clique em Criar projeto para começar a criar um novo projeto do Google Cloud.

    Acessar o seletor de projetos

  6. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como verificar se o faturamento está ativado em um projeto.

  7. Ative as APIs Compute Engine, GKE, and Filestore.

    Ative as APIs

configure o ambiente

Neste tutorial, você usará o Cloud Shell para gerenciar recursos hospedados no Google Cloud. O Cloud Shell vem pré-instalado com o Docker, bem como kubectl e a CLI gcloud.

Siga estes passos para configurar o ambiente usando o Cloud Shell:

  1. No Console do Google Cloud, inicie uma instância do Cloud Shell.
    Abra o Cloud Shell.

  2. Faça o download do código-fonte para este app de amostra.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
    cd kubernetes-engine-samples/batch/aiml-workloads
    
  3. Atualize o arquivo scripts/variables.sh com as informações do projeto:

    sed -i "\
      s/<YOUR_PROJECT_ID>/PROJECT_ID/g; \
      s/<YOUR_REGION>/REGION/g; \
      s/<YOUR_ZONE>/ZONE/g" \
      scripts/variables.sh
    

    Substitua:

  4. Defina as variáveis de ambiente e os padrões gcloud necessários.

    source scripts/variables.sh
    gcloud config set project ${PROJECT_ID}
    gcloud config set compute/region ${REGION}
    gcloud config set compute/zone ${ZONE}
    gcloud config set filestore/zone ${ZONE}
    

Crie um cluster do GKE

Criar um cluster do GKE com dois pools de nós, em que o GKE hospeda o volume permanente e executa a carga de trabalho com a fila de jobs do Redis.

  1. Crie um cluster do GKE do Standard. Esse cluster inicializa um pool de nós com configurações padrão.

    gcloud container clusters create ${CLUSTER_NAME} \
      --machine-type=e2-standard-2 --num-nodes=3
    
  2. Verifique se o cluster do GKE está em execução:

    gcloud container clusters list
    

    O valor STATUS é RUNNING para o cluster batch-aiml.

  3. Crie um segundo pool de nós no cluster do GKE que será ativado com VMs do Spot:

    gcloud beta container node-pools create batch-node-pool \
      --cluster=${CLUSTER_NAME} --spot
    

    Você implantará a carga de trabalho em lote neste pool de nós de VM do Spot mais tarde no tutorial.

Configurar o armazenamento de conjuntos de dados com um Network File System (NFS)

A carga de trabalho de machine learning requer uma solução de armazenamento para os conjuntos de dados e arquivos de saída. Neste tutorial, você criará uma instância do Filestore, que pode ser acessada por todos os nós (leitura e operações de gravação) em um cluster do GKE por meio de um Volume permanente (PV) e Reivindicação de volume permanente (PVC).

Para saber mais, veja como projetar uma estratégia de armazenamento ideal e como acessar compartilhamentos de arquivos dos clusters do GKE.

Criar uma instância do Firestore

  1. Criar uma instância do Filestore:

    gcloud filestore instances create ${FILESTORE_ID} \
      --tier=BASIC_HDD \
      --file-share=name="NFSVol",capacity=1TB \
      --network=name="default"
    

    onde:

    • tier é o nível de serviço da instância do Filestore. Esta amostra usa a oferta básica, mas é possível saber mais sobre as outras opções em Níveis de serviço.

    • network=name é o nome da rede de nuvem privada virtual (VPC) do Compute Engine a que a instância está conectada. O cluster do GKE precisa estar na mesma rede VPC que a instância do Filestore.

    • capacity é o tamanho desejado do volume. Especifique o valor de armazenamento em uma das unidades compatíveis descritas em Quantidades de recursos.

  2. Verifique se a instância do Filestore foi implantada:

    gcloud filestore instances list --project=${PROJECT_ID} --zone=${ZONE}
    

    A saída é semelhante à seguinte, em que o valor STATE é READY para a instância batch-aiml-filestore:

    INSTANCE_NAME: batch-aiml-filestore
    LOCATION: us-central1-b
    TIER: BASIC_HDD
    CAPACITY_GB: 1024
    FILE_SHARE_NAME: NFSVol
    IP_ADDRESS: 10.152.101.10
    STATE: READY
    CREATE_TIME: 2022-03-15T18:23:51
    
  3. Na saída, anote o valor IP_ADDRESS. Ele será usado na próxima seção.

Criar um volume permanente

Uma especificação de volume permanente (PV, na sigla em inglês) do Kubernetes permite que o cluster do GKE se conecte à instância do Filestore.

  1. Atualize o arquivo kubernetes-manifests/persistent-volume.yaml com o endereço IP da instância do Filestore:

    sed -i "\
      s/<FILESTORE_IP_ADDRESS>/IP_ADDRESS/g" \
      kubernetes-manifests/persistent-volume.yaml
    

    Substitua IP_ADDRESS pelo valor que você anotou ao criar a instância do Filestore.

  2. Implante a especificação do PV:

    kubectl apply -f kubernetes-manifests/persistent-volume.yaml
    

Criar uma reivindicação de volume permanente

Uma especificação de reivindicação de volume permanente (PVC, na sigla em inglês) do Kubernetes permite que pods e jobs do Kubernetes acessem os recursos de armazenamento de um volume permanente.

Implante a especificação do PVC:

kubectl apply -f kubernetes-manifests/persistent-volume-claim.yaml

Consumir a reivindicação de volume permanente

Com o volume permanente e a declaração de volume permanente configurados no cluster do GKE, é possível configurar o servidor Redis e os jobs em lote para consumir o PVC. Ele aparecerá como um volume de armazenamento montável na VM que executa os recursos do Kubernetes.

Inspecione os arquivos kubernetes-manifests/redis-pod.yaml e kubernetes-manifests/workload.yaml. As configurações do manifesto são semelhantes às seguintes:

  spec:
  …
  containers:
  - name: workload
    image: "us-central1-docker.pkg.dev/gke-batch-aiml/batch-aiml-docker-repo/workload"
    volumeMounts:
    - mountPath: /mnt/fileserver
      name: workload-pvc
  volumes:
  - name: workload-pvc
    persistentVolumeClaim:
      claimName: fileserver-claim
      readOnly: false

onde:

  • spec.volumes especifica as declarações de volume permanente para consumir.

  • spec.containers.volumeMounts especifica o caminho do arquivo local na VM em que o compartilhamento de arquivos do Filestore pode ser acessado.

Configurar uma fila de jobs do Redis

A carga de trabalho processará dados em lotes para treinar iterativamente o modelo de detecção de fraudes. Para gerenciar os conjuntos de dados que estão sendo processados ou ainda na fila, implante o servidor Redis no cluster do GKE.

Para simplificar, inicie uma única instância do Redis nesta amostra. Para um exemplo de como implantar o Redis de maneira escalonável e redundante, veja como criar um livro de visitas com Redis e PHP.

  1. Implante a especificação do servidor do Redis.

    kubectl apply -f kubernetes-manifests/redis-pod.yaml
    
  2. Verifique se o pod está em execução antes de continuar. Na saída do comando a seguir, o STATUS do pod redis-leader precisa ser Running.

    kubectl get pods
    

    A saída será assim:

    NAME           READY   STATUS    RESTARTS   AGE
    redis-leader   1/1     Running   0          118s
    
  3. Transfira os arquivos que contêm os conjuntos de dados de treinamento e teste para o volume NFS.

    sh scripts/transfer-datasets.sh
    

    Esse script copia os arquivos do repositório de código de amostra para o diretório /mnt/fileserver/datasets/ no pod redis-leader.

  4. Preencha a fila do Redis.

    sh scripts/queue-jobs.sh
    

    Esse script envia os caminhos de arquivo para os conjuntos de dados de treinamento a uma lista chamada datasets no banco de dados do Redis. Essa fila será usada pela carga de trabalho para localizar o próximo conjunto de dados a ser processado.

  5. Implante o Serviço para tornar o servidor Redis detectável no cluster do GKE.

    kubectl apply -f ./kubernetes-manifests/redis-service.yaml
    

Executar a carga de trabalho em lote

Neste ponto, você preparou o cluster do GKE, a fila de jobs do Redis e o compartilhamento de arquivos. Agora, é possível executar sua carga de trabalho em lote.

Nesta seção, você usará uma imagem de contêiner de uma carga de trabalho de amostra para treinar um modelo de detecção de fraudes usando lotes de dados de transações financeiras. O processo de treinamento pode ser resumido como:

  1. Um cliente Redis reivindica jobs (caminhos de arquivo para conjuntos de dados) na fila e os remove da fila depois de concluído.

  2. Uma classe de gerenciador de treinamento de modelo, FraudDetectionModelTrainer, carrega um novo lote de dados e, opcionalmente, um estado salvo de um modelo de machine learning. O conjunto de dados é usado para refinar o modelo. Esse processo é conhecido como treinamento "inicialização com estado salvo".

  3. O novo estado do modelo e um relatório de detalhes do lote e pontuações de desempenho são salvos no volume NFS do Filestore, que pode ser acessado no cluster do GKE por meio de uma declaração de volume permanente.

Para saber mais, conheça o código-fonte.

Definir o job

O manifesto a seguir descreve a especificação do job em lote para a imagem da carga de trabalho. Esse manifesto usa o recurso Job do Kubernetes.

apiVersion: batch/v1
kind: Job
metadata:
  name: workload
spec:
  parallelism: 1
  template:
    metadata:
      name: workload
    spec:
      nodeSelector:
        cloud.google.com/gke-spot: "true"
      containers:
      - name: workload
        image: "us-docker.pkg.dev/google-samples/containers/gke/batch-ml-workload"
        volumeMounts:
        - mountPath: /mnt/fileserver
          name: workload-pvc
      volumes:
      - name: workload-pvc
        persistentVolumeClaim:
          claimName: fileserver-claim
          readOnly: false
      restartPolicy: OnFailure

Implantar a carga de trabalho

  1. Aplique a especificação do job em lote.

    kubectl apply -f ./kubernetes-manifests/workload.yaml
    
  2. Verifique se o status do pod workload-XXX está concluído.

    watch kubectl get pods
    

    Isso pode levar alguns segundos. Para voltar à linha de comando, pressione Ctrl+C.

    A saída será assim:

    NAME             READY   STATUS      RESTARTS   AGE
    redis-leader     1/1     Running     0          16m
    workload-4p55d   0/1     Completed   0          83s
    
  3. Verifique os registros do job workload:

    kubectl logs job/workload
    

    A saída será assim:

    Worker with sessionID: b50f9459-ce7f-4da8-9f84-0ab5c3233a72
    Initial queue state: empty=False
    Processing dataset: datasets/training/2018-04-04.pkl
    Processing dataset: datasets/training/2018-04-03.pkl
    Processing dataset: datasets/training/2018-04-02.pkl
    Processing dataset: datasets/training/2018-04-01.pkl
    Queue empty, exiting
    

    Os arquivos .pkl são serializações de conjuntos de dados que contêm um lote de transações de cartão de crédito, marcadas como válidas ou fraudulentas. O job workload itera esses arquivos, descompactando os conjuntos de dados e usando-os para treinar o modelo de machine learning, antes de removê-los da fila do Redis. A carga de trabalho continua a processar os dados em lotes, até que a fila do Redis seja esvaziada, antes de sair com sucesso.

Analisar o volume NFS

Durante a operação, a carga de trabalho cria arquivos no volume NFS montado, acessível em todo o cluster a outros jobs em lote ou aplicativos on-line. Para explorar os arquivos no volume NFS, siga estas etapas:

  1. Liste os arquivos criados pela carga de trabalho:

    kubectl exec --stdin --tty redis-leader -- /bin/sh -c "ls -1 /mnt/fileserver/output"
    

    A saída será a seguinte:

    model_cpt_2018-04-01.pkl
    model_cpt_2018-04-02.pkl
    model_cpt_2018-04-03.pkl
    model_cpt_2018-04-04.pkl
    report.txt
    

    Os checkpoints do modelo treinado (nomes de arquivos como model_cpt_XXX.pkl) e um relatório do desempenho do modelo (report.txt) foram criados no diretório /mnt/fileserver/output no volume NFS.

  2. Inspecione o relatório de desempenho do modelo:

    kubectl exec --stdin --tty redis-leader -- /bin/sh -c "cat /mnt/fileserver/output/report.txt"
    

    Veja a seguir um trecho da resposta:

    Report generated on: 2022-02-09 14:19:42.303619
    Training dataset: 2018-04-04.pkl
    Model checkpoint: model_cpt_2018-04-04.pkl
    ---
    Accuracy on training data: 0.9981112277019937
    Accuracy on testing data: 0.9977204434773599
    

    O arquivo contém entradas detalhando o tempo de treinamento, o conjunto de dados usado, a precisão alcançada e o nome do arquivo do checkpoint do modelo associado ao treinamento.

Para saber mais sobre volumes NFS, confira os guias do Filestore.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Para remover os recursos individuais criados para este tutorial:

sh scripts/cleanup.sh

A seguir