LLM (Llama3.1 405B) mit mehreren GPU-Knoten bereitstellen


Übersicht

In dieser Anleitung erfahren Sie, wie Sie Llama 3.1 405b mithilfe von GPUs auf mehreren Knoten in der Google Kubernetes Engine (GKE) mit dem vLLM-Bereitstellungs-Framework und der LeaderWorkerSet-API (LWS) bereitstellen.

Dieses Dokument ist ein guter Ausgangspunkt, wenn Sie bei der Bereitstellung und Zugänglichmachung Ihrer KI/ML-Arbeitslasten die detaillierte Kontrolle, Skalierbarkeit, Robustheit, Übertragbarkeit und Kosteneffizienz von verwaltetem Kubernetes benötigen.

LeaderWorkerSet (LWS)

LWS ist eine Kubernetes-Bereitstellungs-API, die gängige Bereitstellungsmuster von KI-/ML-Multi-Node-Inferenzarbeitslasten anspricht. Mit LWS können mehrere Pods als Gruppe behandelt werden.

Bereitstellung mehrerer Hosts mit vLLM

Wenn Sie außergewöhnlich große Sprachmodelle bereitstellen, die nicht auf einen einzelnen GPU-Knoten passen, verwenden Sie mehrere GPU-Knoten, um das Modell bereitzustellen. vLLM unterstützt sowohl Tensor-Parallelität als auch Pipeline-Parallelität, um Arbeitslasten auf GPUs auszuführen.

Bei der Tensor-Parallelität werden die Matrixmultiplikationen in der Transformer-Ebene auf mehrere GPUs aufgeteilt. Diese Strategie erfordert jedoch ein schnelles Netzwerk, da die Kommunikation zwischen den GPUs erforderlich ist. Daher eignet sie sich weniger für die Ausführung von Arbeitslasten auf mehreren Knoten.

Bei der Pipeline-Parallelität wird das Modell nach Ebene oder vertikal aufgeteilt. Bei dieser Strategie ist keine ständige Kommunikation zwischen den GPUs erforderlich. Daher ist sie eine bessere Option, wenn Modelle auf mehreren Knoten ausgeführt werden.

Sie können beide Strategien beim Ausliefern über mehrere Knoten verwenden. Wenn Sie beispielsweise zwei Knoten mit jeweils 8 H100-GPUs verwenden, können Sie das Modell mithilfe der zweistufigen Pipeline-Parallelisierung auf die beiden Knoten und mithilfe der achtstufigen Tensor-Parallelisierung auf die acht GPUs auf jedem Knoten aufteilen.

Lernziele

  1. Bereiten Sie einen GKE Standard-Cluster vor.
  2. Stellen Sie vLLM auf mehreren Knoten in Ihrem Cluster bereit.
  3. vLLM verwenden, um das Llama3-405b-Modell über curl bereitzustellen

Hinweise

  • Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • Make sure that you have the following role or roles on the project: roles/container.admin, roles/iam.serviceAccountAdmin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      IAM aufrufen
    2. Wählen Sie das Projekt aus.
    3. Klicken Sie auf Zugriff erlauben.
    4. Geben Sie im Feld Neue Hauptkonten Ihre Nutzer-ID ein. Dies ist in der Regel die E-Mail-Adresse eines Google-Kontos.

    5. Wählen Sie in der Liste Rolle auswählen eine Rolle aus.
    6. Wenn Sie weitere Rollen hinzufügen möchten, klicken Sie auf Weitere Rolle hinzufügen und fügen Sie weitere Rollen hinzu.
    7. Klicken Sie auf Speichern.
  • Erstellen Sie ein Hugging Face-Konto, falls Sie noch keines haben.
  • Prüfen Sie, ob Ihr Projekt ein ausreichendes Kontingent für GPUs hat. Weitere Informationen finden Sie unter GPUs und Zuteilungskontingente.

Zugriff auf das Modell erhalten

unterzeichnen.

Zugriffstoken erstellen

Generieren Sie ein neues Hugging Face-Token, falls Sie noch keines haben:

  1. Klicken Sie auf Profil > Einstellungen > Zugriffstokens.
  2. Wählen Sie Neues Token aus.
  3. Geben Sie einen Namen Ihrer Wahl und eine Rolle von mindestens Read an.
  4. Wählen Sie Token generieren aus.

Umgebung vorbereiten

In dieser Anleitung verwenden Sie Cloud Shell zum Verwalten von Ressourcen, die inGoogle Cloudgehostet werden. Die Software, die Sie für diese Anleitung benötigen, ist in Cloud Shell vorinstalliert, einschließlich kubectl und gcloud CLI.

So richten Sie Ihre Umgebung mit Cloud Shell ein:

  1. Starten Sie in der Google Cloud -Konsole eine Cloud Shell-Sitzung. Klicken Sie dazu in der Google Cloud -Konsole auf Symbol für die Cloud Shell-Aktivierung Cloud Shell aktivieren. Dadurch wird im unteren Bereich der Google Cloud -Konsole eine Sitzung gestartet.

  2. Legen Sie die Standardumgebungsvariablen fest:

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export CLUSTER_NAME=CLUSTER_NAME
    export ZONE=ZONE
    export HF_TOKEN=HUGGING_FACE_TOKEN
    export IMAGE_NAME=IMAGE_NAME
    

    Ersetzen Sie die folgenden Werte:

    • PROJECT_ID: Ihre Google Cloud Projekt-ID.
    • CLUSTER_NAME: der Name Ihres GKE-Clusters.
    • ZONE: Eine Zone, die H100 unterstützt.
    • IMAGE_NAME: Das vLLM-Image mit dem Ray-Script. Wir stellen Ihnen us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20240821_1034_RC00 zur Verfügung oder Sie können es selbst erstellen.

GKE-Cluster erstellen

Sie können Modelle mit vLLM auf mehreren GPU-Knoten in einem GKE-Cluster im Autopilot- oder Standardmodus bereitstellen. Für eine vollständig verwaltete Kubernetes-Umgebung empfehlen wir die Verwendung eines Autopilot-Clusters. Informationen zum Auswählen des GKE-Betriebsmodus, der für Ihre Arbeitslasten am besten geeignet ist, finden Sie unter GKE-Betriebsmodus auswählen.

Autopilot

Führen Sie in Cloud Shell den folgenden Befehl aus:

  gcloud container clusters create-auto ${CLUSTER_NAME} \
    --project=${PROJECT_ID} \
    --region=${REGION} \
    --cluster-version=${CLUSTER_VERSION}

Standard

  1. Erstellen Sie einen GKE Standard-Cluster mit zwei CPU-Knoten:

    gcloud container clusters create CLUSTER_NAME \
        --project=PROJECT_ID \
        --num-nodes=2 \
        --location=ZONE \
        --machine-type=e2-standard-16
    
  2. Erstellen Sie einen A3-Knotenpool mit zwei Knoten, die jeweils acht H100s enthalten:

    gcloud container node-pools create gpu-nodepool \
        --location=ZONE \
        --num-nodes=2 \
        --machine-type=a3-highgpu-8g \
        --accelerator=type=nvidia-h100-80gb,count=8,gpu-driver-version=LATEST \
        --placement-type=COMPACT \
        --cluster=CLUSTER_NAME
    

Konfigurieren Sie kubectl für die Kommunikation mit Ihrem Cluster:

gcloud container clusters get-credentials CLUSTER_NAME --location=ZONE

Kubernetes-Secret für Hugging Face-Anmeldedaten erstellen

Erstellen Sie ein Kubernetes-Secret, das das Hugging Face-Token enthält:

kubectl create secret generic hf-secret \
  --from-literal=hf_api_token=${HF_TOKEN} \
  --dry-run=client -o yaml | kubectl apply -f -

Optional: Eigenes vLLM-Multi-Node-Image erstellen

Wenn Sie mehr Kontrolle über den Inhalt Ihres Docker-Images haben und neben Ihrem Script bestimmte Abhängigkeiten einschließen möchten, wählen Sie diese Option aus. Wenn Sie vLLM auf mehreren Knoten ausführen möchten, können Sie Ray für die Knotenübergreifende Kommunikation verwenden. Im Dockerfile finden Sie ein Bash-Script zum Einrichten von Ray mit vLLM im LeaderWorkerSet-Repository.

Container erstellen

  1. Klonen Sie das LeaderWorkerSet-Repository:

    git clone https://github.com/kubernetes-sigs/lws.git
    
  2. Image erstellen

    cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile . -t vllm-multihost
    

Übertragen Sie das Image per Push in Artifact Registry:

Damit Ihre Kubernetes-Bereitstellung auf das Image zugreifen kann, speichern Sie es in Artifact Registry in Ihrem Google Cloud -Projekt.

gcloud artifacts repositories create vllm-multihost --repository-format=docker --location=REGION_NAME && \
gcloud auth configure-docker REGION_NAME-docker.pkg.dev && \
docker image tag vllm-multihost REGION_NAME-docker.pkg.dev/PROJECT_ID/vllm-multihost/vllm-multihost:latest && \
docker push REGION_NAME-docker.pkg.dev/PROJECT_ID/vllm-multihost/vllm-multihost:latest

LeaderWorkerSet installieren

Führen Sie den folgenden Befehl aus, um LWS zu installieren:

VERSION=v0.4.2
kubectl apply --server-side -f https://github.com/kubernetes-sigs/lws/releases/download/$VERSION/manifests.yaml

Prüfen Sie, ob der LeaderWorkerSet-Controller im Namespace lws-system ausgeführt wird:

kubectl get pod -n lws-system

Die Ausgabe sieht in etwa so aus:

NAME                                      READY   STATUS    RESTARTS   AGE
lws-controller-manager-5c4ff67cbd-9jsfc   2/2     Running   0          6d23h

vLLM-Modellserver bereitstellen

So stellen Sie den vLLM-Modellserver bereit:

  1. Prüfen Sie das Manifest vllm-llama3-405b-A3.yaml.

    
    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
                  - "/workspace/vllm/examples/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:
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-h100-80gb
            containers:
              - name: vllm-worker
                image: IMAGE_NAME
                command:
                  - sh
                  - -c
                  - "/workspace/vllm/examples/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
    
  2. Wenden Sie das Manifest mit dem folgenden Befehl an:

    kubectl apply -f vllm-llama3-405b-A3.yaml
    
  3. Logs des laufenden Modellservers aufrufen

    kubectl logs vllm-0 -c vllm-leader
    

    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

Führen Sie den folgenden Befehl aus, um die Portweiterleitung zum Modell einzurichten:

kubectl port-forward svc/vllm-leader 8080:8080

Mithilfe von curl mit dem Modell interagieren

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}}

Optional: Modellladezeiten mit Hyperdisk ML beschleunigen

Es kann bis zu 90 Minuten dauern, bis Llama 3.1-405B auf jedem neuen Replikat heruntergeladen, geladen und aufgewärmt wurde. Sie können diese Zeit auf 20 Minuten verkürzen, indem Sie das Modell direkt auf einen Hyperdisk ML herunterladen und auf jedem Pod bereitstellen.

Folgen Sie dem Tutorial KI-/ML-Datenladevorgang mit Hyperdisk ML beschleunigen mit den folgenden YAML-Dateien:

  1. Speichern Sie das folgende Beispielmanifest als producer-pvc.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: producer-pvc
    spec:
      storageClassName: hyperdisk-ml
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 800Gi
    
  2. Speichern Sie das folgende Beispielmanifest als producer-job.yaml:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: producer-job
    spec:
      template:  # Template for the Pods the Job will create
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: cloud.google.com/machine-family
                    operator: In
                    values:
                    - "c3"
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - "ZONE"
          containers:
          - name: copy
            resources:
              requests:
                cpu: "32"
              limits:
                cpu: "32"
            image: python:3.11-bookworm
            command:
            - bash
            - -c
            - "pip install 'huggingface_hub==0.24.6' && \
              huggingface-cli download meta-llama/Meta-Llama-3.1-405B-Instruct --local-dir-use-symlinks=False --local-dir=/data/Meta-Llama-3.1-405B-Instruct --include *.safetensors *.json"
            env:
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
              - mountPath: "/data"
                name: volume
          restartPolicy: Never
          volumes:
            - name: volume
              persistentVolumeClaim:
                claimName: producer-pvc
      parallelism: 1         # Run 1 Pods concurrently
      completions: 1         # Once 1 Pods complete successfully, the Job is done
      backoffLimit: 4        # Max retries on failure
    

vLLM-Modellserver bereitstellen

Nachdem Sie die Schritte ausgeführt haben, können Sie die vLLM-Bereitstellung mit mehreren Knoten für den GPU-Server bereitstellen, der das Hyperdisk ML-Volume nutzt.



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:
        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
              - "/workspace/vllm/examples/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); 
                python3 -m vllm.entrypoints.openai.api_server --port 8080 --model /models/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
              - mountPath: /models
                name: llama3-405b
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
        - name: llama3-405b
          persistentVolumeClaim:
            claimName: hdml-static-pvc
    workerTemplate:
      spec:
        containers:
          - name: vllm-worker
            image: IMAGE_NAME
            command:
              - sh
              - -c
              - "/workspace/vllm/examples/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
              - mountPath: /models
                name: llama3-405b
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
        - name: llama3-405b
          persistentVolumeClaim:
            claimName: hdml-static-pvc
---
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

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Bereitgestellte Ressourcen löschen

Führen Sie den folgenden Befehl aus, um zu vermeiden, dass Ihrem Google Cloud -Konto die in dieser Anleitung erstellten Ressourcen in Rechnung gestellt werden:

gcloud container clusters delete CLUSTER_NAME \
  --location=ZONE

Nächste Schritte