Visão geral
Neste guia, mostramos como disponibilizar modelos de linguagem grandes (LLMs) de última geração, como DeepSeek-R1 671B ou Llama 3.1 405B no Google Distributed Cloud (somente software) em bare metal usando unidades de processamento gráfico (GPUs) em vários nós.
Este guia demonstra como usar tecnologias portáteis de código aberto (Kubernetes, vLLM e a API LeaderWorkerSet [LWS]) para implantar e disponibilizar cargas de trabalho de IA/ML em clusters bare metal. O Google Distributed Cloud estende o GKE para uso em um ambiente local, ao mesmo tempo em que oferece as vantagens do controle granular, da escalonabilidade, da capacidade de recuperação, da portabilidade e da economia do GKE.
Contexto
Esta seção descreve as principais tecnologias usadas neste guia, incluindo os dois LLMs usados como exemplos: DeepSeek-R1 e Llama 3.1 405B.
DeepSeek-R1
O DeepSeek-R1, um modelo de linguagem grande de 671 bilhões de parâmetros da DeepSeek, foi projetado para inferência lógica, raciocínio matemático e resolução de problemas em tempo real em várias tarefas baseadas em texto. O Google Distributed Cloud lida com as demandas computacionais do DeepSeek-R1, oferecendo suporte aos recursos dele com recursos escalonáveis, computação distribuída e rede eficiente.
Para saber mais, consulte a documentação do DeepSeek.
Llama 3.1 405B
O Llama 3.1 405B é um modelo de linguagem grande da Meta projetado para uma ampla variedade de tarefas de processamento de linguagem natural, incluindo geração de texto, tradução e resposta a perguntas. O Google Distributed Cloud oferece a infraestrutura robusta necessária para atender às necessidades de treinamento e veiculação distribuídos de modelos dessa escala.
Para saber mais, consulte a documentação do Llama.
Serviço gerenciado do Kubernetes do Google Distributed Cloud
O Google Distributed Cloud oferece uma ampla variedade de serviços, incluindo o Google Distributed Cloud (somente software) para bare metal, que é adequado para implantar e gerenciar cargas de trabalho de IA/ML no seu próprio data center. O Google Distributed Cloud é um serviço gerenciado do Kubernetes que simplifica a implantação, o escalonamento e o gerenciamento de aplicativos conteinerizados. O Google Distributed Cloud oferece a infraestrutura necessária, incluindo recursos escalonáveis, computação distribuída e rede eficiente, para lidar com as demandas computacionais dos LLMs.
Para saber mais sobre os principais conceitos do Kubernetes, consulte Começar a aprender sobre o Kubernetes. Para saber mais sobre o Google Distributed Cloud e como ele ajuda você a escalonar, automatizar e gerenciar o Kubernetes, consulte a Visão geral do Google Distributed Cloud (somente software) em bare metal.
GPUs
As unidades de processamento gráfico (GPUs) permitem acelerar cargas de trabalho específicas, como machine learning e tratamento de dados. O Google Distributed Cloud oferece suporte a nós equipados com essas GPUs potentes, permitindo que você configure seu cluster para ter desempenho ideal em tarefas de machine learning e processamento de dados. O Google Distributed Cloud oferece uma variedade de opções de tipo de máquina para configuração de nós, incluindo tipos de máquinas com GPUs NVIDIA H100, L4 e A100.
Para saber mais, consulte Configurar e usar GPUs NVIDIA.
LeaderWorkerSet (LWS)
O LeaderWorkerSet (LWS) é uma API de implantação do Kubernetes que aborda padrões de implantação comuns de cargas de trabalho de inferência multinó de IA/ML. O serviço de vários nós usa vários pods, cada um potencialmente executado em um nó diferente, para processar a carga de trabalho de inferência distribuída. Ele permite lidar com vários pods como um grupo, simplificando o gerenciamento da disponibilização de modelos distribuídos.
vLLM e veiculação de vários hosts
Ao veicular LLMs com uso intensivo de computação, recomendamos usar o vLLM e executar as cargas de trabalho em GPUs.
O vLLM é um framework de exibição de LLM de código aberto altamente otimizado que pode aumentar a capacidade de exibição em GPUs, com recursos como:
Otimização da implementação do transformador com PagedAttention
Lotes contínuos para melhorar a capacidade geral de exibição
Exibição distribuída em várias GPUs
Com LLMs especialmente intensivos em computação que não cabem em um único nó de GPU, é possível usar vários nós de GPU para disponibilizar o modelo. O vLLM é compatível com a execução de cargas de trabalho em GPUs com duas estratégias:
O paralelismo de tensor divide as multiplicações de matriz na camada do transformador em várias GPUs. No entanto, essa estratégia exige uma rede rápida devido à comunicação necessária entre as GPUs, o que a torna menos adequada para a execução de cargas de trabalho em nós.
O paralelismo de pipeline divide o modelo por camada ou verticalmente. Essa estratégia não exige comunicação constante entre as GPUs, o que a torna uma opção melhor para a execução de modelos em vários nós.
Você pode usar as duas estratégias na disponibilização multinó. Por exemplo, ao usar dois nós com oito GPUs H100 cada, é possível usar as duas estratégias:
Paralelismo de pipeline bidirecional para dividir o modelo entre os dois nós
Paralelismo de tensor de oito vias para dividir o modelo entre as oito GPUs em cada nó
Para saber mais, consulte a documentação do vLLM.
Objetivos
Prepare seu ambiente com um cluster do Google Distributed Cloud no modo Autopilot ou Standard.
Implantar o vLLM em vários nós no cluster.
Use o vLLM para disponibilizar o modelo por meio de
curl
.
Antes de começar
- Verifique se você tem um cluster bare metal funcionando com pelo menos um pool de nós de trabalho que tenha dois nós de trabalho, cada um configurado com oito GPUs NVIDIA H100 de 80 GB.
- Crie uma conta do Hugging Face caso ainda não tenha uma.
Receber acesso ao modelo
Você pode usar os modelos Llama 3.1 405B ou DeepSeek-R1.
DeepSeek-R1
Gerar um token de acesso
Gere um token do Hugging Face, se você ainda não tiver um:
Clique em Seu perfil > Configurações > Tokens de acesso.
Selecione Novo token.
Especifique um Nome de sua escolha e um Papel de pelo menos
Read
.Selecione Gerar um token.
Llama 3.1 405B
Gerar um token de acesso
Gere um token do Hugging Face, se você ainda não tiver um:
Clique em Seu perfil > Configurações > Tokens de acesso.
Selecione Novo token.
Especifique um Nome de sua escolha e um Papel de pelo menos
Read
.Selecione Gerar um token.
Prepare o ambiente
Para configurar o ambiente, siga estas etapas:
Defina os seguintes parâmetros na estação de trabalho do administrador:
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export HF_TOKEN=HUGGING_FACE_TOKEN export IMAGE_NAME= gcr.io/PROJECT_ID/vllm-multihost/vllm-multihost:latest
Substitua os seguintes valores:
PROJECT_ID
: o ID do projeto associado ao seu cluster.HUGGING_FACE_TOKEN
: o token do Hugging Face gerado na seção anterior Acessar o modelo.
Criar um Secret do Kubernetes para as credenciais do Hugging Face
Crie um secret do Kubernetes que contenha o token do Hugging Face usando o seguinte comando:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
Substitua KUBECONFIG
pelo caminho do arquivo kubeconfig do cluster em que você pretende hospedar o LLM.
Criar sua própria imagem de vários nós do vLLM
Para facilitar a comunicação entre nós para vLLM, use o Ray. O repositório LeaderWorkerSet fornece um Dockerfile, que inclui um script bash para configurar o Ray com o vLLM.
Para criar sua própria imagem vLLM de vários nós, você precisa clonar o repositório LeaderWorkerSet, criar uma imagem Docker usando o Dockerfile fornecido (que configura o Ray para comunicação entre nós) e enviar essa imagem para o Artifact Registry para implantação no Google Distributed Cloud.
Crie o contêiner
Para criar o contêiner, siga estas etapas:
Clone o repositório LeaderWorkerSet:
git clone https://github.com/kubernetes-sigs/lws.git
Crie a imagem.
cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile.GPU . -t vllm-multihost
Envie a imagem para o Artifact Registry
Para garantir que sua implantação do Kubernetes possa acessar a imagem, armazene-a no Artifact Registry dentro do projeto Google Cloud :
docker image tag vllm-multihost ${IMAGE_NAME}
docker push ${IMAGE_NAME}
Instalar o LeaderWorkerSet
Para instalar o LWS, execute este comando:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
Valide se o controlador LeaderWorkerSet está em execução no namespace lws-system
usando o seguinte comando:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
O resultado será assim:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
Implantar o servidor de modelos do vLLM
Para implantar o servidor de modelos vLLM, siga estas etapas:
Crie e aplique o manifesto, dependendo do LLM que você quer implantar.
DeepSeek-R1
Crie um manifesto YAML,
vllm-deepseek-r1-A3.yaml
, para o servidor de modelos do vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model deepseek-ai/DeepSeek-R1 --tensor-parallel-size 8 --pipeline-parallel-size 2 --trust-remote-code --max-model-len 4096" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Execute este comando para aplicar o manifesto:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
Crie um manifesto YAML,
vllm-llama3-405b-A3.yaml
, para o servidor de modelos do vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model meta-llama/Meta-Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Execute este comando para aplicar o manifesto:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
Confira os registros do servidor de modelos em execução com o seguinte comando:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIG
A saída será parecida com esta:
INFO 08-09 21:01:34 api_server.py:297] Route: /detokenize, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/models, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /version, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /v1/chat/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/embeddings, Methods: POST INFO: Started server process [7428] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
Disponibilizar o modelo
Configure o encaminhamento de portas para o modelo executando o seguinte comando:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
Interagir com o modelo usando curl
Para interagir com o modelo usando curl, siga estas instruções:
DeepSeek-R1
Em um novo terminal, envie uma solicitação ao servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-R1",
"prompt": "I have four boxes. I put the red box on the bottom and put the blue box on top. Then I put the yellow box on top the blue. Then I take the blue box out and put it on top. And finally I put the green box on the top. Give me the final order of the boxes from bottom to top. Show your reasoning but be brief",
"max_tokens": 1024,
"temperature": 0
}'
A saída será semelhante a esta:
{
"id": "cmpl-f2222b5589d947419f59f6e9fe24c5bd",
"object": "text_completion",
"created": 1738269669,
"model": "deepseek-ai/DeepSeek-R1",
"choices": [
{
"index": 0,
"text": ".\n\nOkay, let's see. The user has four boxes and is moving them around. Let me try to visualize each step. \n\nFirst, the red box is placed on the bottom. So the stack starts with red. Then the blue box is put on top of red. Now the order is red (bottom), blue. Next, the yellow box is added on top of blue. So now it's red, blue, yellow. \n\nThen the user takes the blue box out. Wait, blue is in the middle. If they remove blue, the stack would be red and yellow. But where do they put the blue box? The instruction says to put it on top. So after removing blue, the stack is red, yellow. Then blue is placed on top, making it red, yellow, blue. \n\nFinally, the green box is added on the top. So the final order should be red (bottom), yellow, blue, green. Let me double-check each step to make sure I didn't mix up any steps. Starting with red, then blue, then yellow. Remove blue from the middle, so yellow is now on top of red. Then place blue on top of that, so red, yellow, blue. Then green on top. Yes, that seems right. The key step is removing the blue box from the middle, which leaves yellow on red, then blue goes back on top, followed by green. So the final order from bottom to top is red, yellow, blue, green.\n\n**Final Answer**\nThe final order from bottom to top is \\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}.\n</think>\n\n1. Start with the red box at the bottom.\n2. Place the blue box on top of the red box. Order: red (bottom), blue.\n3. Place the yellow box on top of the blue box. Order: red, blue, yellow.\n4. Remove the blue box (from the middle) and place it on top. Order: red, yellow, blue.\n5. Place the green box on top. Final order: red, yellow, blue, green.\n\n\\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 76,
"total_tokens": 544,
"completion_tokens": 468,
"prompt_tokens_details": null
}
}
Llama 3.1 405B
Em um novo terminal, envie uma solicitação ao servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3.1-405B-Instruct",
"prompt": "San Francisco is a",
"max_tokens": 7,
"temperature": 0
}'
A saída será semelhante a esta:
{"id":"cmpl-0a2310f30ac3454aa7f2c5bb6a292e6c",
"object":"text_completion","created":1723238375,"model":"meta-llama/Meta-Llama-3.1-405B-Instruct","choices":[{"index":0,"text":" top destination for foodies, with","logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":5,"total_tokens":12,"completion_tokens":7}}
A seguir
- Saiba mais sobre GPUs no Google Distributed Cloud.
- Conheça o repositório do GitHub e a documentação do vLLM.
- Conheça o repositório do GitHub para LWS.