Execute a inferência de MDIs/CEs em GPUs do Cloud Run com o Gemma 3 e o Ollama

Configure o gcloud

Para configurar a CLI gcloud para o seu serviço do Cloud Run:

  1. Defina o projeto predefinido:

    gcloud config set project PROJECT_ID

    Clique no ícone para substituir a variável PROJECT_ID pelo nome do projeto que criou para este tutorial. Isto garante que todas as fichas nesta página que fazem referência a PROJECT_ID já têm o valor correto preenchido.

  2. Configure a CLI gcloud para usar a região europe-west1 para comandos do Cloud Run.

    gcloud config set run/region europe-west1

Use o Docker para criar uma imagem de contentor com o Ollama e o Gemma

  1. Crie um diretório para o serviço Ollama e altere o diretório de trabalho para este novo diretório:

    mkdir ollama-backend
    cd ollama-backend
  2. Crie um ficheiro Dockerfile com o seguinte conteúdo:

    FROM ollama/ollama:latest
    
    # Listen on all interfaces, port 8080
    ENV OLLAMA_HOST 0.0.0.0:8080
    
    # Store model weight files in /models
    ENV OLLAMA_MODELS /models
    
    # Reduce logging verbosity
    ENV OLLAMA_DEBUG false
    
    # Never unload model weights from the GPU
    ENV OLLAMA_KEEP_ALIVE -1
    
    # Store the model weights in the container image
    ENV MODEL gemma3:4b
    RUN ollama serve & sleep 5 && ollama pull $MODEL
    
    # Start Ollama
    ENTRYPOINT ["ollama", "serve"]
    

Armazene os pesos do modelo na imagem do contentor para iniciar as instâncias mais rapidamente

A Google recomenda armazenar os pesos do modelo para o Gemma 3 (4B) e modelos de tamanho semelhante diretamente na imagem do contentor.

Os pesos do modelo são os parâmetros numéricos que definem o comportamento de um MDG. O Ollama tem de ler totalmente estes ficheiros e carregar os pesos na memória da GPU (VRAM) durante o arranque da instância do contentor, antes de poder começar a publicar pedidos de inferência.

No Cloud Run, um arranque rápido da instância de contentor é importante para minimizar a latência dos pedidos. Se a instância do contentor tiver um tempo de arranque lento, o serviço demora mais tempo a dimensionar de zero para uma instância e precisa de mais tempo para dimensionar durante um pico de tráfego.

Para garantir um arranque rápido, armazene os ficheiros do modelo na própria imagem do contentor. Este processo é mais rápido e fiável do que transferir os ficheiros de uma localização remota durante o arranque. O armazenamento interno de imagens de contentores do Cloud Run está otimizado para processar picos de tráfego, o que lhe permite configurar rapidamente o sistema de ficheiros do contentor quando uma instância é iniciada.

Tenha em atenção que os pesos do modelo Gemma 3 (4B) ocupam 8 GB de armazenamento. Os modelos maiores têm ficheiros de peso do modelo maiores, e estes podem ser impraticáveis de armazenar na imagem do contentor. Consulte o artigo Práticas recomendadas: inferência de IA no Cloud Run com GPUs para ver uma vista geral das concessões.

Crie e implemente o serviço do Cloud Run

Crie e implemente o serviço no Cloud Run:

gcloud run deploy ollama-gemma \
  --source . \
  --concurrency 4 \
  --cpu 8 \
  --set-env-vars OLLAMA_NUM_PARALLEL=4 \
  --gpu 1 \
  --gpu-type nvidia-l4 \
  --max-instances 1 \
  --memory 32Gi \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --no-gpu-zonal-redundancy \
  --timeout=600

Tenha em atenção as seguintes flags importantes neste comando:

  • --concurrency 4 está definido para corresponder ao valor da variável de ambiente OLLAMA_NUM_PARALLEL.
  • --gpu 1 com --gpu-type nvidia-l4 atribui 1 GPU NVIDIA L4 a cada instância do Cloud Run no serviço.
  • --max-instances 1 especifica o número máximo de instâncias para dimensionar. Tem de ser igual ou inferior à quota de GPU NVIDIA L4 (Total Nvidia L4 GPU allocation, per project per region) do seu projeto.
  • --no-allow-unauthenticated restringe o acesso não autenticado ao serviço. Ao manter o serviço privado, pode confiar na autenticação da gestão de identidade e de acesso (IAM) incorporada do Cloud Run para a comunicação entre serviços. Consulte o artigo Gerir o acesso através do IAM.
  • O --no-cpu-throttling é necessário para ativar a GPU.
  • --no-gpu-zonal-redundancy Defina opções de redundância zonal consoante os seus requisitos de comutação por falha zonal e a quota disponível. Consulte as opções de redundância zonal da GPU para ver detalhes.

Definir a simultaneidade para um desempenho ideal

Esta secção fornece contexto sobre as definições de concorrência recomendadas. Para uma latência de pedido ótima, certifique-se de que a definição --concurrency é igual à variável de ambiente OLLAMA_NUM_PARALLEL do Ollama.

  • OLLAMA_NUM_PARALLEL determina quantos espaços de pedidos estão disponíveis por modelo para processar pedidos de inferência em simultâneo.
  • --concurrency determina quantos pedidos o Cloud Run envia a uma instância do Ollama em simultâneo.

Se --concurrency exceder OLLAMA_NUM_PARALLEL, o Cloud Run pode enviar mais pedidos a um modelo no Ollama do que tem espaços de pedidos disponíveis. Isto leva à colocação em fila de pedidos no Ollama, o que aumenta a latência dos pedidos em fila. Também leva a um dimensionamento automático menos reativo, uma vez que os pedidos em fila não acionam o Cloud Run para aumentar a escala e iniciar novas instâncias.

O Ollama também suporta a publicação de vários modelos a partir de uma GPU. Para evitar completamente a colocação em fila de pedidos na instância do Ollama, deve continuar a definir --concurrency de modo a corresponder a OLLAMA_NUM_PARALLEL.

É importante ter em atenção que o aumento de OLLAMA_NUM_PARALLEL também faz com que os pedidos paralelos demorem mais tempo.

Otimizar a utilização

Para uma utilização da GPU ideal, aumente o valor de --concurrency, mantendo-o dentro do dobro do valor de OLLAMA_NUM_PARALLEL. Embora isto leve a uma fila de pedidos no Ollama, pode ajudar a melhorar a utilização: as instâncias do Ollama podem processar imediatamente pedidos da respetiva fila, e as filas ajudam a absorver picos de tráfego.

Teste o serviço Ollama implementado com o curl

Agora que implementou o serviço Ollama, pode enviar-lhe pedidos. No entanto, se enviar um pedido diretamente, o Cloud Run responde com HTTP 401 Unauthorized. Isto é intencional, porque uma API de inferência de MDG destina-se a ser chamada por outros serviços, como uma aplicação de interface. Para mais informações sobre a autenticação de serviço a serviço no Cloud Run, consulte o artigo Autenticação de serviço a serviço.

Para enviar pedidos ao serviço Ollama, adicione um cabeçalho com um token OIDC válido aos pedidos, por exemplo, através do proxy do programador do Cloud Run:

  1. Inicie o proxy e, quando lhe for pedido para instalar o componente cloud-run-proxy, escolha Y:

    gcloud run services proxy ollama-gemma --port=9090
  2. Envie-lhe um pedido num separador do terminal separado, deixando o proxy em execução. Tenha em atenção que o proxy é executado em localhost:9090:

    curl http://localhost:9090/api/generate -d '{
      "model": "gemma3:4b",
      "prompt": "Why is the sky blue?"
    }'

    Este comando deve fornecer uma saída de streaming semelhante a esta:

    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.641492408Z","response":"That","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.687529153Z","response":"'","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.753284927Z","response":"s","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.812957381Z","response":" a","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.889102649Z","response":" fantastic","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.925748116Z","response":",","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.958391572Z","response":" decept","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.971035028Z","response":"ively","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.989678484Z","response":" tricky","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.999321940Z","response":" question","done":false}
    ...