Verwenden Sie den verteilten Beschleuniger für Cloud-Speicher mit Run:ai Model Streamer (Vorschau)

Run:ai Model Streamer liest Modelltensoren gleichzeitig und streamt sie in den GPU-Speicher, wobei Speicherlesungen mit CPU-zu-GPU-Übertragungen überlappen. Diese Funktion kann die Ladezeit des Modells verkürzen und die Leerlaufzeit der GPU beim Start und Skalieren des Inferenzservers reduzieren. Nutzen Sie sie, um SafeTensors-Modelle aus Azure Blob Storage mit vLLM zu laden, da sie direktes Laden aus dem Objektspeicher unterstützt und sich in den Modell-Loader von vLLM integriert. Für die Upstream-Integration siehe Loading models with Run:ai Model Streamer.

Durch die Verwendung verteilter Beschleunigung für Cloud-Speicher (DACS) kann dieser Ladepfad auch Modelldaten wiederverwenden, die über Workloads hinweg zwischengespeichert sind. vLLM verwendet das Azure-Backend von Run:ai, um die native DACS-Client-Bibliothek zu laden. Reads rufen zwischengespeicherte Daten ab oder holen fehlende Daten aus Blob Storage.

Dieser Artikel verwendet Run:ai Model Streamer 0.17.0, das öffentliche dacs-client==0.1.0 Paket und den v0.1.0 Server-Build. Die Hauptprozedur installiert die Abhängigkeiten in deinem Workload-Image. Es erfordert kein separates DACS-Client-Image oder Unterstützung für Kubernetes ImageVolume.

Schließen Sie Erste Schritte mit dem verteilten Beschleuniger für Cloudspeicher auf AKS ab, bevor Sie diesen Artikel lesen. Um die DACS-Clientbibliotheken bereitzustellen, ohne Ihr Workload-Image neu zusammenzustellen, finden Sie weitere Informationen unter DACS-Clientbibliotheken mit ImageVolume einbinden.

Prerequisites

  • Eine bestehende DACS-Bereitstellung und deren Discovery-Service-Hostname.
  • Ein AKS-GPU-Node-Pool mit kompatiblen NVIDIA-Treibern, einem Geräte-Plugin und genügend GPU-Speicher für dein Modell. Das folgende Beispiel verwendet bfloat16, was eine kompatible GPU erfordert.
  • Für die Authentifizierung der Arbeitslast-Identität ein AKS-Cluster mit aktiviertem OIDC-Aussteller und aktivierter Microsoft Entra Workload ID. Siehe OIDC-Aussteller und Microsoft Entra Workload ID in einem AKS-Cluster aktivieren.
  • Ein kompatibles GPU-vLLM-Image und eine Linux-Umgebung mit glibc 2.35 oder neuer. Verwende dieselbe Python-Umgebung wie deine Anwendung.
  • Ein privater Blob-Container für Modelldateien.
  • Ein separater Uploader-Benutzer oder eine verwaltete Identität mit Storage Blob Data Contributor für den Modellcontainer.
  • Eine Inferenzidentität mit Storage Blob Data Reader für den Modellcontainer. Konfigurieren Sie eine Methode für Blob-Authentifizierung konfigurieren.
  • Erlaubnis, dein Workload-Image zu erstellen und zu pushen, und Erlaubnis, dass AKS es abrufen darf.
  • Azure CLI, AzCopy v10 und die Hugging Face CLI werden auf deinem Vorbereitungsrechner benötigt, falls du ein Modell hochladen musst.

Für die Modellvorbereitung ist keine GPU erforderlich. Sie können auch die Paketinstallation, das Laden der nativen Bibliotheken und die Blob-Authentifizierung an CPU-Knoten mit einem kompatiblen Anwendungsimage überprüfen. Diese Prüfungen validieren weder GPU-Planung, Speichergröße noch Inferenz.

Laden Sie Modelldateien in Blob Storage hoch

Überspringen Sie diesen Abschnitt, wenn das komplette Modell bereits in Ihrem privaten Container ist. Für einen Cold-Cache-Test verwenden Sie ein Modellpräfix, das Sie nicht über DACS gelesen haben.

Verwenden Sie für dieses Verfahren die Uploader-Identität, nicht die Inferenz-Identität. Für Rollenzuweisungen auf Containerebene siehe Zuweisen einer Azure-Rolle für den Zugriff auf Blobdaten. Azure Control Plane Owner oder Contributor allein gewährt keinen Datenzugriff auf Blob über Microsoft Entra ID.

Laden Sie das Modell herunter

Das folgende Beispiel lädt die Inferencedateien für SmolLM2-135M-Instruct bei einer festen Revision herunter. Seine Modellkarte kennzeichnet die Lizenz als Apache-2.0. Installieren Sie die Hugging Face CLI und führen Sie dann aus:

MODEL_ID="HuggingFaceTB/SmolLM2-135M-Instruct"
MODEL_REVISION="12fd25f77366fa6b3b4b768ec3050bf629380bac"
MODEL_DIR="$PWD/models/SmolLM2-135M-Instruct-$MODEL_REVISION"

hf download "$MODEL_ID" \
  config.json generation_config.json model.safetensors \
  tokenizer.json tokenizer_config.json special_tokens_map.json \
  vocab.json merges.txt README.md \
  --revision "$MODEL_REVISION" \
  --local-dir "$MODEL_DIR"

Verwenden Sie optional den hf cache verify Befehl einer aktuellen CLI, um die heruntergeladenen Dateien mit Hub-Prüfsummen zu überprüfen:

hf cache verify "$MODEL_ID" \
  --revision "$MODEL_REVISION" \
  --local-dir "$MODEL_DIR"

Da dieser Download nur Inferenzdateien auswählt, kann die Verifikation fehlende Repository-Dateien wie ungenutzte Modellvarianten melden. Es kann auch zusätzliche lokale Metadaten zu Hugging-Face-Downloads melden. Diese Meldungen sind keine Prüfsummenfehler. Untersuchen Sie unerwartete Dateien oder Prüfsummenabweichungen, bevor Sie sie hochladen.

Für ein weiteres Modell sollten alle SafeTensors-Shards sowie alle Gewichtungsindexe, Modell- und Generationskonfigurationen, Tokenizer-Dateien sowie zutreffende Lizenz- und Attributionsdateien aufgenommen werden. Bewahren Sie die erforderliche Verzeichnisstruktur bei. Stagen Sie keine nicht zugehörigen ONNX-Varianten, Trainingscheckpoints, Optimiererdateien oder Zugangsdaten.

Mit AzCopy hochladen

Installiere AzCopy v10. Melde dich über die Azure CLI als der Benutzer an, der den Upload ausführt, und kopiere dann den Inhalt des lokalen Verzeichnisses in ein neues Blobpräfix:

TENANT_ID="<tenant-id>"
STORAGE_ACCOUNT="<storage-account>"
CONTAINER="<container>"
RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)"
MODEL_PREFIX="models/SmolLM2-135M-Instruct-${MODEL_REVISION}-${RUN_ID}"
MODEL_URL="https://${STORAGE_ACCOUNT}.blob.core.windows.net/${CONTAINER}/${MODEL_PREFIX}"

az login --tenant "$TENANT_ID"
export AZCOPY_AUTO_LOGIN_TYPE=AZCLI
export AZCOPY_TENANT_ID="$TENANT_ID"

azcopy copy "$MODEL_DIR/*" "$MODEL_URL" \
  --recursive=true \
  --overwrite=false \
  --exclude-path ".cache;.git"

azcopy list "$MODEL_URL"

Die in Anführungszeichen gesetzte Wildcard kopiert den Inhalt des Verzeichnisses direkt in das Präfix, ohne eine Ebene des lokalen Verzeichnisses hinzuzufügen. Die Ausschlüsse schließen Download- und Git-Metadaten aus. Fahren Sie nur fort, wenn AzCopy keine fehlgeschlagenen Übertragungen mehr meldet und das Ziel alle erforderlichen Dateien enthält. Weitere Informationen finden Sie unter Inhalte eines Verzeichnisses mit AzCopy hochladen und AzCopy mit der Azure CLI autorisieren.

Bei einem Uploader, der auf einer Azure-VM ausgeführt wird, können Sie AzCopy stattdessen mit einer verwalteten Identität autorisieren. Belasse den Container privat und entferne temporäre Uploader-Rollenzuweisungen nach Abschluss der Vorbereitungen. Geben Sie neuen Rollenzuweisungen Zeit, wirksam zu werden; umgehen Sie Autorisierungsfehler nicht, indem Sie Speicherschlüssel oder Clientgeheimnisse hinzufügen.

Dokumentieren Sie die Modellrevision und die Blob-Versionen oder ETags. Der Standort des Run:ai-Modells ist az://<container>/<model-prefix>. Lassen Sie diese Dateien bei Kalt- und Warmstarts unverändert. Für einen weiteren Kalttest verwenden Sie ein weiteres neues Präfix, anstatt Daten aus einem gemeinsamen Cache zu entfernen.

Bereite das Workload-Image ohne ImageVolume vor

Installiere Abhängigkeiten während der Erstellung deines Images, nicht beim Start des Pods. Behalten Sie Ihre bestehende Anwendung, Ihr Basisimage und Ihren Entrypoint. Verwenden Sie den Paketmanager der Anwendung sowie den Requirements-/Constraints-Workflow, um kompatible Abhängigkeiten wie Torch, CUDA und NumPy zu erhalten.

Verwende ein GPU-fähiges vLLM-Image mit Torch- und CUDA-Versionen, die mit deinen GPU-Nodes und NVIDIA-Treibern kompatibel sind. Überprüfen Sie die installierten Run:ai-Core- und Azure-Backend-Pakete des Images, bevor Sie Abhängigkeiten hinzufügen; nicht jedes vLLM-Image enthält das Azure-Backend.

Lösen Sie Abhängigkeitskonflikte in Ihrem Workload-Image vor der Bereitstellung. Der Schritt pip check im folgenden Abschnitt muss erfolgreich abgeschlossen werden. Nutzen Sie die Abhängigkeitsbeschränkungen Ihrer Anwendung, um die Kompatibilität mit anderen installierten Paketen zu erhalten.

  1. Wenn dein Image noch keine kompatiblen Run:ai Core- und Azure-Backend-Pakete enthält, füge folgende Anweisung deiner Dockerfile hinzu:

    RUN python3 -m pip install --no-cache-dir "runai-model-streamer[azure]==0.17.0"
    
  2. Installiere das öffentliche DACS-Clientpaket, das die nativen Client-Bibliotheken bereitstellt, in derselben Python-Umgebung:

    RUN python3 -m pip install --no-cache-dir "dacs-client==0.1.0" && \
        python3 -m pip check
    

    Run:ai's Azure Extra installiert die DACS-Clientbibliotheken nicht. Wenn Ihre Anwendung bereits kompatible Run:ai-Pakete hat, wird nur die Installation des DACS-Client-Pakets benötigt.

  3. Baue und pushe mit deiner bestehenden Dockerfile und dem Build-Kontext. Führe die folgenden Befehle in Bash auf deiner Vorbereitungsmaschine aus. Dieses Beispiel wird für x86-64-Knoten erstellt:

    REGISTRY_NAME="<registry-name>"
    REGISTRY_SERVER="$(az acr show --name "$REGISTRY_NAME" --query loginServer --output tsv)"
    WORKLOAD_IMAGE="$REGISTRY_SERVER/workload-runai-dacs:0.17.0-0.1.0"
    
    az acr login --name "$REGISTRY_NAME"
    docker build --platform linux/amd64 -t "$WORKLOAD_IMAGE" .
    docker push "$WORKLOAD_IMAGE"
    
  4. In derselben Bash-Sitzung löst man den nativen Bibliothekspfad aus dem erstellten Image auf:

    docker run --rm --entrypoint python3 "$WORKLOAD_IMAGE" \
      -c 'from importlib.metadata import distribution; from pathlib import Path; p=Path(distribution("dacs-client").locate_file("py_dacs_client/libStorageDirect.so")).resolve(); assert p.is_file(), p; print(p)'
    

    Verwenden Sie den gedruckten absoluten Pfad bei der Konfiguration des Workloads. Behalte die komplette Client-Installation aufrecht, einschließlich der zugehörigen nativen Bibliotheken.

Bevorzugen Sie beim Bereitstellen einen unveränderlichen Image-Digest. Das Aktualisieren des eingebauten Clients erfordert den Neuaufbau und die erneute Bereitstellung des Workload-Images.

Blob-Authentifizierung konfigurieren

Verwenden Sie die Workload-Identität von AKS für die Blob-Authentifizierung. Das Bereitstellungsbeispiel verwendet diese Methode mit Storage Blob Data Reader, der auf den Modellcontainer abgegrenzt ist. Die Schreibberechtigung des Uploaders ist für die Inferenz nicht erforderlich. Für andere Authentifizierungsmethoden siehe Azure-Authentifizierung in der Run:ai Model Streamer-Dokumentation.

Verwenden Sie die AKS-Workload-Identität

Das Bereitstellungsbeispiel verwendet den runai-reader ServiceAccount im Namensraum runai-dacs . Führen Sie die folgenden Schritte aus, bevor Sie den Workload bereitstellen:

  1. Aktivieren Sie den OIDC-Issuer und die Microsoft Entra Workload ID auf Ihrem bestehenden AKS-Cluster, falls diese noch nicht aktiviert sind.

  2. Rufen Sie die URL des OIDC-Herausgebers ab.

  3. Erstelle eine verwaltete Identität oder wähle eine bestehende Identität aus.

  4. Wenn der Namensraum runai-dacs noch nicht existiert, erstelle ihn.

    kubectl create namespace runai-dacs
    
  5. Erstellen Sie ein Kubernetes ServiceAccount, das mit der Client-ID dieser Identität annotiert ist.

  6. Erstellen der föderierten Identitätsanmeldeinformationen für den genauen Namespace und ServiceAccount. Du musst die folgenden Key Vault-Schritte nicht abschließen.

Weisen Sie der verwalteten Identität, die mit Ihrer Anwendung ServiceAccount federiert ist, die Blob-Leserrolle zu. Für ein Beispiel für eine container-scoped Zuweisung siehe Grant Read Access to Model Data, wobei diese Identität anstelle der kubelet-Identität des Quickstarts verwendet wird.

Der Pod muss das ServiceAccount verwenden und das Label azure.workload.identity/use: "true" haben. AKS fügt die Identitätseinstellungen und das projizierte Token ein. Füge Clientgeheimnisse oder Speicherkontoschlüssel nicht manuell hinzu.

Konfigurieren Sie den Image-Pull-Zugriff separat

Für private ACR-Images konfigurieren Sie die Pull-Berechtigungen der Kubelet-Identität wie in Den Client zu einem Workload-Image hinzufügen beschrieben. Verwenden Sie AcrPull für klassisches RBAC. Für eine ABAC-fähige Registry verwenden Sie Container Registry Repository Reader mit entsprechendem Repository-Zugriff. Nutze --attach-acr nicht für diese Registrierung.

Blob-Read-Zugriff auf die Identität der Anwendung gewährt dem Kubelet keinen Image-Pull-Zugriff. Für ImageVolume muss der Pull-Zugriff sowohl die Arbeitslast als auch die Client-Images abdecken, einschließlich separater Registries oder Repositories, sofern zutreffend.

Konfigurieren und stellen Sie den Workload bereit

Legen Sie diese vier Applikationsvariablen fest, bevor Sie vLLM starten. Sie sind getrennt von den Identitätseinstellungen, die von Ihrer Authentifizierungsmethode bereitgestellt werden:

Umgebungsvariable Purpose
AZURE_STORAGE_ACCOUNT_NAME Speicherkonto, das das Modell enthält.
CACHE_DISCOVERY_URL DACS-Discovery-Hostname, wie zum Beispiel cache-sample-discovery.<namespace>.svc.cluster.local.
CACHE_SERVER_PORT Cache-Port, typischerweise 9065.
RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB Der absolute Pfad der nativen Bibliothek wurde aus deinem Workload-Image ermittelt.

Important

Cache-Entdeckung ist nicht optional. Ein Modell kann erfolgreich geladen werden, indem Blob Storage direkt gelesen wird, wenn der Cache nicht konfiguriert ist. Mit dem Run:ai-Azure-Backend 0.17.0, spezifizieren Sie auch explizit den nativen Bibliothekspfad, anstatt auf automatische Entdeckung zu setzen.

Verwenden Sie das Modell-URI-Format von Run:ai, az://<container>/<model-prefix>, wobei das Konto über AZURE_STORAGE_ACCOUNT_NAME bereitgestellt wird. Dieses URI-Format unterscheidet sich von der kanonischen URI des nativen Python-Clients, die den Konto-Hostnamen enthält.

Ersetzen Sie die Platzhalter im folgenden Beispiel und speichern Sie es als runai-dacs-pod.yaml. Verwenden Sie das Modellpräfix aus Ihrem Upload und den nativen Bibliothekspfad, der vom erstellten Image ausgegeben wird. Das Beispiel verwendet Workload-Identität und enthält kein ImageVolume oder Init-Container:

apiVersion: v1
kind: Pod
metadata:
  name: runai-dacs-vllm
  namespace: runai-dacs
  labels:
    azure.workload.identity/use: "true"
spec:
  serviceAccountName: runai-reader
  restartPolicy: Never
  nodeSelector:
    agentpool: "<gpu-nodepool-name>"
  tolerations:
    - key: nvidia.com/gpu
      operator: Exists
      effect: NoSchedule
  containers:
    - name: vllm
      image: "<workload-image>"
      command: ["vllm", "serve"]
      args:
        - "az://<container>/<model-prefix>"
        - "--load-format"
        - "runai_streamer"
        - "--served-model-name"
        - "cached-model"
        - "--dtype"
        - "bfloat16"
        - "--max-model-len"
        - "1024"
      env:
        - name: AZURE_STORAGE_ACCOUNT_NAME
          value: "<storage-account>"
        - name: CACHE_DISCOVERY_URL
          value: "<cache-discovery-hostname>"
        - name: CACHE_SERVER_PORT
          value: "9065"
        - name: RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB
          value: "<dacs-native-library-path>"
        - name: RUNAI_STREAMER_CHUNK_BYTESIZE
          value: "8388608"
        - name: SI_streamingChunkSize
          value: "8388608"
      resources:
        requests:
          cpu: "4"
          memory: 16Gi
        limits:
          cpu: "4"
          memory: 16Gi
          nvidia.com/gpu: 1
      ports:
        - containerPort: 8000
      readinessProbe:
        httpGet:
          path: /health
          port: 8000
        periodSeconds: 10
        timeoutSeconds: 5
      volumeMounts:
        - name: shm
          mountPath: /dev/shm
  volumes:
    - name: shm
      emptyDir:
        medium: Memory
        sizeLimit: 2Gi

Diese Ressourcen zeigen ein kleines Modell, kein 30B-Modell. Bewahren Sie die erforderliche Zeitplanung, Ressourcen, Probes, geteilten Speicher und andere vLLM-Argumente Ihrer Arbeitslast. Passe GPU-Anzahl, Tensorparallelität, Modelllänge und Speichergröße für dein Modell an. Für eine Deployment oder StatefulSet wenden Sie Pod-Labels unter spec.template.metadata und Pod-Einstellungen unter spec.template.spec.

Die erste Bereitstellung startet vLLM und lädt das Modell, bevor der Pod bereit ist. Für einen Cold-Cache-Vergleich führen Sie diese Schritte in der Reihenfolge durch:

  1. Wählen Sie Modelldaten aus, die der Cache nicht gelesen hat, wie zum Beispiel das neue Präfix aus der Upload-Prozedur. Verdrängen Sie keine Daten aus einem gemeinsam genutzten Cache.

  2. Vor der Bereitstellung des Anwendungs-Pods erfassen Sie einen Basis-Metrik-Snapshot von jedem Cache-Server-Pod, wie in Monitor distributed accelerator for cloud storage beschrieben. Zeichnen Sie den Zeitstempel sowie cache_server_download_request_size_bytes_sum, cache_server_cache_size_bytes und cache_server_upload_request_size_bytes_sum jedes Servers auf.

  3. Stellen Sie den akzeptierten Pod bereit und inspizieren Sie ihn:

    kubectl apply --dry-run=server -f runai-dacs-pod.yaml
    kubectl apply -f runai-dacs-pod.yaml
    kubectl -n runai-dacs get pod runai-dacs-vllm -o yaml
    kubectl -n runai-dacs wait --for=condition=Ready pod/runai-dacs-vllm --timeout=30m
    

Überprüfen Sie die Workload-Laufzeit

Führen Sie diese Prüfung im vLLM-Anwendungscontainer mit der Python-ausführbaren Datei der Anwendung aus. Es überprüft die Paketkonsistenz und das Laden der nativen Bibliotheken, nicht die Blob-Authentifizierung oder die Cache-Nutzung:

kubectl -n runai-dacs exec -i runai-dacs-vllm -c vllm -- python3 - <<'PY'
import ctypes
import os
import subprocess
import sys
from importlib.metadata import version

for package in (
    "vllm",
    "torch",
    "runai-model-streamer",
    "runai-model-streamer-azure",
):
    print(f"{package}: {version(package)}", flush=True)

subprocess.run([sys.executable, "-m", "pip", "check"], check=True)

path = os.environ["RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB"]
print(f"Checking DACS native library: {path}", flush=True)
library = ctypes.CDLL(path)
print(f"DACS native library loaded: {path}")
PY

Beheben Sie Fehler, bevor Sie fortfahren. Für die GPU-Bereitstellung sollten Sie außerdem die GPU-Sichtbarkeit und die vLLM-Engine-Logs überprüfen, um die CUDA-Ausführung und den vorgesehenen Modell-Dtyp zu bestätigen. Bereitschaft oder das erfolgreiche Laden einer Bibliothek allein beweisen weder die GPU-Ausführung noch die Nutzung des DACS-Caches.

Überprüfen Sie das Verhalten des kalten und warmen Caches

Verwenden Sie die vor der Bereitstellung erfasste Baseline aus Configure and deploy the workload. Der während der Bereitstellung durchgeführte Modellladevorgang ist der Kaltladevorgang.

Überprüfen Sie die Kaltlast

Überprüfen Sie das Anwendungsprotokoll:

kubectl -n runai-dacs logs runai-dacs-vllm -c vllm

Suchen Sie nach nativ ReadChunk stats. RemoteClient zählt Reads des Backing-Store-Gewichts; RemoteCache zählt Remote-Cache-Reads. Einige Cache-Hits während des ersten Ladens sind normal, da frühere Reads Daten füllen können. GetProperties Cache-Hits beschreiben Metadaten, keine Treffer auf Modellgewichte.

Senden Sie eine Schlussanfrage:

kubectl -n runai-dacs exec -i runai-dacs-vllm -c vllm -- python3 - <<'PY'
import json
import urllib.request

body = json.dumps({
    "model": "cached-model",
    "prompt": "Once upon a time",
    "max_tokens": 16,
    "temperature": 0,
}).encode()
request = urllib.request.Request(
    "http://127.0.0.1:8000/v1/completions", data=body,
    headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request, timeout=600) as response:
    result = json.load(response)
print(json.dumps(result, indent=2))
assert result["choices"][0]["text"].strip()
assert result["usage"]["completion_tokens"] > 0
PY

Bestätigen Sie nicht-null Cold Backing-Store-Lesungen. Lassen Sie den Anwendungspod laufen, während Sie die asynchrone Cache-Population überprüfen:

  1. Erfassen Sie alle 10 Sekunden cache_server_upload_request_size_bytes_sum und cache_server_cache_size_bytes Messwerte von jedem Cache-Server-Pod für die ausgewählte Cache-Ressource, bis zu fünf Minuten lang. Verwenden Sie das Verfahren zum Endpunkt der Metriks. Verwenden Sie frische Proben, nicht wiederholte Kopien eines gespeicherten Scrapes.
  2. Vergleichen Sie die Proben mit der Baseline vor der Bereitstellung. Es ist eine Erhöhung der insgesamt hochgeladenen Bytes und der Gesamtzahl der zwischengespeicherten Bytes auf diesen Servern erforderlich. Verlange nicht, dass jeder Server Daten empfängt.
  3. Warten Sie, bis der Upload-Byte-Zähler jedes Servers drei aufeinanderfolgende Sampling-Intervalle unverändert bleibt, nachdem der Gesamtupload gestiegen ist. Bestätigen Sie, dass kein Server neu gestartet und kein Zähler während des Vergleichs zurückgesetzt wurde.
  4. Speichere diese letzte Probe als Post-Cold-Snapshot, einschließlich cache_server_download_request_size_bytes_sum von jedem Server als Basislinie für die warme Last.

Wenn diese Bedingungen nicht innerhalb von fünf Minuten erfüllt sind, stoppen Sie den Vergleich, anstatt den Cache als warm zu behandeln. Überprüfe die Upload-Fehler des Clients, die Gesundheit des Cache-Servers und den laufenden Datenverkehr, bevor du es erneut versuchst. Größere Modelle benötigen möglicherweise ein längeres Beobachtungsfenster. Eine fehlende Metrik oder ein fehlgeschlagener Scraping ist kein Nullwert oder ein Beweis dafür, dass die Uploads abgeschlossen sind.

Stabile Zähler sind ein Bereitschaftssignal, nicht der Beweis, dass jeder Modellchunk zwischengespeichert ist. Shared-Cache-Verkehr kann ebenfalls eine Stabilisierung verhindern oder für Erhöhungen verantwortlich sein. Verwenden Sie möglichst ein ruhiges Validierungsfenster und schreiben Sie die untenstehenden fresh-Pod-Warm-Read-Prüfungen vor, um die Wiederverwendung des verteilten Caches zu bestätigen.

Überprüfen Sie einen Warmstart in einem frischen Pod

Speichere das Cold Log und die Pod-UID. Erstellen Sie nur den Anwendungspod mit denselben Modelldateien, Cache-Endpunkt, Bibliothek und Chunk-Größe erneut:

kubectl -n runai-dacs logs runai-dacs-vllm -c vllm > runai-cold.log
kubectl -n runai-dacs get pod runai-dacs-vllm -o jsonpath='{.metadata.uid}' > runai-cold.uid
kubectl -n runai-dacs delete pod runai-dacs-vllm --wait=true
kubectl apply -f runai-dacs-pod.yaml
kubectl -n runai-dacs wait --for=condition=Ready pod/runai-dacs-vllm --timeout=30m
kubectl -n runai-dacs get pod runai-dacs-vllm -o jsonpath='{.metadata.uid}' > runai-warm.uid
kubectl -n runai-dacs logs runai-dacs-vllm -c vllm > runai-warm.log

Führen Sie die Laufzeitprüfung und die Inferenzanfrage erneut aus. Anschließend erfassen Sie von jedem Cache-Server eine Metrikaufnahme nach dem Aufwärmen. Unterschiedliche Pod-UIDs, eine erhöhte Trefferrate des Remote-Source-Caches und weniger Backing-Store-Reads. Vergleichen Sie cache_server_download_request_size_bytes_sum mit dem Snapshot nach dem Kaltstart, um warme Cache-Lesungen zu verifizieren. Ein frischer Prozess vermeidet es, einen lokalen In-Memory-Prefetch mit einem verteilten Cache-Hit zu verwechseln.

Die Trefferrate der entfernten Quelle ist RemoteCache / (RemoteCache + RemoteClient), ohne lokale Prefetch. Verwenden Sie den neuesten kumulativen Snapshot für jeden nativen Prozess, jeden Mount und jede Chunk-Größe; summieren Sie keine periodischen Proben. Messungen, die durch Cache-Server-Neustarts oder Counter-Resets betroffen sind, werden ausgeschlossen. Shared-Server-Zähler bestätigen Anwendungsprotokolle, ordnen aber nicht den gesamten Datenverkehr einer einzigen Arbeitslast zu.

Metadaten können weiterhin auf Blob Storage zugreifen, selbst wenn Warm-Weight-Read-Zähler 0 Backing-Store-Lesungen anzeigen.

DACS-Client-Bibliotheken mit ImageVolume einbinden

Nutze diese Alternative nur, wenn die Node-Laufzeit ImageVolume unterstützt und du ein pullbares Client-Image hast, das aus dem öffentlichen DACS-Wheel erstellt wurde. Gehen Sie nicht davon aus, dass ein vorgeschlagenes MCR-Bild oder -Tag veröffentlicht wird. Wenn kein geeignetes Client-Image verfügbar ist, verwenden Sie das Workload-Image-Verfahren im vorherigen Abschnitt.

Ihr GPU-vLLM-Image muss bereits kompatible Run:ai-Core- und Azure-Pakete enthalten. Du musst das DACS-Clientpaket nicht in dessen Python-Umgebung installieren, da das Bildvolumen die nativen Client-Bibliotheken liefert.

Adaptiere das Pod-Beispiel wie folgt:

  1. Behalte dein bestehendes, kompatibles vLLM-Image statt es neu zu bauen, um die DACS-Client-Bibliotheken zu installieren.

  2. Fügen Sie ein schreibgeschütztes Client-Bildvolumen hinzu und hängen Sie es ein:

    # Add to spec.volumes.
    - name: dacs-client
      image:
        reference: "<accessible-client-image>"
        pullPolicy: IfNotPresent
    
    # Add to the vLLM container's volumeMounts.
    - name: dacs-client
      mountPath: /opt/cache-client
      readOnly: true
    
  3. Setze RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB auf den absoluten Pfad von libStorageDirect.so unter /opt/cache-client, basierend auf dem tatsächlichen Layout dieses Bildes. Bewahre die nativen Abhängigkeiten gleichgeordneter Komponenten.

  4. Stellen Sie bereit und bestätigen Sie, dass das Image-Volume und die schreibgeschützte Mount-Einbindung in der Pod-Spezifikation live erhalten bleiben. Überprüfen Sie, ob die Datei existiert, führen Sie dann dieselben Prüfungen der Laufzeit für Application-Container sowie Kalt-/Warm-Prüfungen durch.

Einige ältere Cluster können nicht unterstützte image-volume-Felder und -mounts aus dem akzeptierten Pod entfernen. Die Kubernetes-Version und der Server-Dry-Run allein reichen nicht aus. Installieren Sie keine widersprüchliche Version der DACS-Client-Bibliotheken und laden Sie keine solche Version zusammen mit dem gemounteten Client vor; ein absoluter Bibliothekspfad isoliert den Namespace nativer Abhängigkeiten nicht.

Leseleistung optimieren

Warum die Chunk-Größe anpassen? Modelle haben unterschiedliche Tensorgrößen und Lesemuster, sodass eine Chunk-Größe möglicherweise nicht für jedes Modell die beste Modellladeleistung liefert. Übergroße Chunks laden mehr Daten ab, als ein Lesen benötigt, und erhöhen das Puffern. Unterdimensionierte Stücke erhöhen die Anzahl der Anfragen und den Overhead pro Anfrage. Die Wahl einer Größe, die zu den häufig auftretenden Tensoren des Modells passt, gleicht diese Kosten aus, verbessert den effektiven Gewichtsdurchsatz und reduziert die Ladezeit des Modells, einschließlich warmer Lasten von DACs. Betrachten Sie die folgenden Empfehlungen als Ausgangspunkte und messen Sie die kalten und warmen Ladezeiten getrennt. Gewinne hängen vom Modell, der Nebenwahl des Loaders sowie der Speicher- und Netzwerkleistung ab.

Wählen Sie eine Chunk-Größe anhand folgender modellspezifischer Empfehlungen. Für andere Modelle inspizieren Sie die Tensor-Metadaten, wie im nächsten Abschnitt beschrieben, oder verwenden Sie 32 MiB , falls Metadaten-Inspektion nicht verfügbar ist.

Model Empfohlene Stückgröße Wert in Bytes
qwen3-coder-30b-a3b-instruct 3 MiB 3145728
gpt-oss-20b 2 MiB 2097152
deepseek-r1-0528 14 MiB 14680064
deepseek-v3-0324 14 MiB 14680064
phi-2 2 MiB 2097152
mistral-small-4-119b-2603-nvfp4 2 MiB 2097152
ministral-3-3b-instruct-2512 2 MiB 2097152
ministral-3-3b-instruct (alias) 2 MiB 2097152
ministral-3-8b-instruct-2512 2 MiB 2097152
ministral-3-8b-instruct (Alias) 2 MiB 2097152
ministral-3-14b-instruct-2512 2 MiB 2097152
ministral-3-14b-instruct (Alias) 2 MiB 2097152
Ausweichlösung, wenn Metadaten-Inspektion nicht verfügbar ist 32 MiB 33554432

Wählen Sie eine Chunk-Größe für ein anderes Modell

Verwenden Sie einen Safetensors-Metadaten-Viewer oder ein Header-Inspektionstool, um alle Model-Shards zu inspizieren, ohne Tensorinhalte zu laden:

  1. Finde die gespeicherte Größe jedes Tensors in Bytes: seinen Enddatenoffset minus den Startoffset. Den Eintrag __metadata__ ausschließen.
  2. Behandle jede Größe über 32 MiB als 32 MiB , bevor du die Vorkommnisse zähle.
  3. Wählen Sie die über alle Shards hinweg am häufigsten vorkommende Größe aus. Wenn mehrere Größen gleich häufig vorkommen, wähle die größere.
  4. Wenn die gewählte Größe unter 2 MiB liegt, verwenden Sie 2 MiB.

Wenn beispielsweise 3-MiB-Tensoren am häufigsten nach dem Capping auftreten, verwenden Sie 3 MiB (3145728 bytes). Wenn die Metadaten-Inspektion nicht verfügbar ist, verwenden Sie 32 MiB (33554432 Byte).

Konfigurieren der Anwendung

Setzen Sie sowohl RUNAI_STREAMER_CHUNK_BYTESIZE als auch SI_streamingChunkSize auf den resultierenden Byte-Wert in der Umgebung des Anwendungscontainers. Zum Beispiel für eine 3-MiB-Empfehlung:

env:
  - name: RUNAI_STREAMER_CHUNK_BYTESIZE
    value: "3145728"
  - name: SI_streamingChunkSize
    value: "3145728"

Legen Sie diese Werte explizit fest; die Tabelle beschreibt Empfehlungen, nicht automatische Modellerkennung oder eingebaute Standardeinstellungen. Erstelle den Anwendungs-Pod nach den Änderungen neu; Cache-Server müssen nicht neu gestartet werden. Leser und Population-Jobs, die zwischengespeicherte Daten teilen, sollten die gleiche Chunk-Größe verwenden.

Die Lesegröße von Run:ai und die native Cache-Chunk-Größe sind separate Steuerungen, die oben zusammen konfiguriert sind. Teste die Empfehlung anhand deiner Arbeitslast und passe die Parallelität des Loaders separat an. Vergleiche kalte und warme Ladevorgänge unabhängig voneinander. Die Änderung der Cache-Chunk-Größe erzeugt verschiedene Cache-Schlüssel und kann die Cache-Belegung vorübergehend erhöhen. Ändern Sie jeweils eine Einstellung und messen Sie die Ladezeit, native Zähler, Cache-Metriken, CPU-, GPU- und Hostspeicher sowie die Netzwerknutzung. Die Tensorausrichtung allein garantiert keine bessere Leistung.

Warning

Das asynchrone Upload-Buffer-Budget des öffentlichen nativen Clients beträgt in 0.1.0 standardmäßig 400 GiB. Es handelt sich nicht um eine Vorallokation oder ein sicheres Pod-Speicherlimit. Eine Kältepopulation mit großem Modell kann einen kleineren Pod erschöpfen. Für speicherbeschränkte Arbeitslasten testen Sie synchrone Population (SI_cacheEnableSyncUpload=true) oder ein begrenztes asynchrones Upload-Budget (SI_cacheMaxUploadBufferSizePerProcessGB). Budgetmodell-Staging, native Upload-/Prefetch-Puffer, GPU-Speicher und /dev/shm separat. Diese Schutzmaßnahmen sind optionale, workloadspezifische Einstellungen, nicht zusätzliche Anforderungen für das Beispiel eines kleinen Modells.

Troubleshoot

Symptom Prüfen
Fehler beim Abrufen eines Images Kubelet-Berechtigungen zum Pullen, Registry-Berechtigungsmodus, Image-Digest und Netzwerkzugriff.
Die Native-Bibliothek wird nicht geladen Python-Umgebung der Anwendung, expliziter Pfad, glibc-Kompatibilität und benachbarte native Bibliotheken.
Blob-Autorisierung schlägt fehl Ausgewählte Identität, Reader-Rolle, Rollenweitergabe, Föderation und Pod-Label. Für andere Authentifizierungsmethoden folgen Sie der oben verlinkten ursprünglichen Azure-Authentifizierungsanleitung.
Das Modell wird ohne Cache-Datenverkehr geladen Sowohl Erkennungseinstellungen, das Laden von Providern, DNS-/Netzwerkerreichbarkeit als auch native Zähler für gelesene Daten.
Warmstarts lesen weiterhin Blob-Daten Vervollständigung der Population, Blob-Versionen, übereinstimmende Chunk-Größen, Verdrängungen und partielle Lesevorgänge.
ImageVolume fehlt Live-Pod-Felder und Node-/Laufzeitunterstützung; verwenden Sie die integrierte Methode, falls diese Unterstützung nicht verfügbar ist.
Pod wird OOM getötet Modell- und Staging-Speicher, native Puffer, Dimensionierung des GPU-/KV-Caches und /dev/shm.

Für einen separaten direkten Blobvergleich setzen Sie RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 und erstellen Sie einen Test-Pod neu. Wenn man es stattdessen auf 1 setzt, führen Fehler beim Laden des Providers dazu, dass der Start fehlschlägt, anstatt stillschweigend darauf zurückzufallen. Keine der beiden Einstellungen belegt Cache-Hits; prüfen Sie die Datenlesezähler.

Beispiel bereinigen

Wenn du den eigenständigen Beispiel-Pod erstellt hast, lösche ihn, wenn du fertig bist:

kubectl -n runai-dacs delete pod runai-dacs-vllm --wait=true

Entferne nur Modellpräfixe, Abbilder, Identitäten, Föderationen, Namensräume und Rollenzuweisungen, die du für dieses Beispiel erstellt hast und nicht mehr benötigst. Löschen Sie keinen bestehenden freigegebenen Cache oder eine vorhandene Identität. Gespeicherte Modelldaten sind jetzt warm; verwenden Sie ein frisches Präfix für eine weitere Cold-Cache-Validierung.

Nächste Schritte