Panoramica
Questa guida mostra come pubblicare modelli linguistici di grandi dimensioni (LLM) all'avanguardia, come DeepSeek-R1 671B o Llama 3.1 405B su Google Distributed Cloud (solo software) su bare metal utilizzando unità di elaborazione grafica (GPU) su più nodi.
Questa guida mostra come utilizzare tecnologie open source portatili, ovvero Kubernetes, vLLM e l'API LeaderWorkerSet (LWS), per eseguire il deployment e gestire i carichi di lavoro AI/ML su cluster bare metal. Google Distributed Cloud estende GKE per l'utilizzo in un ambiente on-premise, fornendo al contempo i vantaggi del controllo granulare, della scalabilità, della resilienza, della portabilità e della convenienza economica di GKE.
Sfondo
Questa sezione descrive le tecnologie chiave utilizzate in questa guida, tra cui i due LLM utilizzati come esempi in questa guida: DeepSeek-R1 e Llama 3.1 405B.
DeepSeek-R1
DeepSeek-R1, un modello linguistico di grandi dimensioni con 671 miliardi di parametri di DeepSeek, è progettato per l'inferenza logica, il ragionamento matematico e la risoluzione di problemi in tempo reale in varie attività basate su testo. Google Distributed Cloud gestisce le esigenze di calcolo di DeepSeek-R1, supportandone le funzionalità con risorse scalabili, computing distribuito e networking efficiente.
Per saperne di più, consulta la documentazione di DeepSeek.
Llama 3.1 405B
Llama 3.1 405B è un modello linguistico di grandi dimensioni di Meta progettato per un'ampia gamma di attività di elaborazione del linguaggio naturale, tra cui generazione di testi, traduzione e risposta a domande. Google Distributed Cloud offre l'infrastruttura solida necessaria per supportare le esigenze di addestramento e serving distribuito di modelli di questa scala.
Per saperne di più, consulta la documentazione di Llama.
Servizio Kubernetes gestito Google Distributed Cloud
Google Distributed Cloud offre un'ampia gamma di servizi, tra cui Google Distributed Cloud (solo software) per bare metal, ideale per il deployment e la gestione dei carichi di lavoro di AI/ML nel tuo data center. Google Distributed Cloud è un servizio Kubernetes gestito che semplifica il deployment, lo scaling e la gestione delle applicazioni containerizzate. Google Distributed Cloud fornisce l'infrastruttura necessaria, tra cui risorse scalabili, computing distribuito e networking efficiente, per gestire le esigenze di calcolo degli LLM.
Per saperne di più sui concetti chiave di Kubernetes, consulta Inizia a scoprire Kubernetes. Per scoprire di più su Google Distributed Cloud e su come ti aiuta a scalare, automatizzare e gestire Kubernetes, consulta la panoramica di Google Distributed Cloud (solo software) per bare metal.
GPU
Le GPU (Graphics Processing Unit) ti consentono di accelerare carichi di lavoro specifici, come machine learning ed elaborazione di dati. Google Distributed Cloud supporta i nodi dotati di queste potenti GPU, consentendoti di configurare il cluster per prestazioni ottimali nelle attività di machine learning ed elaborazione dei dati. Google Distributed Cloud offre una gamma di opzioni di tipo di macchina per la configurazione dei nodi, inclusi tipi di macchine con GPU NVIDIA H100, L4 e A100.
Per saperne di più, consulta Configurare e utilizzare le GPU NVIDIA.
LeaderWorkerSet (LWS)
LeaderWorkerSet (LWS) è un'API di deployment Kubernetes che gestisce i pattern di deployment comuni dei carichi di lavoro di inferenza AI/ML multimodali. Il servizio multi-nodo utilizza più pod, ognuno dei quali potenzialmente in esecuzione su un nodo diverso, per gestire il carico di lavoro di inferenza distribuita. LWS consente di trattare più pod come un gruppo, semplificando la gestione della pubblicazione di modelli distribuiti.
vLLM e servizio multi-host
Quando vengono pubblicati LLM ad alta intensità di calcolo, consigliamo di utilizzare vLLM ed eseguire i carichi di lavoro sulle GPU.
vLLM è un framework di gestione degli LLM open source altamente ottimizzato che può aumentare la velocità effettiva di gestione sulle GPU, con funzionalità come le seguenti:
Implementazione ottimizzata di Transformer con PagedAttention
Batch continuo per migliorare la velocità effettiva complessiva della pubblicazione
Pubblicazione distribuita su più GPU
Con LLM particolarmente intensivi dal punto di vista computazionale che non possono essere contenuti in un singolo nodo GPU, puoi utilizzare più nodi GPU per gestire il modello. vLLM supporta l'esecuzione di carichi di lavoro su più GPU con due strategie:
Il parallelismo tensoriale suddivide le moltiplicazioni di matrici nel livello Transformer tra più GPU. Tuttavia, questa strategia richiede una rete veloce a causa della comunicazione necessaria tra le GPU, il che la rende meno adatta per l'esecuzione di workload tra i nodi.
Il parallelismo della pipeline suddivide il modello per livello o in verticale. Questa strategia non richiede una comunicazione costante tra le GPU, il che la rende un'opzione migliore quando si eseguono modelli su più nodi.
Puoi utilizzare entrambe le strategie nel servizio multimodello. Ad esempio, quando utilizzi due nodi con otto GPU H100 ciascuno, puoi utilizzare entrambe le strategie:
Parallelismo della pipeline bidirezionale per partizionare il modello tra i due nodi
Parallelismo dei tensori a otto vie per suddividere il modello tra le otto GPU di ogni nodo
Per saperne di più, consulta la documentazione di vLLM.
Obiettivi
Prepara l'ambiente con un cluster Google Distributed Cloud in modalità Autopilot o Standard.
Esegui il deployment di vLLM su più nodi del cluster.
Utilizza vLLM per pubblicare il modello tramite
curl
.
Prima di iniziare
- Assicurati di avere un cluster bare metal funzionante con almeno un pool di nodi worker che abbia due nodi worker, ciascuno configurato con otto GPU NVIDIA H100 da 80 GB.
- Crea un account Hugging Face, se non ne hai già uno.
Ottenere l'accesso al modello
Puoi utilizzare i modelli Llama 3.1 405B o DeepSeek-R1.
DeepSeek-R1
Generare un token di accesso
Se non ne hai già uno, genera un nuovo token Hugging Face:
Fai clic su Il tuo profilo > Impostazioni > Token di accesso.
Seleziona Nuovo token.
Specifica un nome a tua scelta e un ruolo di almeno
Read
.Seleziona Genera un token.
Llama 3.1 405B
devi firmare il contratto di consenso.Generare un token di accesso
Se non ne hai già uno, genera un nuovo token Hugging Face:
Fai clic su Il tuo profilo > Impostazioni > Token di accesso.
Seleziona Nuovo token.
Specifica un nome a tua scelta e un ruolo di almeno
Read
.Seleziona Genera un token.
Prepara l'ambiente
Per configurare l'ambiente:
Imposta i seguenti parametri sulla workstation di amministrazione:
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
Sostituisci i seguenti valori:
PROJECT_ID
: l'ID progetto associato al tuo cluster.HUGGING_FACE_TOKEN
: il token Hugging Face generato dalla sezione precedente Ottieni l'accesso al modello.
Crea un secret di Kubernetes per le credenziali di Hugging Face
Crea un secret Kubernetes che contenga il token Hugging Face utilizzando il seguente comando:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
Sostituisci KUBECONFIG
con il percorso del file kubeconfig per
il cluster su cui intendi ospitare l'LLM.
Crea la tua immagine multinodo vLLM
Per facilitare la comunicazione tra nodi per vLLM, puoi utilizzare Ray. Il repository LeaderWorkerSet fornisce un Dockerfile, che include uno script bash per configurare Ray con vLLM.
Per creare la tua immagine multinodo vLLM, devi clonare il repository LeaderWorkerSet, creare un'immagine Docker utilizzando il Dockerfile fornito (che configura Ray per la comunicazione tra nodi) e poi eseguire il push dell'immagine in Artifact Registry per il deployment su Google Distributed Cloud.
Crea il container
Per creare il contenitore:
Clona il repository LeaderWorkerSet:
git clone https://github.com/kubernetes-sigs/lws.git
Crea l'immagine.
cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile.GPU . -t vllm-multihost
Esegui il push dell'immagine in Artifact Registry
Per assicurarti che il deployment Kubernetes possa accedere all'immagine, archiviala in Artifact Registry all'interno del tuo progetto Google Cloud :
docker image tag vllm-multihost ${IMAGE_NAME}
docker push ${IMAGE_NAME}
Installazione di LeaderWorkerSet
Per installare LWS, esegui questo comando:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
Verifica che il controller LeaderWorkerSet sia in esecuzione nello spazio dei nomi lws-system
utilizzando il seguente comando:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
Esegui il deployment del server di modelli vLLM
Per eseguire il deployment del server del modello vLLM:
Crea e applica il manifest, a seconda dell'LLM che vuoi eseguire il deployment.
DeepSeek-R1
Crea un manifest YAML,
vllm-deepseek-r1-A3.yaml
, per il server del modello 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
Applica il manifest eseguendo questo comando:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
Crea un manifest YAML,
vllm-llama3-405b-A3.yaml
, per il server del modello 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
Applica il manifest eseguendo questo comando:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
Visualizza i log del server del modello in esecuzione con questo comando:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIG
L'output dovrebbe essere simile al seguente:
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)
Pubblica il modello
Configura il port forwarding al modello eseguendo questo comando:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
Interagisci con il modello utilizzando curl
Per interagire con il modello utilizzando curl, segui queste istruzioni:
DeepSeek-R1
In un nuovo terminale, invia una richiesta al server:
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
}'
L'output dovrebbe essere simile al seguente:
{
"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
In un nuovo terminale, invia una richiesta al server:
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
}'
L'output dovrebbe essere simile al seguente:
{"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}}
Passaggi successivi
- Scopri di più sulle GPU in Google Distributed Cloud.
- Esplora il repository GitHub e la documentazione di vLLM.
- Esplora il repository GitHub di LWS