Übersicht
In diesem Leitfaden wird beschrieben, wie Sie moderne Large Language Models (LLMs) wie DeepSeek-R1 671B oder Llama 3.1 405B in Google Distributed Cloud (nur Software) auf Bare Metal mit GPUs auf mehreren Knoten bereitstellen.
In diesem Leitfaden wird gezeigt, wie Sie portable Open-Source-Technologien wie Kubernetes, vLLM und die LeaderWorkerSet-API (LWS) verwenden, um KI-/ML-Arbeitslasten in Bare Metal-Clustern bereitzustellen und auszuführen. Google Distributed Cloud erweitert GKE für die Verwendung in einer lokalen Umgebung und bietet gleichzeitig die Vorteile der detaillierten Steuerung, Skalierbarkeit, Resilienz, Portabilität und Kosteneffizienz von GKE.
Hintergrund
In diesem Abschnitt werden die in diesem Leitfaden verwendeten Schlüsseltechnologien beschrieben, einschließlich der beiden LLMs, die in diesem Leitfaden als Beispiele verwendet werden: DeepSeek-R1 und Llama 3.1 405B.
DeepSeek-R1
DeepSeek-R1 ist ein Large Language Model mit 671 Milliarden Parametern von DeepSeek, das für logische Schlussfolgerungen, mathematische Argumentation und die Lösung von Problemen in Echtzeit bei verschiedenen textbasierten Aufgaben entwickelt wurde. Google Distributed Cloud bewältigt die Rechenanforderungen von DeepSeek-R1 und unterstützt seine Funktionen mit skalierbaren Ressourcen, verteiltem Computing und effizienter Vernetzung.
Weitere Informationen finden Sie in der DeepSeek-Dokumentation.
Llama 3.1 405B
Llama 3.1 405B ist ein Large Language Model von Meta, das für eine Vielzahl von Natural Language Processing-Aufgaben entwickelt wurde, darunter Textgenerierung, Übersetzung und Fragenbeantwortung. Google Distributed Cloud bietet die robuste Infrastruktur, die für die verteilte Trainings- und Bereitstellungsanforderungen von Modellen dieser Größenordnung erforderlich ist.
Weitere Informationen finden Sie in der Llama-Dokumentation.
Verwalteter Kubernetes-Dienst von Google Distributed Cloud
Google Distributed Cloud bietet eine Vielzahl von Diensten, darunter Google Distributed Cloud (nur Software) für Bare Metal, die sich gut für die Bereitstellung und Verwaltung von KI/ML-Arbeitslasten in Ihrem eigenen Rechenzentrum eignet. Google Distributed Cloud ist ein verwalteter Kubernetes-Dienst, der die Bereitstellung, Skalierung und Verwaltung von containerisierten Anwendungen vereinfacht. Google Distributed Cloud bietet die erforderliche Infrastruktur, einschließlich skalierbarer Ressourcen, verteiltem Computing und effizienter Vernetzung, um die Rechenanforderungen von LLMs zu bewältigen.
Weitere Informationen zu wichtigen Kubernetes-Konzepten finden Sie unter Kubernetes lernen. Weitere Informationen zu Google Distributed Cloud und dazu, wie Sie damit Kubernetes skalieren, automatisieren und verwalten können, finden Sie in der Übersicht über Google Distributed Cloud (nur Software) für Bare Metal.
GPUs
Mit Grafikprozessoren (GPUs) können Sie bestimmte Arbeitslasten wie maschinelles Lernen und Datenverarbeitung beschleunigen. Google Distributed Cloud unterstützt Knoten mit diesen leistungsstarken GPUs. So können Sie Ihren Cluster für optimale Leistung bei Aufgaben für maschinelles Lernen und Datenverarbeitung konfigurieren. Google Distributed Cloud bietet eine Reihe von Maschinentypoptionen für die Knotenkonfiguration, einschließlich Maschinentypen mit NVIDIA H100-, L4- und A100-GPUs.
Weitere Informationen finden Sie unter NVIDIA-GPUs einrichten und verwenden.
LeaderWorkerSet (LWS)
LeaderWorkerSet (LWS) ist eine Kubernetes-Bereitstellungs-API, die gängige Bereitstellungsmuster von KI/ML-Inferenzarbeitslasten mit mehreren Knoten abdeckt. Beim Multi-Node-Serving werden mehrere Pods verwendet, die jeweils potenziell auf einem anderen Knoten ausgeführt werden, um die verteilte Inferenzlast zu verarbeiten. Mit LWS können mehrere Pods als Gruppe behandelt werden, was die Verwaltung der verteilten Modellbereitstellung vereinfacht.
vLLM und Bereitstellung mit mehreren Hosts
Wenn Sie rechenintensive LLMs bereitstellen, empfehlen wir die Verwendung von vLLM und die Ausführung der Arbeitslasten auf mehreren GPUs.
vLLM ist ein hoch optimiertes Open-Source-LLM-Bereitstellungs-Framework, das den Bereitstellungsdurchsatz auf GPUs über Funktionen wie die Folgenden beschleunigen kann:
Optimierte Transformer-Implementierung mit PagedAttention
Kontinuierliche Batchverarbeitung zur Verbesserung des allgemeinen Bereitstellungsdurchsatzes
Verteilte Bereitstellung auf mehreren GPUs
Bei besonders rechenintensiven LLMs, die nicht auf einen einzelnen GPU-Knoten passen, können Sie das Modell auf mehreren GPU-Knoten bereitstellen. vLLM unterstützt die Ausführung von Arbeitslasten auf mehreren GPUs mit zwei Strategien:
Bei der Tensor-Parallelität werden die Matrixmultiplikationen in der Transformer-Schicht auf mehrere GPUs aufgeteilt. Diese Strategie erfordert jedoch ein schnelles Netzwerk aufgrund der Kommunikation zwischen den GPUs. Daher ist sie weniger geeignet für die Ausführung von Arbeitslasten über Knoten hinweg.
Bei der Pipeline-Parallelität wird das Modell nach Schicht oder vertikal aufgeteilt. Für diese Strategie ist keine ständige Kommunikation zwischen GPUs erforderlich. Sie ist daher eine bessere Option, wenn Modelle auf mehreren Knoten ausgeführt werden.
Sie können beide Strategien für die Bereitstellung mit mehreren Knoten verwenden. Wenn Sie beispielsweise zwei Knoten mit jeweils acht H100-GPUs verwenden, können Sie beide Strategien nutzen:
Bidirektionale Pipeline-Parallelität zum Sharden des Modells auf die beiden Knoten
Achtfache Tensor-Parallelität zum Sharden des Modells auf die acht GPUs auf jedem Knoten
Weitere Informationen finden Sie in der vLLM-Dokumentation.
Lernziele
Bereiten Sie Ihre Umgebung mit einem Google Distributed Cloud-Cluster im Autopilot- oder Standardmodus vor.
Stellen Sie vLLM auf mehreren Knoten in Ihrem Cluster bereit.
Verwenden Sie vLLM, um das Modell über
curl
bereitzustellen.
Hinweise
- Sie benötigen einen funktionierenden Bare-Metal-Cluster mit mindestens einem Worker-Knotenpool mit zwei Worker-Knoten, die jeweils mit acht NVIDIA H100-GPUs mit 80 GB konfiguriert sind.
- Erstellen Sie ein Hugging Face-Konto, falls Sie noch keines haben.
Zugriff auf das Modell erhalten
Sie können die Modelle Llama 3.1 405B oder DeepSeek-R1 verwenden.
DeepSeek-R1
Zugriffstoken erstellen
Falls Sie noch keines haben, generieren Sie ein neues Hugging Face-Token:
Klicken Sie auf Profil > Einstellungen > Zugriffstokens.
Wählen Sie Neues Token aus.
Geben Sie einen Namen Ihrer Wahl und eine Rolle von mindestens
Read
an.Wählen Sie Token generieren aus.
Llama 3.1 405B
Zugriffstoken erstellen
Falls Sie noch keines haben, generieren Sie ein neues Hugging Face-Token:
Klicken Sie auf Profil > Einstellungen > Zugriffstokens.
Wählen Sie Neues Token aus.
Geben Sie einen Namen Ihrer Wahl und eine Rolle von mindestens
Read
an.Wählen Sie Token generieren aus.
Umgebung vorbereiten
So richten Sie Ihre Umgebung ein:
Legen Sie auf der Administrator-Workstation die folgenden Parameter fest:
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
Ersetzen Sie die folgenden Werte:
PROJECT_ID
: die Projekt-ID, die Ihrem Cluster zugeordnet ist.HUGGING_FACE_TOKEN
: das Hugging Face-Token, das im vorherigen Abschnitt Zugriff auf das Modell erhalten generiert wurde.
Kubernetes-Secret für Hugging Face-Anmeldedaten erstellen
Erstellen Sie mit dem folgenden Befehl ein Kubernetes-Secret, das das Hugging Face-Token enthält:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
Ersetzen Sie KUBECONFIG
durch den Pfad der kubeconfig-Datei für den Cluster, auf dem Sie das LLM hosten möchten.
Eigenes vLLM-Image mit mehreren Knoten erstellen
Um die knotenübergreifende Kommunikation für vLLM zu erleichtern, können Sie Ray verwenden. Das LeaderWorkerSet-Repository enthält ein Dockerfile mit einem Bash-Skript zum Konfigurieren von Ray mit vLLM.
Wenn Sie ein eigenes vLLM-Multi-Node-Image erstellen möchten, müssen Sie das LeaderWorkerSet-Repository klonen, ein Docker-Image mit dem bereitgestellten Dockerfile erstellen (das Ray für die knotenübergreifende Kommunikation konfiguriert) und dieses Image dann zur Bereitstellung in Google Distributed Cloud in Artifact Registry hochladen.
Container erstellen
So erstellen Sie den Container:
Klonen Sie das LeaderWorkerSet-Repository:
git clone https://github.com/kubernetes-sigs/lws.git
Image erstellen
cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile.GPU . -t vllm-multihost
Übertragen Sie das Image per Push in Artifact Registry:
Damit Ihr Kubernetes-Deployment auf das Image zugreifen kann, speichern Sie es in Artifact Registry in Ihrem Google Cloud -Projekt:
docker image tag vllm-multihost ${IMAGE_NAME}
docker push ${IMAGE_NAME}
LeaderWorkerSet installieren
Führen Sie den folgenden Befehl aus, um LWS zu installieren:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
Prüfen Sie mit dem folgenden Befehl, ob der LeaderWorkerSet-Controller im Namespace lws-system
ausgeführt wird:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
Die Ausgabe sieht etwa so aus:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
vLLM Model Server bereitstellen
So stellen Sie den vLLM-Modellserver bereit:
Erstellen Sie das Manifest und wenden Sie es an. Das hängt davon ab, welches LLM Sie bereitstellen möchten.
DeepSeek-R1
Erstellen Sie ein YAML-Manifest (
vllm-deepseek-r1-A3.yaml
) für den vLLM-Modellserver: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
Wenden Sie das Manifest mit dem folgenden Befehl an:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
Erstellen Sie ein YAML-Manifest (
vllm-llama3-405b-A3.yaml
) für den vLLM-Modellserver: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
Wenden Sie das Manifest mit dem folgenden Befehl an:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
Sehen Sie sich die Logs des ausgeführten Modellservers mit dem folgenden Befehl an:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIG
Die Ausgabe sollte in etwa so aussehen:
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)
Modell bereitstellen
Richten Sie mit dem folgenden Befehl die Portweiterleitung zum Modell ein:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
Mithilfe von curl mit dem Modell interagieren
So interagieren Sie mit dem Modell mithilfe von curl:
DeepSeek-R1
Senden Sie in einem neuen Terminal eine Anfrage an den 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
}'
Die Ausgabe sollte in etwa so aussehen:
{
"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
Senden Sie in einem neuen Terminal eine Anfrage an den 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
}'
Die Ausgabe sollte in etwa so aussehen:
{"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}}
Nächste Schritte
- Weitere Informationen zu GPUs in Google Distributed Cloud
- Sehen Sie sich das GitHub-Repository und die Dokumentation zu vLLM an.
- GitHub-Repository für LWS