Użyj rozproszonego akceleratora do przechowywania w chmurze z Run:ai Model Streamer (podgląd)

Run:ai Model Streamer odczytuje tensory modelu równocześnie i przesyła je do pamięci GPU, nakładając odczyty pamięci z transferami CPU-GPU. Ta funkcja może skrócić czas ładowania modelu i skrócić czas bezczynności GPU podczas uruchamiania i skalowania serwera wnioskowania. Użyj jej do ładowania modeli SafeTensors z Azure Blob Storage w vLLM, ponieważ obsługuje bezpośrednie ładowanie z magazynu obiektów i integruje się z modułem ładowania modeli vLLM. W przypadku integracji upstream zobacz Ładowanie modeli za pomocą Run:ai Model Streamer.

Dzięki zastosowaniu rozproszonego akceleratora do przechowywania w chmurze (DACS), ta ścieżka ładowania może również ponownie wykorzystać dane modelu buforowane w różnych obciążeniach. vLLM używa backendu Azure Run:ai do ładowania natywnej biblioteki klienta DACS. Odczyty, pobierają dane z pamięci podręcznej lub pobierają brakujące dane z Blob Storage.

Ten artykuł wykorzystuje Run:ai Model Streamer 0.17.0, publiczny pakiet dacs-client==0.1.0 oraz wersję serwera v0.1.0. Główna procedura instaluje zależności w obrazie obciążenia roboczego. Nie wymaga osobnego obrazu klienta DACS ani wsparcia dla Kubernetes ImageVolume.

Ukończ Rozpocznij korzystanie z rozproszonego akceleratora do przechowywania w chmurze na AKS przed użyciem tego artykułu. Aby dostarczyć biblioteki klientów DACS bez konieczności odbudowy obrazu obciążenia, zobacz: Mount DACS client libraries with ImageVolume.

Prerequisites

  • Istniejące wdrożenie DACS oraz jego nazwa hosta usługi discovery.
  • Pula węzłów GPU usługi AKS z kompatybilnymi sterownikami NVIDIA, wtyczką urządzenia i wystarczającą pamięcią GPU dla Twojego modelu. Poniższy przykład wykorzystuje bfloat16, co wymaga kompatybilnej karty graficznej.
  • Do uwierzytelniania tożsamości obciążenia wymagany jest klaster AKS z włączonym wystawcą OIDC i Tożsamość obciążeń Microsoft Entra. Zobacz Włącz wystawcę OIDC i Tożsamość obciążeń Microsoft Entra w klastrze AKS.
  • Kompatybilny obraz GPU vLLM oraz środowisko Linux z glibc 2.35 lub nowszym. Używaj tego samego środowiska Python co twoja aplikacja.
  • Prywatny kontener Blob dla plików modeli.
  • Oddzielny użytkownik przesyłający lub zarządzana tożsamość z rolą Storage Blob Data Contributor dla kontenera modelu.
  • Tożsamość wnioskowania z Storage Blob Data Reader na kontenerze modelu. Skonfiguruj jedną metodę w Skonfiguruj uwierzytelnianie obiektu blob.
  • Uprawnienia do budowania i wysyłania obrazu obciążenia roboczego oraz uprawnienia dla AKS do jego pobierania.
  • Potrzebujesz Azure CLI, AzCopy v10 oraz Hugging Face CLI na maszynie przygotowawczej, jeśli musisz przesłać model.

Przygotowanie modelu nie wymaga użycia karty graficznej. Możesz także sprawdzić instalację pakietów, ładowanie natywnej biblioteki oraz uwierzytelnianie Blob na węzłach CPU z kompatybilnym obrazem aplikacji. Te kontrole nie weryfikują harmonogramowania GPU, rozmiarowania pamięci ani inferencji.

Przesyłaj pliki modeli do Blob Storage

Pomiń tę sekcję, jeśli cały model jest już w twoim prywatnym kontenerze. Do testu cold-cache użyj prefiksu modelu, który nie został odczytany przez DACS.

Do tej procedury używaj tożsamości uploadera, a nie tożsamości inferencji. W przypadku przypisań ról o zakresie kontenera zobacz Przypisywanie roli platformy Azure w celu uzyskania dostępu do danych obiektów blob. Sama płaszczyzna sterowania platformy Azure Owner lub Contributor same w sobie nie zapewniają dostępu do danych obiektów blob za pośrednictwem identyfikatora Microsoft Entra ID.

Pobierz model

Poniższy przykład pobiera pliki wnioskowania dla SmolLM2-135M-Instruct w określonej rewizji. Karta modelu identyfikuje licencję jako Apache-2.0. Zainstaluj Hugging Face CLI, a następnie uruchom:

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"

Opcjonalnie użyj polecenia aktualnego CLI hf cache verify , aby zweryfikować pobrane pliki względem sum kontrolnych Hub:

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

Ponieważ pobieranie wybiera tylko pliki inferencyjne, weryfikacja może zgłaszać brakujące pliki repozytorium, takie jak nieużywane warianty modelu. Może także raportować dodatkowe lokalne metadane pobierania Hugging Face. Te wiadomości nie są komunikatami o niezgodności sumy kontrolnej. Zbadaj nieoczekiwane pliki lub niezgodności sum kontrolnych przed przesłaniem.

W przypadku innego modelu uwzględnij wszystkie fragmenty SafeTensors oraz wszelkie pliki indeksu wag, konfigurację modelu i generowania, pliki tokenizera oraz odpowiednie pliki licencyjne i pliki z informacjami o autorstwie. Zachowaj wymaganą strukturę katalogu. Nie umieszczaj niezwiązanych wariantów ONNX, punktów kontrolnych treningowych, plików optymalizatorów ani poświadczeń.

Przesyłaj za pomocą AzCopy

Zainstaluj AzCopy v10. Zaloguj się przez Azure CLI jako użytkownik uploadera, a następnie skopiuj zawartość lokalnego katalogu do nowego prefiksu Bloba:

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"

Ujęty w cudzysłów symbol wieloznaczny kopiuje zawartość katalogu bezpośrednio do prefiksu bez dodawania poziomu katalogu lokalnego. Wykluczenia nie obejmują metadanych pobierania i Git. Kontynuuj dopiero gdy AzCopy zgłosi brak nieudanych transferów oraz gdy miejsce docelowe zawiera wszystkie wymagane pliki. Więcej informacji można znaleźć w sekcji Przekazywanie zawartości katalogu za pomocą narzędzia AzCopy oraz Autoryzowanie narzędzia AzCopy przy użyciu interfejsu wiersza polecenia platformy Azure.

Dla uploadera działającego na maszynie wirtualnej Azure możesz zamiast tego autoryzować AzCopy za pomocą zarządzanej tożsamości. Zachowaj kontener prywatny i usuń tymczasowe przypisania ról uploadera po przygotowaniu. Poczekaj na propagację nowych przypisań ról; nie omijaj błędów autoryzacji, dodając klucze magazynu lub wpisy tajne klienta.

Zapisz rewizję modelu i wersje Blob lub ETags. Lokalizacja modelu Run:ai to az://<container>/<model-prefix>. Zachowaj te pliki bez zmian między ładowaniem na zimno a na ciepło. Do następnego testu na zimno użyj kolejnego nowego prefiksu, zamiast usuwać dane ze współdzielonej pamięci podręcznej.

Przygotuj obraz obciążenia roboczego bez ImageVolume

Instaluj zależności podczas budowania obrazu, a nie przy starcie poda. Zachowaj swoją istniejącą aplikację, obraz bazowy i punkt wejścia. Korzystaj z menedżera pakietów aplikacji oraz procesu zarządzania wymaganiami lub ograniczeniami, aby zachować zgodność zależności, w tym Torch, CUDA i NumPy.

Użyj obrazu vLLM z obsługą GPU z wersjami Torch i CUDA zgodnymi z Twoimi węzłami GPU i sterownikami NVIDIA. Sprawdź zainstalowane pakiety Run:ai core i backend Azure przed dodaniem zależności; nie każdy obraz vLLM zawiera backend Azure.

Rozwiąż konflikty zależności w obrazie obciążenia roboczego przed wdrożeniem. Krok pip check w następnej sekcji musi zostać pomyślnie ukończony. Wykorzystaj ograniczenia zależności aplikacji, aby zachować kompatybilność z innymi zainstalowanymi pakietami.

  1. Jeśli Twój obraz nie zawiera jeszcze kompatybilnych pakietów Run:ai core i backendowych pakietów Azure, dodaj następującą instrukcję do pliku Dockerfile:

    RUN python3 -m pip install --no-cache-dir "runai-model-streamer[azure]==0.17.0"
    
  2. Zainstaluj publiczny pakiet klienta DACS, który dostarcza natywne biblioteki klienckie, w tym samym środowisku Python:

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

    Azure extra Run:ai nie instaluje bibliotek klienckich DACS. Jeśli twoja aplikacja ma już kompatybilne pakiety Run:ai, wystarczy instalacja pakietu klienta DACS.

  3. Buduj i wypchnij za pomocą istniejącego Dockerfile i kontekstu budowania. Wykonaj następujące polecenia w Bash na swojej maszynie przygotowawczej. Ten przykład buduje się dla węzłów x86-64:

    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. W tej samej sesji Bash rozstrzygnij ścieżkę natywnej biblioteki z zbudowanego obrazu:

    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)'
    

    Używaj wydrukowanej ścieżki absolutnej podczas konfigurowania obciążenia roboczego. Zachowaj kompletną instalację klienta, w tym powiązane biblioteki natywne.

Preferuj niezmienny skrót obrazu podczas wdrażania. Aktualizacja wbudowanego klienta wymaga odbudowy i ponownego wdrożenia obrazu workloadu.

Skonfiguruj uwierzytelnianie obiektów Blob

Użyj tożsamości obciążenia AKS do uwierzytelniania obiektów blob. Przykład wdrożenia wykorzystuje tę metodę z Storage Blob Data Reader przypisanym do kontenera modelu. Do wnioskowania nie jest potrzebne uprawnienie do zapisu osoby przesyłającej. Inne metody uwierzytelniania można znaleźć w dokumentacji Run:ai Model Streamer, gdzie można znaleźć informacje o uwierzytelnianiu Azure.

Użyj tożsamości obciążenia AKS

Przykład wdrożenia wykorzystuje runai-reader ServiceAccount w runai-dacs przestrzeni nazw. Wykonaj następujące kroki przed wdrożeniem obciążenia roboczego:

  1. Włącz emitenta OIDC i Tożsamość obciążeń Microsoft Entra na swoim obecnym klastrze AKS, jeśli nie są jeszcze włączone.

  2. Pobierz adres URL wydawcy OIDC.

  3. Utwórz tożsamość zarządzaną lub wybierz istniejącą tożsamość.

  4. Jeśli przestrzeń runai-dacs nazw jeszcze nie istnieje, utwórz ją.

    kubectl create namespace runai-dacs
    
  5. Stwórz konto serwisowe Kubernetes opatrzone adnotacją zawierającą identyfikator klienta tej tożsamości.

  6. Stwórz poświadczenie tożsamości federacyjnej dla dokładnej przestrzeni nazw i ServiceAccount. Nie musisz wykonywać kolejnych kroków Key Vault.

Przypisz rolę Czytelnik danych obiektów blob do zarządzanej tożsamości sfederowanej z kontem ServiceAccount aplikacji. Przykład przypisania w zakresie kontenera można znaleźć w Przyznawanie dostępu do odczytu danych modelu, zastępując tę tożsamość tożsamością kubeleta z przewodnika Szybki start.

Pod musi używać obiektu ServiceAccount i mieć etykietę azure.workload.identity/use: "true". AKS wprowadza ustawienia tożsamości i rzutowany token. Nie dodawaj ręcznie sekretów klienta ani kluczy do konta magazynowego.

Konfiguruj dostęp do pobierania obrazów kontenerów osobno

Dla prywatnych obrazów ACR konfiguruj uprawnienia tożsamości kubeleta do pobierania zgodnie z opisem w sekcji Dodaj klienta do obrazu obciążenia. Użyj AcrPull do klasycznego RBAC. Dla rejestru z obsługą ABAC należy używać Container Registry Repository Reader z odpowiednim dostępem do repozytorium. Nie używaj --attach-acr dla tego rejestru.

Dostęp do odczytu aplikacji nie daje dostępu do pobierania obrazów do kubelet. W przypadku ImageVolume dostęp pull musi obejmować zarówno obciążenie robocze, jak i obrazy klienta, w tym oddzielne rejestry lub repozytoria, jeśli dotyczy.

Skonfiguruj i wdróż obciążenie robocze

Ustaw te cztery zmienne aplikacyjne przed uruchomieniem vLLM. Są one oddzielne od ustawień tożsamości dostarczanych przez twoją metodę uwierzytelniania:

Zmienna środowiskowa Purpose
AZURE_STORAGE_ACCOUNT_NAME Konto pamięci zawierające model.
CACHE_DISCOVERY_URL Nazwa hosta wykrywania DACS, taka jak cache-sample-discovery.<namespace>.svc.cluster.local.
CACHE_SERVER_PORT Port pamięci podręcznej, zazwyczaj 9065.
RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB Absolutna ścieżka natywnej biblioteki ustalona na podstawie obrazu obciążenia.

Important

Odkrywanie cache nie jest opcjonalne. Załadowanie modelu może się powiódć, odczytując Blob Storage bezpośrednio, gdy pamięć podręczna nie jest skonfigurowana. W backendzie 0.17.0Run:ai Azure również wyraźnie określ ścieżkę natywnej biblioteki zamiast polegać na automatycznym odkrywaniu.

Użyj formatu modelu URI Run:ai, az://<container>/<model-prefix>, a konto dostarcza się przez AZURE_STORAGE_ACCOUNT_NAME. Ten format URI różni się od natywnego kanonicznego URI klienta Python, który zawiera nazwę hosta konta.

Zastąp zastępcze w poniższym przykładzie i zapisz go jako .runai-dacs-pod.yaml Użyj prefiksu modelu z przesłanego pliku oraz ścieżki do biblioteki natywnej wydrukowanej przez zbudowany obraz. Przykład wykorzystuje tożsamość obciążenia i nie zawiera ImageVolume ani kontenera init:

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

Te materiały ilustrują mały model, a nie model 30B. Zachowaj wymagane harmonogramowanie obciążenia roboczego, zasoby, sondy, pamięć współdzieloną i inne argumenty vLLM. Dostosuj liczbę GPU, równoległość tensorów, długość modelu i rozmiar pamięci dla swojego modelu. W przypadku elementu Deployment lub StatefulSet zastosuj etykiety Poda pod spec.template.metadata, a ustawienia Poda pod spec.template.spec.

Pierwsze wdrożenie uruchamia vLLM i ładuje model zanim Pod stanie się gotowy. Aby porównać cold-cache, wykonaj następujące kroki w kolejności:

  1. Wybierz dane modelu, których cache nie odczytał, na przykład świeży prefiks z procedury uploadu. Nie usuwaj danych z wspólnej pamięci podręcznej.

  2. Przed wdrożeniem aplikacyjnego Podu wykonaj bazowy migawkę metryk z każdego Podu serwera pamięci podręcznej, zgodnie z opisem w Monitor distributed accelerator for cloud storage. Zapisz znacznik czasu oraz cache_server_upload_request_size_bytes_sum, cache_server_download_request_size_bytes_sum oraz cache_server_cache_size_bytes każdego serwera.

  3. Wdróż i sprawdź zaakceptowany Pod:

    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
    

Sprawdź czas działania obciążenia

Wykonaj ten test wewnątrz kontenera aplikacji vLLM, używając pliku wykonywalnego Python aplikacji. Weryfikuje spójność pakietów i ładowanie natywnej biblioteki, a nie uwierzytelnianie Blob czy wykorzystanie pamięci podręcznej:

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

Przed kontynuowaniem rozwiąż błędy. Przy wdrożeniu GPU sprawdź także widoczność GPU i logi silnika vLLM, aby potwierdzić wykonanie CUDA i zamierzony dtype. Sama gotowość czy pomyślne ładowanie biblioteki nie dowodzi wykonywania na GPU ani użycia pamięci podręcznej DACS.

Weryfikacja zachowania pamięci podręcznej na zimno i w ciepło

Użyj bazowych metryk sprzed wdrożenia zebranych w Skonfiguruj i wdroż obciążenie robocze. Ładowanie modelu wykonywane podczas wdrożenia to zimne ładowanie.

Sprawdź zimny start

Sprawdź dziennik aplikacji:

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

Szukaj natywnych ReadChunk stats. RemoteClient liczy odczyty wag z magazynu pomocniczego; RemoteCache liczy odczyty wag ze zdalnej pamięci podręcznej. Niektóre trafienia do pamięci podręcznej podczas pierwszego ładowania są normalne, ponieważ wcześniejsze odczyty mogą uzupełnić pamięć podręczną danymi. GetProperties Trafienia w pamięci podręcznej opisują metadane, a nie trafienia dotyczące wag modelu.

Wyślij wniosek o wnioskowanie:

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

Potwierdź odczyty niezerowego cold backing-store. Utrzymuj aplikację włączoną, podczas gdy sprawdzasz populację asynchronicznej pamięci podręcznej:

  1. Próbkowanie i próbowanie cache_server_upload_request_size_bytes_sum z cache_server_cache_size_bytes każdego modułu serwera pamięci podręcznej dla wybranego zasobu pamięci podręcznej co 10 sekund, do pięciu minut. Użyj procedury endpoint metrics. Używaj świeżych próbek, a nie powtarzających się kopii przechowywanego skrobania.
  2. Porównaj próbki z bazową linią sprzed wdrożenia. Wymagaj zwiększenia łącznej liczby przesłanych bajtów oraz łącznej liczby bajtów w pamięci podręcznej na tych serwerach. Nie wymagaj, aby każdy serwer odbierał dane.
  3. Czekaj, aż licznik bajtów przesyłania każdego serwera pozostanie niezmieniony przez trzy kolejne odstępy próbkowania po wzroście całkowitej liczby przesłanych bajtów. Potwierdzam, że podczas porównywania nie było restartu serwera ani resetu licznika.
  4. Zachowaj tę ostatnią próbkę jako migawkę po schłodzeniu, włączając cache_server_download_request_size_bytes_sum z każdego serwera jako punkt odniesienia dla rozgrzanego obciążenia.

Jeśli warunki nie zostaną spełnione w ciągu pięciu minut, przerwij porównanie, zamiast traktować pamięć podręczną jako ciepłą. Sprawdź błędy przesyłania po stronie klienta, stan serwera cache oraz bieżący ruch przed ponowną próbą. Większe modele mogą wymagać dłuższego okna obserwacji. Brakujący wskaźnik lub nieudane scrapowanie nie jest wartością zero ani dowodem, że uploady zostały zakończone.

Liczniki stabilne są sygnałem gotowości, a nie dowodem, że każdy fragment modelu jest buforowany. Ruch współdzielonej pamięci podręcznej może również uniemożliwić stabilizację lub odpowiadać za wzrosty. Stosuj nieinwazyjne okno walidacji, gdzie to możliwe, i wymagaj wykonania poniższych sprawdzeń fresh-Pod warm-read, aby potwierdzić ponowne użycie rozproszonej pamięci podręcznej.

Zweryfikuj ciepłe uruchomienie w nowym podzie

Zachowaj cold log i UID poda. Odtwórz tylko pod aplikacji, używając tych samych plików modelu, endpointu pamięci podręcznej, biblioteki i rozmiaru chunku:

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

Powtórz sprawdzenie w czasie wykonywania i żądanie wnioskowania. Następnie zrób migawkę metryk po rozgrzewaniu z każdego serwera cache. Potwierdź różne UID-y podów, zwiększoną liczbę trafień z pamięci podręcznej zdalnego źródła oraz mniej odczytów z pamięci zapasowej. Porównaj cache_server_download_request_size_bytes_sum z migawką po zimnym uruchomieniu, aby potwierdzić odczyty z ciepłej pamięci podręcznej. Świeżo uruchomiony proces unika mylenia lokalnego prefetchu w pamięci z trafieniem z rozproszonej pamięci podręcznej.

Wskaźnik trafień zdalnego źródła wynosi RemoteCache / (RemoteCache + RemoteClient), z wyłączeniem lokalnego prefetch. Używaj najnowszej skumulowanej migawki dla każdego natywnego procesu, punktu montowania i rozmiaru chunku; nie sumuj próbek okresowych. Wyklucz pomiary dotknięte restartami serwera cache lub resetami liczników. Liczniki serwerów współdzielonych potwierdzają logi aplikacji, ale nie przypisują całego ruchu jednemu obciążeniu roboczemu.

Metadana może nadal komunikować się z Blob Storage, nawet gdy liczniki odczytów warm weight pokazują zero odczytów z pamięci zapasowej.

Montowanie bibliotek klienckich DACS za pomocą ImageVolume

Używaj tej alternatywy tylko wtedy, gdy runtime węzła obsługuje ImageVolume i masz pobieralny obraz klienta zbudowany z publicznego pakietu wheel DACS. Nie zakładaj, że proponowany obraz MCR lub tag MCR zostanie opublikowany. Jeśli nie ma odpowiedniego obrazu klienta, użyj procedury workload-image z poprzedniej sekcji.

Twój obraz GPU vLLM musi już zawierać kompatybilne pakiety rdzenia Run:ai i Azure. Nie musisz instalować pakietu klienta DACS w środowisku Python, ponieważ wolumin obrazu dostarcza natywne biblioteki klienckie.

Dostosuj przykład podu w następujący sposób:

  1. Zachowaj swój istniejący kompatybilny obraz vLLM zamiast go przebudowywać, żeby zainstalować biblioteki klienta DACS.

  2. Dodaj wolumin obrazu klienta tylko do odczytu i zamontuj go:

    # 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. Ustaw RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB absolutną ścieżkę libStorageDirect.so poniżej , /opt/cache-clientna podstawie rzeczywistego układu tego obrazu. Zachowaj natywne zależności równorzędne.

  4. Wdróż i potwierdź, że wolumin obrazu oraz montowanie tylko do odczytu pozostają w specyfikacji poda live. Sprawdź, czy plik istnieje, a następnie uruchom to samo środowisko uruchomieniowe kontenera aplikacji oraz wykonaj testy zimne/ciepłe.

Niektóre starsze klastry mogą usuwać nieobsługiwane pola i montowania woluminu obrazu z zaakceptowanego poda. Sama wersja Kubernetes i dry-run serwera nie są wystarczające. Nie instaluj ani nie wstępnie ładuj konfliktowej wersji bibliotek klienta DACS obok zamontowanego klienta; bezwzględna ścieżka do biblioteki nie izoluje natywnej przestrzeni nazw jego zależności.

Optymalizuj wydajność odczytu

Dlaczego warto dostrajać rozmiar chunku? Modele mają różne rozmiary tensorów i różne wzorce odczytu, więc jeden rozmiar bloku może nie zapewniać najlepszej wydajności ładowania modeli dla każdego modelu. Zbyt duże fragmenty pobierają więcej danych, niż wymaga odczyt, i zwiększają buforowanie. Niewielkie fragmenty zwiększają liczbę żądań i narzut na pojedyncze żądanie. Wybór rozmiaru dostosowanego do często występujących tensorów modelu równoważy te koszty, poprawia efektywną przepustowość odczytu wagi oraz skraca czas ładowania modelu, w tym ciepłych wczytań z DACS. Traktuj poniższe zalecenia jako punkt wyjścia i mierz czasy ładowania zimnego i ciepłego osobno. Przyrosty zależą od modelu, równoległości ładowania oraz wydajności pamięci masowej i sieci.

Wybierz rozmiar bloku, korzystając z poniższych zaleceń dla danego modelu. W przypadku innych modeli należy podejrzeć metadane tensorowe opisane w następnej sekcji lub użyć 32 MiB , jeśli inspekcja metadanych nie jest dostępna.

Model Zalecany rozmiar kawałka Wartość w bajtach
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 (pseudonim) 2 MiB 2097152
Tryb awaryjny, gdy inspekcja metadanych jest niedostępna 32 MiB 33554432

Wybierz rozmiar fragmentu dla innego modelu

Użyj przeglądarki metadanych Safetensors lub narzędzia do inspekcji nagłówków, aby przejrzeć wszystkie shardy modelu, bez ładowania zawartości tensorów:

  1. Znajdź zapisany rozmiar każdego tensora w bajtach: jego końcowe przesunięcie danych minus przesunięcie początkowe. Wyklucz wpis __metadata__.
  2. Traktuj każdy rozmiar powyżej 32 MiB jako 32 MiB przed liczeniem przypadków.
  3. Wybierz najczęściej występujący rozmiar we wszystkich shardach. Jeśli wiele rozmiarów występuje równie często, wybierz większy rozmiar.
  4. Jeśli wybrany rozmiar jest poniżej 2 MiB, użyj 2 MiB.

Na przykład, jeśli tensory 3-MiB występują najczęściej po ograniczeniu, użyj 3 MiB (3145728bajtów). Jeśli inspekcja metadanych jest niedostępna, użyj 32 MiB (33554432bajtów).

Konfigurowanie aplikacji

Ustaw zarówno RUNAI_STREAMER_CHUNK_BYTESIZE, jak i SI_streamingChunkSize na wynikową wartość bajtu w środowisku kontenera aplikacji. Na przykład, dla rekomendacji 3-MiB:

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

Ustaw te wartości wyraźnie; tabela opisuje rekomendacje, a nie automatyczne wykrywanie modeli ani wbudowane domyślne ustawienia. Po ich zmianie odtwórz Pod; serwery cache nie wymagają restartu. Czytniki i zadania populacji dzielące się danymi w pamięci podręcznej powinny używać tego samego rozmiaru bloku.

Rozmiar odczytu Run:ai oraz natywny rozmiar fragmentu pamięci podręcznej to oddzielne ustawienia, skonfigurowane razem powyżej. Porównaj rekomendację z twoim obciążeniem i dostosuj współbieżność ładowaczy osobno. Porównaj niezależnie obciążenia zimne i ciepłe. Zmiana rozmiaru fragmentu pamięci podręcznej tworzy różne klucze pamięci podręcznej i może tymczasowo zwiększyć zajętość pamięci podręcznej. Zmieniaj jedno ustawienie na raz i mierz czas ładowania, natywne liczniki, metryki pamięci podręcznej, CPU, GPU i pamięć hosta oraz wykorzystanie sieci. Samo wyrównanie tensorów nie gwarantuje lepszej wydajności.

Warning

Domyślny budżet asynchronicznego bufora przesyłania publicznego klienta natywnego wynosi 400 GiB w 0.1.0. To nie jest prealokacja ani bezpieczny limit pamięci Pod. Zimne zasiedlanie dużych modeli może wyczerpać mniejszy Pod. Dla obciążeń ograniczonych pamięcią testuj populację synchroniczną (SI_cacheEnableSyncUpload=true) lub ograniczony asynchroniczny budżet uploadu (SI_cacheMaxUploadBufferSizePerProcessGB). Budżetowanie modelu, etapowanie, natywne bufory upload/prefetch, pamięć GPU i /dev/shm osobno. Te zabezpieczenia są opcjonalnymi ustawieniami specyficznymi dla obciążenia, a nie dodatkowymi wymaganiami dla przykładu małego modelu.

Troubleshoot

Objaw Sprawdzanie
Ściąganie obrazu kończy się niepowodzeniem Uprawnienia Kubelet do pobierania, tryb uprawnień rejestru, skrót obrazu oraz dostęp do sieci.
Natywna biblioteka się nie ładuje środowisko Python aplikacji, jawnie określona ścieżka, kompatybilność z glibc oraz sąsiednie natywne biblioteki.
Autoryzacja obiektu blob nie powiodła się Wybrana tożsamość, rola czytelnika, propagacja ról, federacja oraz etykieta Pod. W przypadku innych metod uwierzytelniania postępuj zgodnie z wcześniejszymi wskazówkami dotyczącymi uwierzytelniania Azure.
Model ładuje się bez odwołań do pamięci podręcznej Zarówno ustawienia wykrywania, ładowanie dostawców, dostępność DNS/sieci oraz natywne liczniki odczytu danych.
Ponowne uruchomienia nadal odczytują dane Blob Uzupełnienie populacji, wersje Blob, dopasowanie rozmiarów fragmentów, eksmisje i częściowe odczyty.
Brakuje ImageVolume Pola Live Pod oraz obsługa węzłów/środowiska uruchomieniowego; użyj metody wbudowanej, jeśli ta metoda jest niedostępna.
Pod został ubity z powodu OOM Pamięć modelu i stagingu, natywne bufory, rozmiarowanie pamięci podręcznej GPU/KV oraz /dev/shm.

Dla osobnego porównania bezpośrednio z Blob, ustaw RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 i odtworz testowy Pod. Ustawienie tej wartości na 1 zamiast tego powoduje, że błędy ładowania dostawców przerywają uruchamianie, zamiast po cichu przechodzić do ustawienia awaryjnego. Żadne z tych ustawień nie potwierdza trafień cache; sprawdź liczniki odczytu danych.

Wyczyść przykład

Jeśli stworzyłeś samodzielny przykładowy Pod, usuń go po ukończeniu:

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

Usuń tylko prefiksy modeli, obrazy kontenerów, tożsamości, federacje, przestrzenie nazw i przypisania ról, które utworzyłeś na potrzeby tego przykładu i których już nie potrzebujesz. Nie usuwaj istniejącej współdzielonej pamięci podręcznej ani tożsamości. Zachowane dane modelu są teraz ciepłe; użyj nowego prefiksu do kolejnej walidacji przy zimnym cache.

Następne kroki