Neste tutorial, explicamos como projetar e implantar jobs resilientes do Cloud Run com GPU que podem ser executados por até 12 horas.
Embora o Cloud Run ofereça suporte a tempos limite de tarefas estendidos, ele não oferece um SLA para execução ininterrupta. Como as tarefas com GPU não são migradas em tempo real, a manutenção semanal de rotina as encerra no meio da execução. Consequentemente, qualquer tarefa estendida deve ser interrompida pelo menos uma vez. Para garantir que o job seja concluído sem desperdiçar recursos de computação, projete o aplicativo para criar checkpoints e retomar, em vez de depender de uma única execução ininterrupta.
Neste tutorial, mostramos como implementar o checkpoint, processar sinais da plataforma
SIGTERM e configurar o número máximo de novas tentativas.
Objetivos
Neste tutorial, você vai:
- Prepare um aplicativo Python que implemente pontos de verificação e processe
sinais
SIGTERM. - Crie um bucket do Cloud Storage para manter os checkpoints.
- Crie e implante um job do Cloud Run com GPU ativada, um tempo limite de tarefa de 12 horas e uma política de repetição configurada.
- Execute o job e entenda como monitorar eventos de preempção nos registros.
Custos
Neste documento, você vai usar 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.
Antes de começar
- Faça login na sua conta do Google Cloud . Se você começou a usar o Google Cloudagora, crie uma conta para avaliar o desempenho dos nossos produtos em situações reais. Clientes novos também recebem US $300 em créditos para executar, testar e implantar cargas de trabalho sem custos financeiros.
-
Instale a CLI do Google Cloud.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init -
Crie ou selecione um projeto do Google Cloud .
Papéis necessários para selecionar ou criar um projeto
- Selecionar um projeto: para selecionar um projeto, não é necessário ter um papel do IAM específico. É possível selecionar qualquer projeto em que você tenha um papel.
-
Criar um projeto: para criar um projeto, é preciso ter o papel de criador de projetos
(
roles/resourcemanager.projectCreator), que contém a permissãoresourcemanager.projects.create. Saiba como conceder papéis.
-
Crie um projeto do Google Cloud :
gcloud projects create PROJECT_ID
Substitua
PROJECT_IDpor um nome para o projeto do Google Cloud que você está criando. -
Selecione o projeto do Google Cloud que você criou:
gcloud config set project PROJECT_ID
Substitua
PROJECT_IDpelo nome do projeto do Google Cloud .
-
Verifique se o faturamento está ativado para o projeto do Google Cloud .
-
Instale a CLI do Google Cloud.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init -
Crie ou selecione um projeto do Google Cloud .
Papéis necessários para selecionar ou criar um projeto
- Selecionar um projeto: para selecionar um projeto, não é necessário ter um papel do IAM específico. É possível selecionar qualquer projeto em que você tenha um papel.
-
Criar um projeto: para criar um projeto, é preciso ter o papel de criador de projetos
(
roles/resourcemanager.projectCreator), que contém a permissãoresourcemanager.projects.create. Saiba como conceder papéis.
-
Crie um projeto do Google Cloud :
gcloud projects create PROJECT_ID
Substitua
PROJECT_IDpor um nome para o projeto do Google Cloud que você está criando. -
Selecione o projeto do Google Cloud que você criou:
gcloud config set project PROJECT_ID
Substitua
PROJECT_IDpelo nome do projeto do Google Cloud .
-
Verifique se o faturamento está ativado para o projeto do Google Cloud .
Ative as APIs Cloud Run, Artifact Registry, Cloud Build e Cloud Storage, se ainda não estiverem ativadas:
Funções necessárias para ativar APIs
Para ativar APIs, você precisa da permissão
serviceusage.services.enable. Se você criou o projeto, provavelmente já tem essa permissão por meio do papel de proprietário (roles/owner). Caso contrário, é possível conseguir essa permissão por meio do papel de administrador do Service Usage (roles/serviceusage.serviceUsageAdmin). Saiba como conceder papéis.gcloud services enable run.googleapis.com
cloudbuild.googleapis.com artifactregistry.googleapis.com storage.googleapis.com - Defina sua região como uma variável de ambiente:
export REGION=REGION
- Crie uma conta de serviço para o job:
gcloud iam service-accounts create gpu-job-sa
- Verifique se você tem [cota de GPU suficiente](/run/docs/configuring/jobs/gpu#request-quota) (por exemplo, Nvidia L4) na região escolhida.
Preparar o aplicativo
Para tornar um job de longa duração resiliente, seu aplicativo precisa:
Salve periodicamente o progresso (checkpointing) em um local permanente, como um bucket do Cloud Storage montado.
Você tem aproximadamente 10 segundos após
SIGTERMantes que a tarefa seja encerrada. Esse tempo não é suficiente para gravar um checkpoint de modelo grande. Trate o gerenciadorSIGTERMcomo uma limpeza de melhor esforço apenas de estado pequeno e use o checkpoint periódico como sua proteção principal. Escolha o intervalo de checkpoint com base na quantidade de trabalho que você pode perder, lembrando que checkpoints mais frequentes significam mais tempo sem realizar trabalho útil. O objetivo é alcançar o equilíbrio certo para seu caso de uso.Restaura o estado do último checkpoint na inicialização.
Detecte o sinal
SIGTERM, que o Cloud Run envia 10 segundos antes do processo de manutenção, e tente salvar um checkpoint final antes de sair.
O exemplo abaixo ilustra como implementar esses recursos.
Criar o código do aplicativo
Crie um diretório para o projeto:
mkdir gc-run-gpu-resilience cd gc-run-gpu-resilienceCrie um arquivo chamado
task.pye cole o script a seguir para simular um processo de treinamento ou processamento em lote que ofereça suporte a checkpoints e processamento de sinais:import os import sys import time import signal # The checkpoint directory will be mounted to this path CHECKPOINT_DIR = "/checkpoints" # Cloud Run sets these variables automatically JOB_NAME = os.environ.get("CLOUD_RUN_JOB", "local-job") TASK_INDEX = os.environ.get("CLOUD_RUN_TASK_INDEX", "0") CHECKPOINT_FILE = os.path.join( CHECKPOINT_DIR, f"{JOB_NAME}-task-{TASK_INDEX}-checkpoint.txt") TOTAL_STEPS = 100 current_step = 0 is_exiting = False def save_checkpoint(step): print(f"Saving checkpoint at step {step} to {CHECKPOINT_FILE}...") try: # Write to a temp file and rename to ensure atomicity temp_file = CHECKPOINT_FILE + ".tmp" with open(temp_file, "w") as f: f.write(str(step)) os.rename(temp_file, CHECKPOINT_FILE) print("Checkpoint saved successfully.") except Exception as e: print(f"Failed to save checkpoint: {e}") def load_checkpoint(): print(f"Looking for a checkpoint at {CHECKPOINT_FILE}...") global current_step if os.path.exists(CHECKPOINT_FILE): try: with open(CHECKPOINT_FILE, "r") as f: current_step = int(f.read().strip()) print(f"Resuming from checkpointed step {current_step}.") except Exception as e: print(f"Failed to load checkpoint: {e}. Starting from scratch.") else: print("No checkpoint found. Starting from scratch.") def sigterm_handler(signum, frame): global is_exiting print("Received SIGTERM signal from platform. Initiating graceful shutdown...") is_exiting = True # Register the signal handler for SIGTERM signal.signal(signal.SIGTERM, sigterm_handler) # Load existing checkpoint if any to resume work load_checkpoint() # Simulate work loop while current_step < TOTAL_STEPS and not is_exiting: print(f"Processing step {current_step}/{TOTAL_STEPS}...") # Simulate heavy GPU computation time.sleep(1) current_step += 1 # Periodically save checkpoint (e.g., every 5 steps) if current_step % 5 == 0: save_checkpoint(current_step) if is_exiting: # Save final state before exiting due to preemption # Best-effort only: with ~10s before SIGKILL this will not complete for # large state. Periodic checkpointing (above) is what actually protects # you. save_checkpoint(current_step) # Note that save_checkpoint already writes-then-renames for atomicity, # which is good, but the reason it matters here is that a truncated # checkpoint from an interrupted final save must not clobber the last # good one. print("Graceful shutdown complete. Exiting with error code to trigger retry.") # Exit with a non-zero code to signal to Cloud Run that the task # was interrupted and needs to be retried from the checkpoint. sys.exit(143) # Note that this statement deliberately consumes of the configured retry # attempts. print("Task completed successfully.") sys.exit(0)Crie um
Dockerfilepara colocar o aplicativo em um contêiner:
Confira este exemplo para uma implementação mais detalhada e realista.
Criar um bucket do Cloud Storage para checkpoints
Crie um bucket do Cloud Storage para armazenar os arquivos de checkpoint e conceda à conta de serviço do job permissão para acessá-lo.
Crie o bucket:
gcloud storage buckets create gs://gpu-checkpoints-PROJECT_ID \ --location REGIONConceda o papel de Administrador de objetos do Storage à conta de serviço do job:
gcloud storage buckets add-iam-policy-binding gs://gpu-checkpoints-PROJECT_ID \ --member="serviceAccount:gpu-job-sa@PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin"
Implantar o job
Implante o job no Cloud Run:
gcloud beta run jobs deploy gpu-resilient-job \
--source=. \
--region REGION \
--gpu 1 \
--gpu-type nvidia-l4 \
--no-gpu-zonal-redundancy \
--task-timeout 168h \
--max-retries 3 \
--service-account gpu-job-sa@PROJECT_ID.iam.gserviceaccount.com \
--add-volume=name=checkpoint-volume,type=cloud-storage,bucket=gpu-checkpoints-PROJECT_ID \
--add-volume-mount=volume=checkpoint-volume,mount-path=/checkpoints
Observe as seguintes flags críticas:
--task-timeout 168h: permite que a tarefa seja executada por até 12 horas.--max-retries 3: para jobs de GPU com um tempo limite maior que 1 hora, recomendamos definir a configuração padrão de 3 novas tentativas. Para evitar falhas silenciosas durante a manutenção da plataforma, recomendamos não definir 0 tentativas. Por fim, recomendamos que você inclua no orçamento pelo menos uma nova tentativa para falhas relacionadas à manutenção, além de novas tentativas para falhas de aplicativos em um período de execução de 12 horas.--add-volumee--add-volume-mount: monta o bucket do Cloud Storage em/checkpointspara que o aplicativo possa persistir o estado entre as novas tentativas de tarefa.
Executar e monitorar o job
Execute o job:
gcloud run jobs execute gpu-resilient-job --region REGIONEsse comando retorna uma mensagem semelhante a esta:
Execution [gpu-resilient-job-abcde] has been successfully started. View details about this execution by running `gcloud run jobs executions describe gpu-resilient-job-abcde`. See logs for this execution at: https://console.cloud.google.com/logs/viewer?project=YOUR_PROJECT_ID&resource=cloud_run_job/job_name/my-job/location/my-region/execution_id/gpu-resilient-job-abcdeA string
gpu-resilient-job-abcdeé o ID exclusivo gerado automaticamente para essa tentativa de execução específica. Você pode usá-lo para monitorar ou cancelar essa execução específica. A saída também inclui um link direto para a página da Análise de registros no console do Google Cloud para visualizar a saída ou os erros das tarefas do job.Monitorar os registros. Se um evento de manutenção ocorrer, o Cloud Run vai registrar um aviso. Você verá o seguinte:
- Os registros do aplicativo:
Received SIGTERM signal from platform. Initiating graceful shutdown...seguido porSaving checkpoint.... - Um registro do sistema indicando preempção:
Container instance preemption initiated by the platform due to underlying hardware maintenance.com o motivoINSTANCE_PREEMPTED. - O Cloud Run reinicia a tarefa automaticamente.
- Os registros do aplicativo após a reinicialização:
Resuming from checkpointed step X..
- Os registros do aplicativo:
Limpar
Para evitar cobranças extras na sua conta do Google Cloud , exclua todos os recursos implantados com este guia de início rápido.
Excluir o repositório
O Cloud Run cobra apenas pelo tempo de execução do job. No entanto, é possível que você ainda receba cobranças pelo armazenamento da imagem do contêiner no Artifact Registry. Para excluir repositórios do Artifact Registry, siga as etapas em Excluir repositórios na documentação do Artifact Registry.
Excluir sua vaga
Os jobs do Cloud Run só geram custos quando uma tarefa de job está em execução. Para excluir o job do Cloud Run, siga uma destas etapas:
Console
Para excluir um job, siga estas etapas:
No console do Google Cloud , acesse o Cloud Run:
Localize o job que você quer excluir na lista de jobs e clique na caixa de seleção para marcá-lo.
Clique em Excluir. Isso encerra todas as execuções de jobs em andamento e todas as instâncias de contêiner em execução.
gcloud
Para excluir um job, execute o seguinte comando:
gcloud run jobs delete JOB_NAME
Substitua JOB_NAME pelo nome do job.
Excluir o projeto de teste
A exclusão do projeto do Google Cloud interrompe o faturamento de todos os recursos nele. Para liberar todos os recursos do Google Cloud no seu projeto, siga estas etapas:
Exclua um projeto do Google Cloud :
gcloud projects delete PROJECT_ID
Exclua o bucket do Cloud Storage:
gcloud storage buckets delete gs://gpu-checkpoints-PROJECT_ID
A seguir
- Saiba mais sobre novas tentativas de jobs e checkpoints.
- Confira as práticas recomendadas de desempenho da GPU.