Nutzerhandbuch für Open-Weight-LLMs in GDC mit Air Gap

Dieser Bereitstellungsleitfaden enthält eine detaillierte Anleitung zum Ausführen von modernen Large Language Models (LLMs) mit Open-Source-Software (OSS) in Google Distributed Cloud (GDC)-Umgebungen mit Air Gap. In dieser Anleitung werden alle Schritte beschrieben, die zum Ausführen der neuesten Releases von Gemma-, DeepSeek- und Llama-Modellen erforderlich sind. Außerdem werden allgemeine Verfahren zum Bereitstellen anderer öffentlich verfügbarer LLMs vorgestellt. Wir werden containerisierte Serving-Backends wie vLLM und Ollama nutzen, die eine Vielzahl von Funktionen, unterschiedliche Konfigurationsstufen und eine einfache Bereitstellung bieten.

Inhaltszusammenfassung

In diesem Leitfaden wird die Bereitstellung und der Betrieb von Open-Source-Large Language Models (LLMs) in Google Distributed Cloud (GDC) mit Air Gap beschrieben.

Kernziele und Infrastruktur

  • Zweck: Detaillierte Anleitung zum Ausführen von hochmodernen LLMs, einschließlich Gemma 3 (multimodal), DeepSeek-R1 und Llama (3.1/3.2) mit optimierten Back-Ends wie vLLM und Ollama.
  • Mindestversion: GDC-Softwareversion mit Air Gap 1.15.x*.
  • Hardwareanforderungen: Mindestens 1 NVIDIA A100-GPU ist erforderlich. Für eine optimale Ladezeit von Modellgewichten (von 30 Minuten auf unter 5 Minuten) wird Hochleistungsspeicher (PVC mit mindestens 500 GiB) empfohlen.

Bereitstellungskomponenten

Komponente Beschreibung
LLM-Backends vLLM (Bereitstellung mit hohem Durchsatz mit PagedAttention) und Ollama (vereinfachte lokale Verwaltung und multimodale Unterstützung)
Modelle Öffentlich verfügbare LLMs, einschließlich der Familien Gemma, DeepSeek und Llama
Beschleuniger Unterstützt vollständige NVIDIA A100-GPUs oder MIG-Slices (Multi-Instance GPU), je nach VRAM-Footprint des Modells.
GDC-Dienste Verwendet GDC Container Service, Load Balancer (ELB/ILB), Harbor Container Registry

Wichtige Betriebsverfahren

  • Modellverwaltung: Das LLM-Backend verwaltet das Laden und Entladen von Modellen basierend auf der Nutzung. vLLM fixiert Modelle im Arbeitsspeicher, um eine gleichbleibend niedrige Latenz zu erzielen, während Ollama das dynamische Laden von Modellen ermöglicht, Modelle aber nach 30 Minuten Inaktivität automatisch entlädt.
  • Anpassung: Nutzer können bevorzugte LLMs verwenden, indem sie sie aus dem Internet abrufen, neue Docker-Images erstellen und in die lokale Harbor-Registry hochladen.

Vorbereitung

Release

  • GDC mit Air Gap, Version 1.15.1 oder höher.

Komponenten

  • Der Nutzercluster wurde mit ausreichenden Ressourcen (CPU, Arbeitsspeicher, GPU) erstellt.
  • Es ist mindestens eine NVIDIA A100-GPU erforderlich.
  • Die Harbor-Instanz ist verfügbar und zugänglich.
  • Die kubectl- und gdcloud-Befehlszeilen sind für den Zugriff auf den Nutzercluster konfiguriert.
  • Der Docker-Client ist installiert und für das Pushen in Harbor konfiguriert.
  • Die erforderlichen IAM-Berechtigungen wurden gewährt (z. B. Namespace Admin, Cluster Developer).
  • Wenn Sie Modelle mit eingeschränktem Zugriff verwenden, müssen Sie ein Hugging Face-Konto haben und die Authentifizierung muss konfiguriert sein.

Kapazitätsbedarf

Ressource Kapazität
CPU 8 vCPUs
RAM 32 GiB
Sitzungsspezifischer Speicher 16 Gi
GPUs 1 NVIDIA A100-GPU
Nichtflüchtiges Volume *500 GiB+

Diese Hardwareressourcen sind erforderlich, damit Back-Ends LLMs mit GPU-Beschleunigung ausführen können. Ein a2-ultragpu-1g-gdc-Maschinentyp würde beispielsweise genügend Ressourcen bereitstellen.

Gesamtdiagramm

Allgemeines Diagramm zur Bereitstellung von LLMs mit offenen Gewichten.

In diesem Diagramm ist ein Nutzer zu sehen, der APIs nutzt, die von zwei LLM-Back-Ends (vLLM und Ollama) bereitgestellt werden, um Inferenzantworten von Open-Source-Modellen wie Gemma, Llama und DeepSeek zu erhalten. Je nach Modellgröße, gemessen in Milliarden von Parametern, benötigt jedes LLM möglicherweise eine vollständige GPU oder einen Teil davon, um ausgeführt zu werden.

Diagramm der Dienst- und Sicherheitsgrenzen für ein LLM-Deployment

Diese Lösung basiert auf den folgenden Diensten, die bereits im GDC-Softwarestack für Air-Gap-Umgebungen enthalten sind:

  • GDC Container Service: zum Ausführen aller Prozesse und zum Skalieren mit HPA.
  • GDC Load Balancer: Mit einem Kubernetes-Dienst werden alle Backends in dieser Lösung bereitgestellt und die LLMs sind über das Kundennetzwerk zugänglich. Dies wird als ELB bezeichnet, was für „External Load Balancer“ (externer Load Balancer) steht. Umgekehrt kann der Kunde festlegen, dass LLMs nur innerhalb eines Nutzerclusters erreichbar sind. Das kann nützlich sein, wenn nur ein interner Agent in seiner Lösung Inferenzanfragen stellt. Dies wird als ILB bezeichnet, was für Internal Load Balancer (interner Load Balancer) steht.
  • GDC CI/CD: Harbor Container Registry zum Speichern von LLM-Back-Ends und Modellgewichten.
  • GDC Observability Stack: zum Erfassen und Suchen von Backend-Logs und zum Bereitstellen von Dashboards.

In Bezug auf die Sicherheit hängt der Zugriff auf die LLM-Bereitstellung davon ab, welche Nutzer den Load-Balancer-Dienst erreichen können, der die LLM-Serving-Backends verfügbar macht, die als Pods in einem Kubernetes-Projekt / -Namespace ausgeführt werden.

Architekturdiagramm für Dienst- und Sicherheitsgrenzen.

Bereitstellung

Vorbereitung

Installieren Sie die folgenden Tools auf einer Workstation, die mit Ihrer GDC mit Air Gap-Umgebung verbunden ist:

  1. docker
  2. kubectl
  3. gcloud-CLI

Dieses Dokument enthält den gesamten Quellcode und alle Konfigurationsdateien, die Sie zum Bereitstellen von LLMs benötigen.

Secret zum Abrufen von Bildern aus Harbor erstellen

Wenn Sie ein Image-Pull-Secret für eine Containerarbeitslast in GDC mit Air Gap konfigurieren möchten, müssen Sie ein Kubernetes-Secret vom Typ docker-registry erstellen, das Anmeldedaten für den Zugriff auf Ihr privates Harbor-Projekt enthält. Auf dieses Secret wird dann in Ihrer Bereitstellungsspezifikation verwiesen.

Für den programmatischen Zugriff auf Bilder in privaten Harbor-Projekten sollten Sie ein Harbor-Roboterkonto verwenden.

So konfigurieren Sie das Image-Pull-Secret:

Harbor-Roboterkonto erstellen:

  • Rufen Sie die Benutzeroberfläche Ihrer Harbor-Instanz auf.
  • Rufen Sie Ihr Harbor-Projekt auf.
  • Wählen Sie den Tab Roboterkonten aus.
  • Klicken Sie auf + NEUES ROBOT-KONTO.
  • Geben Sie ihm einen Namen (z. B. oss-llm-puller) und gewähren Sie ihm bis zu einem Ablaufdatum die erforderlichen Berechtigungen (mindestens „pull“-Zugriff).
  • Speichern Sie den Namen des Roboterkontos (z. B. robot$oss-llm-puller) und das bereitgestellte geheime Token sicher.

Docker für Harbor authentifizieren:

Melden Sie sich auf Ihrem Computer, auf dem Docker installiert ist und der Netzwerkzugriff auf die Harbor-Registry hat, mit den Anmeldedaten des Roboter-Kontos an:

export INSTANCE_URL="your-harbor-instance-url"
# for example, harbor1-project1.org1.zone1.google.gdc.com

export ROBOT_NAME="your-robot-account-name"
# for example, robot\$oss-llm-puller (note how we escape the $ character)

export ROBOT_SECRET="your-robot-account-secret"

docker login ${INSTANCE_URL} --username ${ROBOT_NAME} --password ${ROBOT_SECRET}

# Sample output:

WARNING! Using --password via the CLI is insecure. Use --password-stdin.

WARNING! Your credentials are stored unencrypted in '$HOME/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

Wie in der Beispielausgabe zu sehen ist, wird durch diesen Befehl die lokale Docker-Konfigurationsdatei ($HOME/.docker/config.json) mit den Authentifizierungsdetails aktualisiert. Die Datei „config.json“ sieht so aus:

{
    "auths": {
        "harbor1-project1.org1.zone1.google.gdc.com": {
            "auth": "...omitted..."
        }
    }
}

Wenn Sie sich in der Vergangenheit mit Ihrem Docker-Client in anderen Registries angemeldet haben, sehen Sie mehr Einträge unter „auths“.

Kubernetes-Secret zum Abrufen von Images erstellen:

Verwenden Sie kubectl, um ein Secret vom Typ docker-registry in Ihrem Projektnamespace zu erstellen. Verwenden Sie dazu die Docker-Konfigurationsdatei, die im vorherigen Schritt aktualisiert wurde:

# Log in to GDC air-gapped using the next commands

gdcloud auth login --login-config-cert {path to your web TLS certificate}

gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE

export SECRET_NAME="oss-llm-pull-secret" # You can choose another name
export NAMESPACE="your-project-namespace"
# Assuming default Docker config path. Adjust if necessary.
export DOCKER_CONFIG_PATH="$HOME/.docker/config.json"

kubectl create secret docker-registry ${SECRET_NAME} \
      --from-file=.dockerconfigjson=${DOCKER_CONFIG_PATH} \
      -n ${NAMESPACE}

Sie verweisen später in der Spezifikation Ihres LLM-Backend-Containers auf dieses Secret, indem Sie das Feld imagePullSecrets einfügen.

Wenn Sie diese Schritte ausführen, verwendet Ihr Kubernetes-Cluster jetzt die bereitgestellten Anmeldedaten, um ein Container-Image aus Ihrer privaten Harbor-Registry in Ihrer GDC mit Air Gap-Umgebung abzurufen. Diese Schritte sind auch in der Produktdokumentation enthalten.

LLM-Bereitstellung einrichten

Für das LLM-Backend haben Sie die folgenden zwei Optionen:

  • vLLM
  • Ollama

Sie können einen oder beide Backends auswählen. Auf jedem Backend können ein oder mehrere LLMs ausgeführt werden, z. B.:

  • Gemma 3
  • DeepSeek
  • Llama 3
  • Andere LLMs

In Abschnitt 1 finden Sie eine Anleitung zum Bereitstellen von vLLM und in Abschnitt 2 wird die Installation von Ollama beschrieben.

1. vLLM als LLM-Backend bereitstellen

vLLM-Docker-Image abrufen

Im Allgemeinen wird vLLM verwendet, um Modelle bereitzustellen, die von Hugging Face heruntergeladen wurden. Dies wird in diesem LLM-Deployment gezeigt. Einige Modelle sind zugangsbeschränkt. Das bedeutet, dass Nutzer den Zugriff auf ihre Dateien und Inhalte im Hugging Face Hub explizit anfordern oder ihm zustimmen müssen, bevor sie sie herunterladen oder verwenden können.

Melden Sie sich mit Docker bei Ihrer Harbor-Instanz an, wie in der Dokumentation beschrieben. Rufen Sie auf einem Computer mit Internetzugriff das vLLM-Docker-Image ab und übertragen Sie es dann in Ihr Harbor-Projekt:

# Pull and Tag vLLM (v0.13.0 recommended for stability)
docker pull vllm/vllm-openai:v0.13.0
docker tag vllm/vllm-openai:v0.13.0 HARBOR_URL/PROJECT/vllm-openai:v0.13.0
docker push HARBOR_URL/PROJECT/vllm-openai:v0.13.0

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.

Die in diesem Bereitstellungsleitfaden verwendete vLLM-Version ist v0.13.0.

LLM-Modellgewichte in einem PVC speichern

Öffnen Sie ein neues Terminal und erstellen Sie einen Ordner, in dem Sie die Dateien für die vLLM-Bereitstellung speichern:

mkdir vllm-deployment
cd vllm-deployment

Erstellen Sie dann eine YAML-Datei (z. B. model-pvc.yaml), um einen PersistentVolumeClaim (PVC) mit standardmäßigen Kubernetes-Primitiven zu deklarieren:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: model-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Gi
  storageClassName: standard-rwo
  volumeMode: Filesystem

Stellen Sie eine Verbindung zu Ihrem GDC-Cluster ohne Internetverbindung her und wenden Sie den PVC an:

# Log in to GDC air-gapped using the next commands

gdcloud auth login --login-config-cert {path to your web TLS cert}

gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE

# Apply the PVC manifest
kubectl apply -f model-pvc.yaml

Modellgewichte von Hugging Face herunterladen:

# Log in to Hugging Face
hf auth login

# Download weights for Gemma 3 (for example, 4B instruction-tuned)
hf download google/gemma-3-4b-it

Beispielausgabe:

Fetching 9 files: 100%| 9/9 [00:00<00:00, 19.34it/s]
Downloading (…)7f58a/.gitattributes: 100%| 1.62k/1.62k [00:00<00:00, 7.82MB/s]
Downloading (…)del-00002-of-00002.safetensors: 100%| 3.75G/3.75G [00:46<00:00, 81.3MB/s]
Downloading (…)del-00001-of-00002.safetensors: 100%| 4.90G/4.90G [00:54<00:00, 90.1MB/s]
Downloading (…)-3-4b-it/README.md: 100%| 23.3k/23.3k [00:00<00:00, 48.0MB/s]
Downloading (…)8a/model.safetensors.index.json: 100%| 26.3k/26.3k [00:00<00:00, 39.5MB/s]
Downloading (…)f58a/config.json: 100%| 908/908 [00:00<00:00, 4.41MB/s]
Downloading (…)generation_config.json: 100%| 210/210 [00:00<00:00, 936kB/s]
Downloading (…)tokenizer.json: 100%| 33.1M/33.1M [00:01<00:00, 17.6MB/s]
/Users/rashjab/.cache/huggingface/hub/models--google--gemma-3-4b-it/snapshots/952ec8ffca3adadfd00c6d71b40280ebdbb7f58a

Wie Sie in der Beispielausgabe sehen können, beträgt die Modellgröße auf der Festplatte 8,64 GB, was in den zuvor definierten PVC mit 500 GiB passt. Achten Sie immer darauf, dass dies für jedes Modell der Fall ist, das Sie in das Persistent Volume (PV) laden. Wenn Sie beispielsweise ein 15-GB-Modell mit einem 500-GiB-PVC verwenden, um 1.500 IOPS zu erreichen, wird die Ladezeit des Gewichts von etwa 30 Minuten auf unter 5 Minuten verkürzt.

Füllen Sie das PV, indem Sie die Modelldateien in sein Volume kopieren. Dazu gehören oft:

  • Erstellen eines temporären „Helper“-Pods, der das PV mountet.
  • Verwenden Sie kubectl cp, um die Modelldateien von Ihrer Workstation in das bereitgestellte Volume des Helper-Pods zu kopieren.
  • Beispiel für einen Helper-Pod:

helper-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: model-uploader
spec:
  containers:
  - name: uploader
    image: HARBOR_URL/PROJECT/busybox:latest
    command: ["sleep", "3600"]
    volumeMounts:
    - name: model-data
      mountPath: /data
  imagePullSecrets:
  - name: oss-llm-pull-secret
  volumes:
  - name: model-data
    persistentVolumeClaim:
      claimName: model-pvc

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.
  • oss-llm-pull-secret: wenn Sie einen anderen Namen für das Image-Pull-Secret ausgewählt haben.
  • model-pvc: mit dem Namen, den Sie Ihrem PVC gegeben haben.

Übertragen Sie das Helper-Docker-Image (busybox) per Push:

docker pull busybox:latest
docker tag busybox HARBOR_URL/PROJECT/busybox:latest
docker push HARBOR_URL/PROJECT/busybox:latest

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.

Wenden Sie die Datei helper-pod.yaml an und kopieren Sie die Modellgewichte auf das PV:

kubectl apply -f helper-pod.yaml

# Wait for the pod to be Running
kubectl cp ~/.cache/huggingface/hub/ NAMESPACE/model-uploader:/data/

# After copying, delete the helper pod
kubectl delete pod model-uploader

vLLM-Backend bereitstellen

Erstellen Sie die Bereitstellungsdatei für vLLM, um den Modellserver auszuführen. Im folgenden Beispiel wird das Modell gemma-3-4b-it bereitgestellt.

vllm-gemma-3-4b-it-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gemma-3-4b-it
  labels:
    app: gemma-3-4b-it
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gemma-3-4b-it
  template:
    metadata:
      labels:
        app: gemma-3-4b-it
    spec:
      volumes:
      - name: cache-volume
        persistentVolumeClaim:
          claimName: model-pvc # change with the name you gave initially to your PVC
      # vLLM needs to access the host's shared memory for tensor parallel inference.
      - name: shm
        emptyDir:
          medium: Memory
          sizeLimit: "16Gi"
      containers:
      - name: gemma-3-4b-it
        image: HARBOR_URL/PROJECT/vllm-openai:v0.13.0
        command: ["python3"]
        args: [
          "-m",
          "vllm.entrypoints.openai.api_server",
          "--model",
          "google/gemma-3-4b-it", # Use the repo ID
          "--max-model-len",
          "32768",
          "--enforce-eager"
        ]
        env:
        - name: HF_HUB_OFFLINE
          value: "1"
        - name: HF_HOME
          value: "/model" # Tells vLLM to look for models in /model/hub
        # --- PERFORMANCE & STABILITY OPTIMIZATIONS ---
        - name: NCCL_P2P_DISABLE
          value: "1" # Prevents initialization hangs on P2P checks
        - name: NCCL_IB_DISABLE
          value: "1" # Prevents initialization hangs on InfiniBand checks
        # --- FIPS BYPASS ---
        - name: BORINGSSL_FIPS
          value: "0"
        - name: OPENSSL_FIPS
          value: "0"
        - name: OPENSSL_CONF
          value: "/dev/null"
        - name: FIPS_SIG
          value: "off"
        ports:
        - containerPort: 8000
        securityContext:
          privileged: true
          runAsUser: 0
        resources:
          limits:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
            cpu: "8"       # Increased to handle model weight verification
            memory: "64Gi"  # Increased to ensure headroom for weight loading
          requests:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
            cpu: "8"
            memory: "32Gi"
        volumeMounts:
        - name: cache-volume
          mountPath: /model
        - name: shm
          mountPath: /dev/shm
      imagePullSecrets:
      - name: oss-llm-pull-secret

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.
  • oss-llm-pull-secret: Der Name, den Sie beim Erstellen des Image-Pull-Secrets angegeben haben.
  • claimName: der Name, den Sie Ihrem ersten PVC gegeben haben.

Erstellen Sie als Nächstes eine Kubernetes-Dienstdatei, um die vLLM-Backend-APIs bereitzustellen:

vllm-gemma-3-4b-it-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: gemma-3-4b-it
  namespace: NAMESPACE
spec:
  ports:
  - name: http-gemma-3-4b-it
    port: 80
    protocol: TCP
    targetPort: 8000
  selector:
    app: gemma-3-4b-it
  sessionAffinity: None
  type: LoadBalancer

Wenden Sie die Deployment- und Dienstkonfigurationen an:

kubectl apply -f vllm-gemma-3-4b-it-deployment.yaml
kubectl apply -f vllm-gemma-3-4b-it-service.yaml

vLLM-Bereitstellung prüfen und testen

  1. Pod-Status prüfen:

    kubectl get pods
    

    Warten Sie, bis der Pod den Status Running erreicht hat.

  2. Prüfen Sie den Dienst:

    kubectl get service
    

    Beispielausgabe:

    # NAME          TYPE         CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
    # gemma-3-4b-it LoadBalancer 10.201.136.62  136.125.37.198   80:30109/TCP   3d1h
    

    Notieren Sie sich die EXTERNAL-IP des vLLM-Dienstes (z. B. 136.125.37.198) aus der vorherigen Ausgabe. Sie können es auch mit folgenden Optionen ausdrucken:

    kubectl get service gemma-3-4b-it \
    -o jsonpath='{.status.loadBalancer.ingress[*].ip}'
    
  3. Logs ansehen:

    kubectl logs YOUR_VLLM_POD
    

    Suchen Sie nach Meldungen, die darauf hinweisen, dass der Server gestartet und das Modell geladen wurde (z. B. INFO: Application startup complete.). Da kein Hugging Face-Download erfolgt, sollte dies schnell gehen, wenn sich die Dateien auf dem PVC mit einer hohen Persistent Volume-Kapazität befinden.

  4. Inferenz mit curl testen:

    Nachdem Sie bestätigt haben, dass der vLLM-Pod ausgeführt wird und Sie die externe IP-Adresse des Dienstes haben, können Sie mit curl eine Inferenzanfrage senden. Da vLLM eine OpenAI-kompatible API bietet, können Sie den /v1/chat/completions-Endpunkt verwenden:

    curl http://EXTERNAL_IP/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "google/gemma-3-4b-it",
        "messages": [
          {"role": "user", "content": "What is Google Distributed Cloud air-gapped?"}
        ],
        "max_tokens": 100
      }'
    

    Ersetzen Sie EXTERNAL_IP durch die externe IP-Adresse des vLLM-Dienstes.

2. Ollama als LLM-Backend bereitstellen

Ollama ist ein beliebtes Framework zum lokalen Ausführen von Open-Source-LLMs und in containerisierten Umgebungen. Sie vereinfacht die Ausführung von Modellen, da sie das Herunterladen von Gewichten, die Quantisierung und die GPU-Beschleunigung übernimmt. Sie enthält eine integrierte REST API zum Generieren von Vervollständigungen, Chat-Antworten und Einbettungen.

Im Gegensatz zu anderen Serving-Engines verwaltet Ollama die Ausführung von Modellen dynamisch:

  • Dynamisches Laden von Modellen: Wenn eine Anfrage für ein bestimmtes Modell eingeht, lädt Ollama die Gewichte bei Bedarf in den Speicher (GPU-VRAM oder System-RAM).
  • Entladen bei Inaktivität: Wenn für ein Modell 30 Minuten lang keine Inferenzanfragen eingehen (konfigurierbar mit OLLAMA_KEEP_ALIVE), wird es von Ollama aus dem Arbeitsspeicher entladen, um Hardware-Ressourcen für andere Arbeitslasten freizugeben.
  • Ein einzelnes aktives Modell pro Instanz: Ollama verarbeitet Anfragen für jeweils ein aktives Modell pro Serverinstanz. Wenn mehrere Modelle parallel aufgerufen werden, stellt Ollama die Anfragen in die Warteschlange und tauscht die Modelle sequenziell aus, was zu Latenz führen kann. Wenn Sie mehrere Modelle gleichzeitig bereitstellen möchten, ohne sie auszutauschen, sollten Sie für jedes Modell separate Ollama-Instanzen bereitstellen.

Modellgewichte herunterladen und ein Docker-Image erstellen

Im Gegensatz zu vLLM, das Gewichte direkt aus einem Persistent Volume laden kann, erwartet Ollama in der Regel, dass Modelle im internen Verzeichnisformat (~/.ollama/models) gespeichert werden.

In einer Umgebung ohne Internetverbindung, in der die Laufzeitcontainer keine Modelle aus dem öffentlichen Internet herunterladen können, müssen Sie die Modellgewichte während der Build-Phase in das Container-Image selbst einfügen. So ist sichergestellt, dass der Container vollständig in sich geschlossen ist und nach der Bereitstellung sofort bereit ist, Anfragen zu bearbeiten, ohne dass ein externer Netzwerkzugriff erforderlich ist.

Erstellen Sie einen Ordner für die Ollama-Bereitstellung:

mkdir ollama-gemma3
cd ollama-gemma3

Erstellen Sie ein Dockerfile mit folgendem Inhalt:

# Use a standard Linux base image
FROM ubuntu

# Install necessary dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    ca-certificates \
    zstd \
    && rm -rf /var/lib/apt/lists/*

# Install Ollama
# This uses Ollama's official installation script, which adds Ollama to /usr/local/bin
RUN curl -fsSL https://ollama.com/install.sh -o install.sh && \
    chmod +x install.sh && \
    ./install.sh && \
    rm install.sh

# Set environment variables for Ollama (optional, but a good practice)
# ENV OLLAMA_HOST="0.0.0.0"

# If you want to customize the model storage path within the container, set OLLAMA_MODELS, for example:
# ENV OLLAMA_MODELS="/usr/local/ollama/models"
# The default OLLAMA_MODELS is /root/.ollama
# Then, ensure you create and populate that directory.

# --- Download Gemma 3 model weights ---
# This step starts Ollama server in the background, pulls the model,
# and then kills the server to allow the Docker build to continue.
# This approach works around the Docker RUN command limitations for services.

RUN ollama serve & \
    # Give the Ollama server a moment to start up
    # Use --retry and --retry-connrefused to handle startup delays
    curl --retry 10 --retry-connrefused -s http://localhost:11434 || true && \
    # Pull the Gemma 3 model weights
    ollama pull gemma3:latest && \
    # Stop the background Ollama server process cleanly
    pkill ollama || true

# Expose Ollama's default port
EXPOSE 11434

# Command to run Ollama server when the container starts
CMD ["ollama", "serve"]

Wenn Sie ein anderes Open-Source-LLM ausprobieren möchten, z. B. ein Modell aus der Llama 3.2- oder DeepSeek-R1-Familie, ändern Sie diesen Ollama-Befehl im vorherigen Dockerfile:

ollama pull gemma3:latest

Wenn Sie beispielsweise Llama 3.2 mit 3 Milliarden Parametern abrufen möchten, verwenden Sie diesen Befehl:

ollama pull llama3.2:3b

Wenn Sie lieber DeepSeek-R1 mit 8 Milliarden Parametern verwenden möchten, verwenden Sie diesen Befehl:

ollama pull deepseek-r1:8b

Sie können auch mehrere LLMs herunterladen und die zugehörigen Modellgewichte in Containern speichern. Ollama kann dann zwischen Modellen wechseln, wenn Sie Inferenzanfragen für verschiedene vorab geladene Modelle stellen. Sie können beispielsweise sowohl Gemma- als auch Llama-Modelle in Ihr Docker-Image einfügen. In einer Air-Gap-Umgebung hat ein Ollama-Backend keinen Zugriff auf die Ollama-Bibliothek, um jederzeit ein Modell herunterzuladen.

Denken Sie daran, die Lizenz und die Nutzungsbedingungen jedes Modells zu prüfen und ihnen zuzustimmen, bevor Sie es in Ihren Anwendungen ausführen. In der Bibliothek von Ollama sind viele LLMs verfügbar. Sie benötigen nur eine Internetverbindung, um die Modellgewichte beim Erstellen des Docker-Images für das LLM-Backend herunterzuladen.

Docker-Image erstellen und per Push an Harbor übertragen

Melden Sie sich mit Docker bei Ihrer Harbor-Instanz an, wie in der Dokumentation beschrieben. Erstellen Sie das Gemma 3-Docker-Image und laden Sie es in Ihr Harbor-Repository hoch:

docker build -t ollama-gemma3 .
docker tag ollama-gemma3 HARBOR_URL/PROJECT/ollama-gemma3:latest
docker push HARBOR_URL/PROJECT/ollama-gemma3:latest

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.

Ollama-Version, die für diesen Bereitstellungsleitfaden verwendet wird: 0.14.1

Kubernetes-Deployment und -Dienst vorbereiten

Erstellen Sie eine Datei mit dem Namen ollama-gemma3.yaml, um die Bereitstellung des Ollama-Backends und die zugehörige Load-Balancer-Konfiguration zu definieren, damit es als Dienst verfügbar gemacht wird:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ollama-gemma3
  namespace: osd-dev
  labels:
    app: ollama-gemma3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ollama-gemma3
  template:
    metadata:
      labels:
        app: ollama-gemma3
    spec:
      containers:
      - name: ollama-gemma3
        image: rashjab-mhs-rashjab-test2.gdc1.us-west6-a.staging.gpcdemolabs.com/rashjab-repo/ollama-gemma3:latest
        env:
        # This is the crucial fix: Tell Ollama to listen on all network interfaces
        - name: OLLAMA_HOST
          value: "0.0.0.0"
        imagePullPolicy: Always
        ports:
        - containerPort: 11434
        securityContext:
          privileged: true
          runAsUser: 0
        resources:
          limits:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
          requests:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
      imagePullSecrets:
      - name: oss-llm-pull-secret
---
apiVersion: v1
kind: Service
metadata:
  name: ollama-gemma3
  namespace: osd-dev
spec:
  type: LoadBalancer
  selector:
    app: ollama-gemma3
  ports:
  - name: ollama-gemma3-port
    port: 11434
    protocol: TCP
    targetPort: 11434

Ersetzen Sie Folgendes:

  • HARBOR_URL: die URL der Harbor-Instanz.
  • PROJECT: der Name des Harbor-Projekts.
  • oss-llm-pull-secret: wenn Sie einen anderen Namen für das Image-Pull-Secret ausgewählt haben.

GPU-Zuweisung prüfen

GDC mit Air Gap unterstützt NVIDIA-GPUs mit mehreren Instanzen (Multi-Instance GPUs, MIGs). Die verschiedenen MIG-Profile können in der öffentlichen Dokumentation eingesehen werden. Wenn Sie kleine LLMs bereitstellen, sollten Sie ihre Größe (im Arbeitsspeicher) prüfen und Ihre GPUs entsprechend partitionieren. Das Partitionierungsschema für einen Knotenpool wird in der benutzerdefinierten Cluster-Ressource definiert. Weitere Informationen zum Anwenden eines GPU-Partitionierungsschemas finden Sie unter Knotenpool hinzufügen. Wenn Sie ein Application Operator (AO) sind, wenden Sie sich an Ihren Platform Administrator (PA), um Informationen zu den installierten und verfügbaren Beschleunigern in Ihrem Projekt / Cluster zu erhalten. Weitere Informationen zum Konfigurieren eines Containers für die Verwendung von GPU-Ressourcen und zum Prüfen der GPU-Ressourcenzuweisung

Die Standardgenauigkeit des Gemma 3-Modells mit 4 Milliarden Parametern ist 16 Bit. Gemäß dieser von Google veröffentlichten Tabelle beträgt der GPU-Arbeitsspeicherbedarf für dieses LLM 6,4 GB bei Verwendung von BF16-Präzision (16 Bit).

Im vorherigen ollama-gemma3.yaml haben wir dem Container einen 10 GB großen GPU-Slice (NVIDIA A100) zugewiesen, da dieser VRAM-Speicher ausreicht, um das Modell Gemma 3 4B zu laden und auszuführen, wie im Folgenden gezeigt:

ollama-gemma3.yaml

... omitted ...

        resources:
          limits:
            nvidia.com/mig-1g.10gb-NVIDIA_A100_80GB_PCIE: 1
          requests:
            nvidia.com/mig-1g.10gb-NVIDIA_A100_80GB_PCIE: 1

... omitted ...

Ollama-Backend bereitstellen und als Dienst verfügbar machen

Stellen Sie eine Verbindung zu Ihrem Cluster her und legen Sie den Kontext auf Ihren Projekt-Namespace fest:

# Log in to GDC air-gapped using the next commands

gdcloud auth login --login-config-cert {path to your web TLS certificate}

gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE

Wenden Sie das Ollama-Manifest an:

kubectl apply -f ollama-gemma3.yaml

Prüfen Sie, ob der Ollama-Pod ausgeführt wird und der zugehörige Dienst vorhanden ist:

kubectl get pods

Beispielausgabe:

# NAME                             READY   STATUS    RESTARTS   AGE
# ollama-gemma3-6fc6fff74b-9qtpf   1/1     Running   0          1h
kubectl get service

Beispielausgabe:

# NAME             TYPE          CLUSTER-IP    EXTERNAL-IP    PORT(S)          AGE
# ollama-gemma3   LoadBalancer  172.0.0.1     10.0.0.1       11434:31822/TCP  1d

Notieren Sie sich die EXTERNAL-IP des Ollama-Dienstes (z. B. 10.0.0.1) aus der vorherigen Ausgabe. Sie können es auch mit folgenden Optionen ausdrucken:

kubectl get service ollama-gemma3 \
-o jsonpath='{.status.loadBalancer.ingress[*].ip}'

Bevor Sie prüfen, ob Ollama Gemma 3 funktioniert, müssen Sie eine Netzwerkrichtlinie anwenden, z. B.:

apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
  name: allow-ollama-ingress
  namespace: osd-dev
spec:
  subject:
    subjectType: UserWorkload
  policyType: Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0 # Allows traffic from any IP. Restrict this for production.
    ports:
    - protocol: TCP
      port: 11434

Wenden Sie die Netzwerkrichtlinie an:

kubectl apply -f ollama-netpol.yaml

Ollama-Bereitstellung prüfen und testen:

  1. Prüfen Sie, ob Ollama ausgeführt wird:

    curl http://EXTERNAL_IP:11434
    

    Erwartete Antwort: „Ollama is running“ (Ollama wird ausgeführt)

  2. Vervollständigungsanfrage senden:

    curl -X POST http://EXTERNAL_IP:11434/v1/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "gemma3:latest",
        "prompt": "Google Distributed Cloud air-gapped is a",
        "max_tokens": 128,
        "temperature": 0.90
      }'
    

Schlussfolgerungen anfordern

Nachdem Ihre LLM-Backends (vLLM und Ollama) bereitgestellt wurden und über die jeweiligen LoadBalancer-Dienste erreichbar sind, können Sie sie für die Inferenz verwenden.

Je nach Anwendungsfall haben Sie mehrere Möglichkeiten:

  • Interaktive Weboberfläche: Für Tests, Prototypen oder um Nutzern eine ChatGPT-ähnliche Umgebung zu bieten, können Sie Open WebUI oder ein ähnliches Frontend bereitstellen.
  • Befehlszeile: Für die schnelle Überprüfung, das Scripting oder die Automatisierung können Sie curl oder benutzerdefinierte Scripts verwenden.
  • Anwendungsintegration: Sie können Ihre internen Anwendungen, KI-Agents oder IDE-Plug‑ins (z. B. Continue für VS Code/JetBrains) direkt mit den OpenAI-kompatiblen Endpunkten verbinden, die von vLLM (/v1) oder Ollama (/v1) bereitgestellt werden.

1. Über eine Benutzeroberfläche mit dem LLM interagieren

Wenn Sie eine ChatGPT-ähnliche Oberfläche für die Interaktion mit Ihren Modellen bereitstellen möchten, stellen Sie Open WebUI in Ihrem Cluster bereit.

Open WebUI-Deployment erstellen

open-webui-deployment.yaml erstellen:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: open-webui
  namespace: osd-dev
  labels:
    app: open-webui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: open-webui
  template:
    metadata:
      labels:
        app: open-webui
    spec:
      containers:
      - name: open-webui
        image: HARBOR_URL/PROJECT/open-webui:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
        env:
        - name: OPENAI_API_BASE_URL
          value: "http://gemma-3-4b-it/v1" # Point to your vLLM service
        - name: OPENAI_API_KEY
          value: "EMPTY"
        - name: WEBUI_AUTH
          value: "False"
      imagePullSecrets:
      - name: oss-llm-pull-secret
---
apiVersion: v1
kind: Service
metadata:
  name: open-webui
  namespace: osd-dev
spec:
  type: LoadBalancer
  selector:
    app: open-webui
  ports:
  - port: 80
    targetPort: 8080

Netzwerkrichtlinie anwenden

Sie müssen zulassen, dass Ihr Computer den Open WebUI-Dienst über Port 80 erreicht.

Aktualisieren Sie die PNP Project Network-Richtlinie, um den open-webui-Dienst einzuschließen, oder wenden Sie eine allgemeine Richtlinie an:

apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
  name: allow-webui-ingress
  namespace: NAMESPACE
spec:
  subject:
    subjectType: UserWorkload
  policyType: Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0 # Allows traffic from any IP then restrict this for production
    ports:
    - protocol: TCP
      port: 8080

Überprüfung

  1. Rufen Sie die WebUI-IP ab:

    kubectl get service open-webui -n NAMESPACE
    
  2. Auf die Benutzeroberfläche zugreifen: Öffnen Sie Ihren Browser und rufen Sie http://WEB_UI_EXTERNAL_IP auf.

  3. Konfigurieren: Erstellen Sie bei der ersten Anmeldung ein Administratorkonto. Prüfen Sie in den Einstellungen, ob der OpenAI-Verbindungspunkt auf http://gemma-3-4b-it/v1 verweist.

  4. Modell auswählen: Wählen Sie in der Chatoberfläche im Drop-down-Menü für das Modell google/gemma-3-4b-it aus.

    Öffnen Sie das Drop-down-Menü zur Auswahl des WebUI-Modells.

2. HTTP-Anfragen über eine Befehlszeile stellen

  • curl:
curl -X POST http://OLLAMA_LOAD_BALANCER_IP:11434/v1/completions \
-H "Content-Type: application/json" \
-d '{
  "model": "gemma3:latest",
  "prompt": "Google Distributed Cloud air-gapped is a",
  "max_tokens": 128,
  "temperature": 0.90
}'

Validierung und Überprüfung

Prüfen Sie, ob alle Container und Dienste ausgeführt werden:

# Log in to GDC air-gapped using the next commands

gdcloud auth login --login-config-cert {path to your web TLS cert}
gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE

# Pods

kubectl get pods # This command should return results like below

# NAME                                   READY   STATUS    RESTARTS   AGE
# vllm-6fc6fff74b-9qtpf                 1/1     Running   0          1h
# ollama-798fbf6ff6-9m7ln               1/1     Running   0          1h


# Services

kubectl get services # This command should return results like below

# NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)           AGE
# vllm-service              LoadBalancer   172.0.0.1        10.0.0.1       11434:31822/TCP   1h
# ollama-service        LoadBalancer   172.0.0.2        10.0.0.2       11434:30728/TCP   1h

Schritte zum Entfernen

  1. Entfernen Sie alle Kubernetes-Ressourcen:

    kubectl delete -f vllm-gemma-3-4b-it-deployment.yaml
    kubectl delete -f vllm-gemma-3-4b-it-service.yaml
    
  2. Löschen Sie nicht verwendete Container manuell aus Ihrem Harbor-Repository.

Vorgänge

vLLM-Backend

vLLM – Grundlagen

vLLM ist als leistungsstarke Engine für die Bereitstellung einzelner Modelle konzipiert. Es wird nicht unterstützt, mehrere Modelle in einem einzigen Serverprozess bereitzustellen oder mehrere Modelle in einem einzigen Startbefehl zu definieren. Wenn Sie mehr als ein Modell bereitstellen möchten (z. B. ein Chatmodell und ein separates Einbettungsmodell), müssen Sie separate vLLM-Instanzen starten, die sich jeweils in einem eigenen Pod oder Container befinden und optional verschiedenen GPUs oder GPU-Slices zugewiesen werden. Im Gegensatz zu anderen Backends, bei denen Modelle dynamisch getauscht werden können, wird bei einer vLLM-Instanz das Modell und der zugehörige KV-Cache-Speicher bei der Initialisierung fixiert, um einen gleichbleibend hohen Durchsatz und eine niedrige Latenz zu gewährleisten.

Mit den folgenden Befehlen können Sie ein Terminal auf einem der vLLM-Pods öffnen:

kubectl exec -it gemma-3-4b-random-string -n NAMESPACE -- /bin/bash

So sehen Sie, welche Modelle geladen sind, ihre Argumente und ihre PIDs :

ps aux | grep vllm

Erwartete ähnliche Ausgabe:

root           1  0.1  0.8 9436960 1550504 ?     Ssl  Feb04   9:18 python3 -m vllm.entrypoints.openai.api_server --model google/gemma-3-4b-it --max-model-len 32768 --enforce-eager
root         504  0.0  0.0   3476  1596 pts/0    S+   02:48   0:00 grep --color=auto vllm

Wenn Sie eine übersichtlichere, „Ollama-ähnliche“ Ansicht ohne die Unordnung des grep-Befehls selbst und der System-PIDs wünschen, können Sie diesen Einzeiler verwenden:

ps aux | grep [v]llm.entrypoints | awk -F'--model ' '{print $2}' | awk '{print $1}'

Beispielantwort :

google/gemma-3-4b-it

Sie können den Status Ihrer vLLM-Bereitstellung mit Standardbefehlen für kubectl und durch Abfragen der internen API-Endpunkte überwachen.

Pod-Logs prüfen

Öffnen Sie ein Terminal, um die Initialisierungs- und Bereitstellungsprotokolle aufzurufen:

kubectl logs -f gemma-3-4b-it-random_string -n NAMESPACE

Suchen Sie nach der Bestätigung, dass der Server bereit ist:

(APIServer pid=1) INFO:     Started server process [1]
(APIServer pid=1) INFO:     Waiting for application startup.
(APIServer pid=1) INFO:     Application startup complete.

Internen Status abfragen

Da vLLM eine OpenAI-kompatible API bereitstellt, können Sie die geladenen Modelle und den Systemzustand direkt über ein Terminal im Cluster prüfen, z. B. mit einem debug-sh-Pod.

Sie müssen zuerst den Debug-Pod starten. Hier finden Sie eine Anleitung :

Debug-Pod starten

Führen Sie den folgenden Befehl aus, um eine kurzlebige Shell in Ihrem Projekt-Namespace zu starten. Bei dieser Konfiguration wird das Busybox-Image verwendet (das zuvor in Ihre Harbor-Registry übertragen wurde) und die erforderlichen Anmeldedaten werden mit dem Flag --overrides eingefügt:

kubectl run --rm -it debug-sh \
  --image=HARBOR_URL/PROJECT/busybox:latest \
  --restart=Never -n osd-dev --overrides='{
    "spec": {
      "imagePullSecrets": [{"name": "oss-llm-pull-secret"}]
    }
  }' -- sh

Wichtige Parameter:

  • --rm: Löscht den Pod beim Beenden automatisch und schont so Clusterressourcen.
  • --overrides: In Umgebungen ohne Internetverbindung erforderlich, damit sich der Pod bei der privaten Harbor-Registry authentifizieren kann.

Serverstatus des Abfragemodells

Verwenden Sie im Pod das wget-Tool, um die vLLM API abzufragen. Da der vLLM-Dienst den internen Port 8000 dem Port 80 zuordnet, können Sie den DNS-Namen des Dienstes verwenden:

  • Geladene Modelle auflisten: Prüfen Sie, ob die vLLM-Engine erfolgreich initialisiert und die Gemma 3-Gewichte geladen wurden.

    wget -qO- http://gemma-3-4b-it/v1/models
    

    Erfolgreiche Antwort:

    {"object":"list","data":[{"id":"google/gemma-3-4b-it"}]}
    
  • Anwendungsstatus prüfen: Prüfen Sie, ob der API-Server bereit ist, Anfragen zu verarbeiten.

    wget -qO- http://gemma-3-4b-it/health
    

    Erfolgreiche Antwort:

    OK
    

Ollama – Grundlagen

Ollama unterstützt das gleichzeitige Laden mehrerer Modelle in den Arbeitsspeicher nicht. Wenn Sie das LLM für einen bestimmten Zeitraum (in der Regel standardmäßig 30 Minuten) nicht verwenden, entlädt Ollama das aktuelle Modell aus dem Arbeitsspeicher.

Aufgrund des oben beschriebenen Verhaltens werden in der Lösung je nach Bedarf und Anwendungsfall zwei oder mehr Ollama-Backends implementiert, sodass viele Entwickler oder Nutzer sie parallel verwenden können, ohne dass nur eine Ollama-Instanz Modelle häufig lädt und entlädt, was zu unnötiger Latenz führt.

Mit den folgenden Befehlen können Sie ein Terminal in einem der Ollama-Pods öffnen:

kubectl exec -it ollama-chat-random_string -- sh
kubectl exec -it ollama-autocomplete-random_string -- sh

In den Pods können Sie mit der Ollama-Befehlszeile die verfügbaren Modelle aufrufen und sehen, welches geladen ist:

  • Im ollama-chat-Pod finden Sie ein Modell:

    # ollama list
    NAME                     ID              SIZE      MODIFIED
    codegemma:7b-instruct    0c96700aaada    5.0 GB    2 hours ago
    
    # ollama ps
    NAME                     ID              SIZE     PROCESSOR    UNTIL
    codegemma:7b-instruct    0c96700aaada    10 GB    100% GPU     4 minutes from now
    
  • Im ollama-autocomplete-Pod finden Sie zwei Modelle:

    # ollama list
    NAME                     ID              SIZE      MODIFIED
    codegemma:2b             926331004170    1.6 GB    2 hours ago
    codegemma:7b-code        aee9a63c13b9    5.0 GB    2 hours ago
    
    # ollama ps
    NAME                 ID              SIZE      PROCESSOR    UNTIL
    codegemma:7b-code    aee9a63c13b9    7.1 GB    100% GPU     4 minutes from now
    
  • Wenn Ollama das aktuelle Modell entlädt, ist die Ausgabe leer:

    # ollama ps
    NAME    ID    SIZE    PROCESSOR    UNTIL
    

Ollama lädt ein Modell dynamisch wieder, wenn Sie die nächste Anfrage zur Codeunterstützung senden, ohne dass manuelle Eingriffe erforderlich sind.

Bedeutung der GPU-Kapazität

Wenn Sie einen GPU-Slice mit 10 GB bereitstellen, der Speicherbedarf des Modells aber (etwas) größer ist, wird ein Teil des LLM auf die CPU geladen, wie im Folgenden zu sehen ist:

# ollama ps
NAME                     ID              SIZE     PROCESSOR         UNTIL
codegemma:7b-instruct    0c96700aaada    10 GB    6%/94% CPU/GPU    29 minutes from now

Das ist nicht optimal und führt zu einer höheren Antwortlatenz. Achten Sie daher darauf, dass Sie die in diesem Leitfaden empfohlene GPU-Größe verwenden.

LLMs

Ein anderes oder Ihr bevorzugtes LLM mit vLLM verwenden

Wenn Sie verschiedene Größen von Gemma oder ein anderes Open-Source-LLM (Large Language Model) mit vLLM in einer GDC-Air-Gap-Umgebung ausführen möchten, z. B. DeepSeek-R1 oder Llama 3.1, müssen Sie die neuen Modellgewichte in Ihre Umgebung aufnehmen und das Bereitstellungsmanifest so aktualisieren, dass es auf die neuen Assets verweist.

Folgen Sie den für diese Lösung festgelegten Betriebsverfahren, um ein anderes Modell zu laden :

  1. Neue Modellgewichte herunterladen:

    Verwenden Sie auf einer Workstation mit Internetzugang die Hugging Face CLI, um die Gewichte für Ihr bevorzugtes Modell herunterzuladen.

    • Für Gemma 3 (3-12b-it):
    hf download google/gemma-3-12b-it
    
    • Für DeepSeek-R1 (7B Distill):
    hf download deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
    
    • Für Llama 3.1 (8B):
    hf download meta-llama/Meta-Llama-3.1-8B-Instruct
    

    Hinweis: Achten Sie darauf, dass Sie die Lizenzbedingungen des Modells auf Hugging Face akzeptiert haben, bevor Sie es herunterladen.

  2. Füllen Sie das persistente Volume (PVC) auf:

    Aktualisieren Sie Ihr vorhandenes model-pvc oder erstellen Sie ein neues mit ausreichend Kapazität für das neue Modell. Verwenden Sie die Methode mit dem Hilfspod, um die Gewichte von Ihrer Workstation zu übertragen. Größere Formfaktoren erfordern deutlich mehr Speicherplatz. Achten Sie darauf, dass Ihr Persistent Volume Claim (PVC) genügend Kapazität zum Speichern der neuen Gewichte hat.

    • Gemma 3 4B: ca.15,2 GB.
    • Gemma 3 27B: ca. 54 GB+.
    • Empfehlung: Behalten Sie die PVC-Empfehlung von 500 GiB bei, um unabhängig von der Modellgröße hohe IOPS (1.500) für ein schnelleres Laden zu gewährleisten.
    # Copy the new model's hub directory to the helper pod
    kubectl cp ~/.cache/huggingface/hub/ osd-dev/model-uploader:/data/
    
  3. Aktualisieren Sie das vLLM-Deployment-Manifest:

    Ändern Sie die YAML-Datei für die vLLM-Bereitstellung so, dass sie auf die neue Modell-ID verweist. Im Gegensatz zu Ollama, wo Modelle dynamisch ausgetauscht werden können, ist eine vLLM-Instanz einem einzelnen Modell zugeordnet und muss aktualisiert oder neu bereitgestellt werden, um das Modell zu ändern.

    Aktualisieren Sie den Abschnitt „args“ Ihrer Bereitstellung je nach verwendetem Modell. Hier ist DeepSeek als Beispiel angegeben:

    args: [
      "-m", "vllm.entrypoints.openai.api_server",
      "--model", "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B", # Update to new Repo ID
      "--max-model-len", "32768",
      "--enforce-eager" # Recommended for GDC stability
    ]
    
  4. GPU- und Arbeitsspeicherressourcen anpassen:

    Größere Modelle benötigen mehr VRAM für Gewichte und den KV-Cache. Wenn Sie von einem 4B-Modell zu einem 8B- oder 14B-Modell wechseln, müssen Sie darauf achten, dass Ihre Ressourcenlimits ausreichen, um „Out of Memory“-Abstürze zu vermeiden.

    • VRAM-Speicherbedarf: Bei 16‑Bit-Präzision benötigt ein 8B-Modell allein für die Gewichte etwa 16 GB, zuzüglich zusätzlichem Speicher für den vLLM-PagedAttention-Cache.
    • Empfehlung: Verwenden Sie eine vollständige A100-GPU (nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1) für Modelle mit mehr als 7 Milliarden Parametern, um eine optimale Leistung und ausreichend Spielraum für den KV-Cache zu gewährleisten.
  5. Neues Modell bestätigen:

    Nachdem die Bereitstellung abgeschlossen ist, prüfen Sie mit der internen API, ob das neue Modell aktiv ist:

    # Inside a debug-sh pod
    wget -qO- http://gemma-3-4b-it/v1/models
    

    Erfolgreiche Antwort:

    {"object":"list","data":[{"id":"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B"}]}
    

Anderes LLM mit Ollama verwenden

Wenn Sie ein anderes Open-Source-LLM ausprobieren möchten, z. B. ein Modell aus der Llama 3.2- oder DeepSeek-R1-Familie, ändern Sie diesen Ollama-Befehl im vorherigen Dockerfile:

ollama pull gemma3:latest

Wenn Sie beispielsweise Llama 3.2 mit 3 Milliarden Parametern abrufen möchten, verwenden Sie diesen Befehl:

ollama pull llama3.2:3b

Wenn Sie lieber DeepSeek-R1 mit 8 Milliarden Parametern verwenden möchten, verwenden Sie diesen Befehl:

ollama pull deepseek-r1:8b

Sie können auch mehrere LLMs herunterladen und die zugehörigen Modellgewichte in Containern speichern. Ollama kann dann zwischen Modellen wechseln, wenn Sie Inferenzanfragen für verschiedene vorab geladene Modelle stellen. Sie können beispielsweise sowohl Gemma- als auch Llama-Modelle in Ihr Docker-Image einfügen. In einer Air-Gap-Umgebung hat ein Ollama-Backend keinen Zugriff auf die Ollama-Bibliothek, um jederzeit ein Modell herunterzuladen.

Denken Sie daran, die Lizenz und die Nutzungsbedingungen jedes Modells zu prüfen und ihnen zuzustimmen, bevor Sie es in Ihren Anwendungen ausführen. In der Bibliothek von Ollama sind viele LLMs verfügbar. Sie benötigen nur eine Internetverbindung, um die Modellgewichte beim Erstellen des Docker-Images für das LLM-Backend herunterzuladen.

WebUI öffnen

Prüfen Sie, ob sich der Open WebUI-Pod im Status „Wird ausgeführt“ befindet :

kubectl get pods -n NAMESPACE

Erwartete Ausgabe :

NAME                             READY   STATUS    RESTARTS   AGE
open-webui-69df4664d-przjl       1/1     Running   0          6d3h

Prüfen Sie die Dienst-IP :

kubectl get service -n NAMESPACE

Erwartete Ausgabe:

NAME          TYPE            CLUSTER-IP       EXTERNAL-IP      PORT(S)           AGE
open-webui     LoadBalancer   10.201.137.164   136.125.37.224   80:30492/TCP      6d3h

In den folgenden Abschnitten wird beschrieben, wie Sie die wichtigsten UI-Funktionen verwenden.

Diagramm der WebUI-Benutzeroberfläche öffnen

Lösung mit einem Ollama-Backend skalieren

Vertikal

  • Weisen Sie Ihrem LLM, das zum Engpass geworden ist, einen größeren GPU-Slice zu, bis Sie eine vollständige GPU verwenden.
  • Wenn Sie ein größeres LLM für eine bessere Antwortgenauigkeit verwenden möchten, z. B. ein LLM mit 405 Milliarden Parametern anstelle eines mit 7 Milliarden, benötigen Sie möglicherweise mehr als eine GPU, um es reibungslos auszuführen.
  • Bei Modellen, die auf mehr als eine GPU passen, kann es zu Latenz aufgrund der GPU-übergreifenden Kommunikation kommen.

Horizontal

  • Stellen Sie so viele Ollama-Pods bereit, wie Sie für den gewünschten Durchsatz für ein bestimmtes LLM benötigen.
    • Erhöhen Sie dazu die replica-Anzahl in der entsprechenden YAML-Datei für die Ollama-Bereitstellung.
  • Der Kubernetes-Dienst vom Typ LoadBalancer verteilt Anfragen zur Codeunterstützung zwischen Endpunkten (d.h. Pods) und gibt die entsprechenden Antworten über die bereitgestellte externe IP-Adresse zurück.
  • Das Continue-Plug-in verweist nur auf eine IP-Adresse pro Funktion.

Architekturdiagramm für die Skalierung von LLMs mit offenem Gewicht.

Um das vLLM-Backend in Ihrer GDC-Air-Gap-Umgebung zu skalieren, können Sie eine ähnliche Strategie wie für Ollama verwenden, die sich sowohl auf die Zuweisung von Hardwareressourcen als auch auf die Pod-Replikation konzentriert.

Lösung mit einem vLLM-Backend skalieren

Vertikal

  • GPU-Zuweisung upgraden:Wenn der Inferenzdurchsatz (Tokens/Sekunde) zu einem Engpass wird, weisen Sie einen größeren GPU-Slice zu, bis Sie eine vollständige NVIDIA A100-GPU verwenden.
  • Konfigurationen mit mehreren GPUs: Bei umfangreichen Modellen (z. B. mit 70 Mrd. bis 405 Mrd. Parametern), die nicht in den Arbeitsspeicher einer einzelnen A100-GPU mit 80 GB passen, müssen Sie mit Tensor-Parallelität auf mehrere GPUs skalieren.
  • Latenz: Bei Modellen, die sich über mehrere GPUs erstrecken, kann es zu einem leichten Mehraufwand im Zusammenhang mit der GPU-übergreifenden Kommunikation kommen (z. B. NCCL-Synchronisierung).

Horizontal

  • Durchsatz über Replikate erhöhen: Wenn Sie eine höhere Anzahl gleichzeitiger Nutzeranfragen für dasselbe Modell verarbeiten möchten, erhöhen Sie die Anzahl von replicas in der YAML-Datei für die vLLM-Bereitstellung.
  • Dedizierte Modellinstanzen: Da vLLM als Serving-Engine für ein einzelnes Modell konzipiert ist und den KV-Cache-Speicher bei der Initialisierung festlegt, müssen Sie für jedes LLM, das Sie hosten möchten, eine separate Gruppe von Pods bereitstellen.
  • Lastenausgleich: Der GDC Kubernetes-Dienst (Typ LoadBalancer) verteilt eingehende Inferenzanfragen automatisch auf alle fehlerfreien vLLM-Pod-Endpunkte, die diesem Dienst zugeordnet sind.

Fehlerbehebung

Fehler Problembehebung
FIPS-SELBSTTEST FEHLGESCHLAGEN Tritt auf, wenn Bibliotheken wie BoringSSL keine Integritätssignaturen haben. Fehler beheben, indem Sie BORINGSSL_FIPS=0 festlegen und offizielle vLLM-Images verwenden
Gewichtsladen fehlgeschlagen Prüfen Sie, ob bei kleinen PVCs IOPS-Drosselung auftritt. Für die Initialisierung des Leistungsmodells ist ein Volume mit 500 GiB erforderlich.
Verbindung verweigert Prüfen Sie, ob der PNP den targetPort (8000/8080) explizit zulässt. GDC-Firewalls gewähren nicht automatisch Zugriff auf Back-End-Ports für Load-Balancer-VIPs.