Usa Distributed Accelerator para almacenamiento en la nube con Run:ai Model Streamer (vista previa)

Run:ai Model Streamer lee los tensores de modelo simultáneamente y los transmite a la memoria de la GPU, solapando las lecturas de almacenamiento con las transferencias de CPU a GPU. Esta capacidad puede acortar el tiempo de carga del modelo y reducir el tiempo de inactividad de la GPU durante el arranque y el escalado horizontal del servidor de inferencia. Úsala para cargar modelos de SafeTensors desde Azure Blob Storage en vLLM porque soporta la carga directa desde almacenamiento de objetos y se integra con el cargador de modelos de vLLM. Para la integración upstream, véase Cargar modelos con Run:ai Model Streamer.

Al usar acelerador distribuido para almacenamiento en la nube (DACS), este camino de carga también puede reutilizar los datos de modelos almacenados en caché entre cargas de trabajo. vLLM utiliza el backend de Azure de Run:ai para cargar la biblioteca cliente nativa de DACS. Las operaciones de lectura recuperan datos almacenados en caché u obtienen los datos que faltan de Blob Storage.

Este artículo utiliza Run:ai Model Streamer 0.17.0, el paquete público dacs-client==0.1.0 y la compilación del v0.1.0 servidor. El procedimiento principal instala las dependencias en la imagen de la carga de trabajo. No requiere una imagen cliente DACS separada ni soporte para Kubernetes ImageVolume.

Completa Comienza con el acelerador distribuido para almacenamiento en la nube en AKS antes de usar este artículo. Para suministrar las bibliotecas cliente DACS sin tener que reconstruir la imagen de tu carga de trabajo, consulta Montar librerías cliente DACS con ImageVolume.

Prerequisites

  • Un despliegue DACS existente y su nombre de host de servicio de descubrimiento.
  • Un pool de nodos de GPU AKS con drivers NVIDIA compatibles, un plugin para dispositivos y suficiente memoria GPU para tu modelo. El siguiente ejemplo utiliza bfloat16, que requiere una GPU compatible.
  • Para la autenticación mediante identidad de carga de trabajo, un clúster de AKS con el emisor de OIDC y Id. de carga de trabajo de Microsoft Entra habilitados. Consulta Habilitar emisor OIDC y Id. de carga de trabajo de Microsoft Entra en un clúster AKS.
  • Una imagen compatible de GPU vLLM y un entorno Linux con glibc 2.35 o más reciente. Usa el mismo entorno Python que tu aplicación.
  • Un contenedor privado de Blob para archivos de modelos.
  • Un usuario o una identidad administrada independiente para la carga de archivos con el rol Colaborador de datos de Storage Blob en el contenedor del modelo.
  • Una identidad de inferencia con Storage Blob Data Reader en el contenedor del modelo. Configura un método en Configurar la autenticación de blobs.
  • Permisos para compilar e insertar la imagen de la carga de trabajo, así como permisos para que AKS pueda extraerla.
  • CLI de Azure, AzCopy v10 y la CLI de Hugging Face en tu máquina de preparación si necesitas subir un modelo.

La preparación del modelo no requiere una GPU. También puedes comprobar la instalación de paquetes, la carga de librerías nativas y la autenticación Blob en nodos de CPU con una imagen de aplicación compatible. Esas comprobaciones no validan la programación de GPU, el tamaño de la memoria ni la inferencia.

Sube archivos de modelo a Blob Storage

Salta esta sección si el modelo completo ya está en tu contenedor privado. Para realizar una prueba de caché en frío, utilice un prefijo de modelo que no haya leído a través de DACS.

Usa la identidad del uploader para este procedimiento, no la identidad de inferencia. Para asignaciones de roles con alcance de contenedor, consulta Asignar un rol de Azure para acceder a datos de blob. Azure control-plane Owner o Contributor por sí solo no concede acceso a datos Blob a través de Microsoft Entra ID.

Descarga el modelo

El siguiente ejemplo descarga los archivos de inferencia para SmolLM2-135M-Instruct en una revisión fija. Su tarjeta de modelo identifica la licencia como Apache-2.0. Instala la CLI de Hugging Face y luego ejecuta:

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"

Opcionalmente, utiliza el comando hf cache verify de una CLI actual para verificar los archivos descargados frente a las sumas de comprobación del Hub:

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

Como esta descarga selecciona únicamente archivos de inferencia, la verificación puede informar de archivos de repositorio ausentes, como variantes de modelos no utilizadas. También puede reportar metadatos locales adicionales de descarga de Hugging Face. Estos mensajes no son fallos de suma de comprobación. Investiga archivos inesperados o desajustes de suma de comprobación antes de subir.

Para otro modelo, incluye todos los fragmentos de SafeTensors y cualquier índice de peso, configuración de modelo y generación, archivos tokenizadores y archivos de licencias y atribuciones aplicables. Conserva la estructura de directorios necesaria. No incluyas variantes ONNX no relacionadas, puntos de control de entrenamiento, archivos de optimizador o credenciales.

Cargar con AzCopy

Instala AzCopy v10. Inicie sesión en la CLI de Azure como usuario encargado de la carga de archivos y, a continuación, copie el contenido del directorio local en un nuevo prefijo de Blob:

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"

El comodín entrecomillado copia el contenido del directorio directamente al prefijo sin añadir un nivel de directorio local. Las exclusiones omiten los metadatos de descarga y Git. Continúe únicamente cuando AzCopy indique que no se ha producido ningún error de transferencia y que el destino contiene todos los archivos necesarios. Para más información, consulte Subir contenido del directorio con AzCopy y Autorizar AzCopy usando CLI de Azure.

Para un uploader que se ejecuta en una máquina virtual de Azure, puedes autorizar AzCopy con una identidad gestionada. Mantén el contenedor privado y elimina las asignaciones temporales de roles de uploader después de la preparación. Permite tiempo para que se propaguen nuevas asignaciones de roles; no soluciones los errores de autorización añadiendo claves de almacenamiento o secretos del cliente.

Registra la revisión del modelo y las versiones Blob o ETags. La ubicación del modelo Run:ai es az://<container>/<model-prefix>. Mantén estos archivos sin cambios entre cargas en frío y caliente. Para otra prueba en frío, usa otro nuevo prefijo en lugar de expulsar datos de una caché compartida.

Prepara la imagen de la carga de trabajo sin ImageVolume

Instala dependencias durante la construcción de la imagen, no al arrancar el pod. Conserva tu aplicación actual, la imagen base y el punto de entrada. Utiliza el gestor de paquetes de la aplicación y el flujo de trabajo de requisitos o restricciones para preservar dependencias compatibles, incluyendo Torch, CUDA y NumPy.

Usa una imagen vLLM con GPU y versiones Torch y CUDA compatibles con los nodos de la GPU y los controladores NVIDIA. Revisa los paquetes instalados de Run:ai core y backend de Azure antes de añadir dependencias; no todas las imágenes vLLM incluyen el backend de Azure.

Resuelve los conflictos de dependencias en la imagen de tu carga de trabajo antes de desplegarla. El pip check paso de la siguiente sección debe completarse con éxito. Utiliza las restricciones de dependencias de tu aplicación para preservar la compatibilidad con otros paquetes instalados.

  1. Si tu imagen no contiene ya paquetes compatibles de Run:ai core y backend de Azure, añade la siguiente instrucción a tu archivo Docker:

    RUN python3 -m pip install --no-cache-dir "runai-model-streamer[azure]==0.17.0"
    
  2. Instala el paquete cliente público de DACS, que suministra las bibliotecas nativas del cliente, en ese mismo entorno Python:

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

    Azure extra de Run:ai no instala las bibliotecas cliente de DACS. Si tu aplicación ya tiene paquetes Run:ai compatibles, solo se necesita la instalación del paquete cliente DACS.

  3. Compila y empuja usando tu Dockerfile y contexto de compilación existente. Ejecuta los siguientes comandos en Bash en tu máquina de preparación. Este ejemplo se construye para nodos 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. En la misma sesión de Bash, resuelve la ruta de la biblioteca nativa desde la imagen construida:

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

    Utilice la ruta absoluta que se muestra en la salida al configurar la carga de trabajo. Conserve la instalación completa del cliente, incluidas las bibliotecas nativas ubicadas en el mismo directorio.

Dé prioridad al uso de un resumen inmutable de la imagen al realizar la implementación. Actualizar el cliente integrado requiere reconstruir y volver a desplegar la imagen de la carga de trabajo.

Configurar autenticación de Blob

Usa la identidad de carga de trabajo de AKS para la autenticación de Blobs. El ejemplo de despliegue utiliza este método con Storage Blob Data Reader con alcance al contenedor del modelo. No se necesita el permiso de escritura del usuario que sube el archivo para la inferencia. Para otros métodos de autenticación, consulte autenticación de Azure en la documentación de Run:ai Model Streamer.

Usa la identidad de carga de trabajo de AKS

El ejemplo de despliegue utiliza ServiceAccount runai-reader en el runai-dacs espacio de nombres. Completa los siguientes pasos antes de desplegar la carga de trabajo:

  1. Activa el emisor OIDC y el Id. de carga de trabajo de Microsoft Entra en tu clúster AKS existente, si no están ya habilitados.

  2. Recupera la URL del emisor OIDC.

  3. Crea una identidad gestionada o selecciona una identidad existente.

  4. Si el runai-dacs espacio de nombres no existe ya, créalo.

    kubectl create namespace runai-dacs
    
  5. Crea una ServiceAccount de Kubernetes anotada con el ID de cliente de esa identidad.

  6. Cree la credencial de identidad federada para el espacio de nombres exacto y la cuenta de servicio. No necesitas completar los siguientes pasos de Key Vault.

Asigna el rol de lector de Blob a la identidad gestionada federada a tu aplicación ServiceAccount. Para un ejemplo de asignación con alcance de contenedor, véase Conceder acceso de lectura a los datos del modelo, sustituyendo esta identidad por la identidad kubelet del quickstart.

El pod debe seleccionar la cuenta de servicio ServiceAccount y tener la etiqueta azure.workload.identity/use: "true". AKS inyecta la configuración de identidad y el token proyectado. No añadas secretos de cliente ni claves de cuenta de almacenamiento manualmente.

Configurar el acceso a la descarga de imágenes por separado

Para las imágenes privadas de ACR, configure los permisos de extracción de la identidad del kubelet tal como se describe en Agregar el cliente a una imagen de carga de trabajo. Usa AcrPull para RBAC clásico. Para un registro habilitado por ABAC, usa Container Registry Repository Reader con el acceso adecuado al repositorio. No use --attach-acr para ese registro.

El acceso de lectura de blobs para la identidad de la aplicación no otorga acceso para extraer imágenes al kubelet. Para ImageVolume, los permisos de extracción deben abarcar tanto la imagen de la carga de trabajo como la del cliente, incluidos los registros o repositorios independientes, cuando corresponda.

Configurar y desplegar la carga de trabajo

Establece estas cuatro variables de aplicación antes de iniciar vLLM. Son independientes de los ajustes de identidad que proporciona tu método de autenticación:

Variable del entorno Purpose
AZURE_STORAGE_ACCOUNT_NAME Cuenta de almacenamiento que contiene el modelo.
CACHE_DISCOVERY_URL Nombre del host de detección de DACS, como cache-sample-discovery.<namespace>.svc.cluster.local.
CACHE_SERVER_PORT Puerto de caché, normalmente 9065.
RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB Ruta absoluta de biblioteca nativa resuelta desde tu imagen de carga de trabajo.

Important

El descubrimiento de caché no es opcional. Una carga de modelo puede tener éxito leyendo Blob Storage directamente cuando la caché no está configurada. Con el backend 0.17.0de Run:ai Azure, también especifica explícitamente la ruta de la biblioteca nativa en lugar de depender del descubrimiento automático.

Use el formato de URI modelo de Run:ai, az://<container>/<model-prefix>, con la cuenta suministrada a través de AZURE_STORAGE_ACCOUNT_NAME. Este formato URI difiere del URI canónico del cliente nativo de Python, que incluye el nombre de host de la cuenta.

Sustituye los marcadores de posición en el siguiente ejemplo y guárdalo como runai-dacs-pod.yaml. Utilice el prefijo del modelo de la carga de archivos y la ruta de la biblioteca nativa que se muestra en la imagen compilada. El ejemplo utiliza Workload Identity y no contiene ImageVolume ni contenedor de inicialización:

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

Estos recursos ilustran un modelo pequeño, no un modelo 30B. Conserva la planificación requerida de tu carga de trabajo, los recursos, las sondas, la memoria compartida y otros argumentos de vLLM. Ajusta el número de GPU, el paralelismo tensorial, la longitud del modelo y el tamaño de la memoria para tu modelo. Para un despliegue o StatefulSet, aplica etiquetas de Pod bajo spec.template.metadata y Configuración de Pod bajo spec.template.spec.

El primer despliegue inicia vLLM y carga el modelo antes de que el Pod esté listo. Para una comparación de caché en frío, complete estos pasos en orden:

  1. Selecciona los datos del modelo que la caché no haya leído, como el prefijo reciente del procedimiento de subida. No desalojes datos de una caché compartida.

  2. Antes de implementar el pod de la aplicación, capture una instantánea de las métricas de referencia de cada pod de servidor de caché como se describe en Supervisar el acelerador distribuido para el almacenamiento en la nube. Anote la marca de tiempo y el cache_server_upload_request_size_bytes_sum, cache_server_download_request_size_bytes_sum y el cache_server_cache_size_bytes de cada servidor.

  3. Despliega e inspecciona el Pod aceptado:

    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
    

Comprobar el entorno de ejecución de la carga de trabajo

Ejecuta esta comprobación dentro del contenedor de aplicaciones vLLM, usando el ejecutable en Python de la aplicación. Verifica la consistencia de paquetes y la carga de librerías nativas, no la autenticación por blob ni el uso de caché:

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

Resuelva los errores antes de continuar. Para el despliegue de la GPU, también revisa la visibilidad de la GPU y los registros del motor de vLLM para confirmar la ejecución de CUDA y el modelo dtype previsto. El estado de preparación o la carga correcta de una biblioteca por sí solos no demuestran que se haya ejecutado código en la GPU ni que se haya utilizado la caché de DACS.

Verifica el comportamiento de la caché en frío y caliente

Utiliza la línea base de métricas previas al despliegue recogidas en Configura e implementa la carga de trabajo. La carga del modelo realizada durante el despliegue es la carga en frío.

Verifica la carga en frío

Inspecciona el registro de la aplicación:

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

Busque ReadChunk stats nativas. RemoteClient cuenta las lecturas de pesos del almacenamiento subyacente; RemoteCache cuenta las lecturas de la caché remota. Algunos aciertos de caché durante la primera carga son normales porque lecturas previas pueden rellenar la caché con datos. GetProperties Los aciertos de caché describen metadatos, no aciertos en los pesos del modelo.

Envía una solicitud de inferencia:

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

Confirma lecturas distintas de cero del almacén de respaldo en frío. Mantén el Pod de la aplicación funcionando mientras compruebas la población de caché asíncrona:

  1. Tome muestras de cache_server_upload_request_size_bytes_sum y cache_server_cache_size_bytes de cada pod de servidor de caché del recurso de caché seleccionado cada 10 segundos, durante un máximo de cinco minutos. Use el procedimiento para el punto de conexión de métricas. Utilice muestras recientes, no copias repetidas de una recopilación de métricas almacenada.
  2. Compara las muestras con la línea base previa al despliegue. Requerir un aumento en el total de bytes subidos y en el total de bytes en caché en esos servidores. No exija que todos los servidores reciban datos.
  3. Espera hasta que el contador de bytes de subida de cada servidor permanezca sin cambios durante tres intervalos consecutivos de muestreo tras el aumento total de subida. Confirma que ningún servidor se reinició ni se restableció el contador durante la comparación.
  4. Guarde esa última muestra como instantánea posterior a la carga en frío, incluido el valor de cache_server_download_request_size_bytes_sum de cada servidor, como referencia para la carga en caliente.

Si estas condiciones no se cumplen en un plazo de cinco minutos, detenga la comparación en lugar de considerar que la caché se ha precalentado. Comprueba los errores de subida del cliente, el estado del servidor de caché y el tráfico en curso antes de volver a intentarlo. Los modelos más grandes pueden necesitar una ventana de observación más larga. Una métrica que falta o un scrape fallido no es un valor cero ni evidencia de que las subidas hayan terminado.

Los contadores estables son una señal de preparación, no una prueba de que cada bloque de modelo está almacenado en caché. El tráfico de la caché compartida también puede impedir que las métricas se estabilicen o explicar los aumentos observados. Utilice, siempre que sea posible, un intervalo de validación con poco tráfico y exija que las comprobaciones de lectura en caliente de un pod recién creado que se indican a continuación confirmen la reutilización de la caché distribuida.

Comprobar una carga en caliente en un pod recién creado

Guarda el registro en frío y el UID del pod. Recrea solo el pod de la aplicación usando los mismos archivos de modelo, endpoint de caché, biblioteca y tamaño de bloque:

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

Repite la comprobación de tiempo de ejecución y la solicitud de inferencia. Luego, captura una instantánea de métricas post-calentamiento de cada servidor de caché. Confirme que los UID de los pods sean distintos, que haya aumentado la tasa de aciertos de caché de origen remoto y que se hayan reducido las lecturas del almacenamiento subyacente. Compare cache_server_download_request_size_bytes_sum con la instantánea posterior a la lectura en frío para corroborar las lecturas en caliente de la caché. Un proceso nuevo evita confundir la prelectura local en memoria con un acierto en caché distribuida.

La tasa de aciertos del origen remoto es RemoteCache / (RemoteCache + RemoteClient), excluida la precarga local. Utilice la instantánea acumulativa más reciente de cada proceso nativo, punto de montaje y tamaño de fragmento; no sume las muestras periódicas. Excluya las mediciones afectadas por reinicios de los servidores de caché o restablecimientos de los contadores. Los contadores de servidores compartidos corroboran los registros de la aplicación pero no asignan todo el tráfico a una sola carga de trabajo.

Las operaciones de metadatos pueden seguir accediendo a Blob Storage aunque los contadores de lecturas de pesos en caliente indiquen que no se han realizado lecturas del almacenamiento subyacente.

Montar las bibliotecas cliente de DACS con ImageVolume

Usa esta alternativa solo cuando el runtime del nodo soporte ImageVolume y tengas una imagen cliente extraíble construida desde la rueda pública del DACS. No des por hecho que una imagen o etiqueta propuesta de MCR está publicada. Si no hay ninguna imagen de cliente adecuada disponible, utiliza el procedimiento workload-image de la sección anterior.

La imagen de tu GPU vLLM debe contener ya paquetes compatibles de Run:ai core y Azure. No es necesario instalar el paquete del cliente de DACS en su entorno de Python porque el volumen de imagen proporciona las bibliotecas nativas del cliente.

Adapta el ejemplo del pod de la siguiente manera:

  1. Conserva tu imagen vLLM compatible existente en vez de reconstruirla para instalar las bibliotecas cliente de DACS.

  2. Agregue un volumen de imagen del cliente de solo lectura y móntelo:

    # 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. Establezca RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB en la ruta absoluta de libStorageDirect.so en /opt/cache-client, según el diseño real de la imagen. Preserva las dependencias nativas de elementos hermanos.

  4. Despliega y confirma que el volumen de imagen y el montaje de solo lectura permanecen en la especificación del pod live. Compruebe que el archivo existe y, a continuación, ejecute las mismas comprobaciones del entorno de ejecución del contenedor de la aplicación y de las cargas en frío y en caliente.

Algunos clústeres antiguos pueden eliminar los campos y puntos de montaje de volúmenes de imagen no admitidos del pod aceptado. La versión de Kubernetes y la simulación del servidor por sí solas no son suficientes. No instales ni precargues una versión conflictiva de las librerías cliente DACS junto al cliente montado; una ruta absoluta de biblioteca no aísla su espacio de nombres nativo de dependencias.

Optimizar el rendimiento de lectura

¿Por qué ajustar el tamaño de los trozos? Los modelos tienen diferentes tamaños de tensor y patrones de lectura, por lo que un tamaño de chunk puede no ofrecer el mejor rendimiento de carga de modelos para todos. Los bloques sobredimensionados obtienen más datos de los que una lectura necesita y aumentan el buffering. Los bloques demasiado pequeños aumentan el número de solicitudes y la sobrecarga por solicitud. Elegir un tamaño adecuado para los tensores habituales del modelo equilibra estos costes, mejora el rendimiento efectivo de lectura de peso y reduce el tiempo de carga del modelo, incluyendo las cargas calientes de DACS. Toma las siguientes recomendaciones como puntos de partida y mide los tiempos de carga en frío y caliente por separado. Las mejoras dependen del modelo, la concurrencia del cargador y el rendimiento del almacenamiento y la red.

Elija un tamaño de fragmento siguiendo las recomendaciones específicas del modelo que se indican a continuación. Para otros modelos, inspecciona los metadatos tensoriales tal como se describe en la siguiente sección, o usa 32 MiB si no hay inspección de metadatos disponible.

Model Tamaño de bloque recomendado Valor en 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
Alternativa cuando la inspección de metadatos no está disponible 32 MiB 33554432

Elige un tamaño de bloque para otro modelo

Utiliza un visor de metadatos Safetensors o una herramienta de inspección de cabeceras para inspeccionar todos los fragmentos de modelo, sin cargar contenido tensorial:

  1. Encuentra el tamaño almacenado de cada tensor en bytes: su desplazamiento de datos final menos su desplazamiento inicial. Excluye la __metadata__ entrada.
  2. Trata cada tamaño superior a 32 MiB como 32 MiB antes de contar las ocurrencias.
  3. Selecciona el tamaño que aparece con más frecuencia en todos los shards. Si aparecen varias tallas con la misma frecuencia, elige la más grande.
  4. Si el tamaño seleccionado es inferior a 2 MiB, usa 2 MiB.

Por ejemplo, si los tensores de 3 MiB aparecen con mayor frecuencia tras aplicar el límite, utiliza 3 MiB (3145728 bytes). Si la inspección de metadatos no está disponible, utilice 32 MiB (33554432bytes).

Configuración de la aplicación

Establece tanto RUNAI_STREAMER_CHUNK_BYTESIZE como SI_streamingChunkSize en el valor de byte resultante en el entorno del contenedor de la aplicación. Por ejemplo, para una recomendación de 3 MiB:

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

Establece estos valores explícitamente; la tabla describe recomendaciones, no detección automática de modelos ni valores predeterminados incorporados. Vuelva a crear el pod de la aplicación después de modificarlos; no es necesario reiniciar los servidores de caché. Los lectores y los trabajos de población que comparten datos en caché deberían usar el mismo tamaño de bloque.

El tamaño de lectura de Run:ai y el tamaño nativo del bloque de caché son controles independientes, configurados conjuntamente anteriormente. Compara la recomendación con tu carga de trabajo y ajusta la concurrencia del loader por separado. Compare las cargas en frío y en caliente por separado. Cambiar el tamaño del bloque de caché crea diferentes claves de caché y puede aumentar temporalmente la ocupación de caché. Cambia una configuración a la vez y mide el tiempo de carga, los contadores nativos, las métricas de caché, la CPU, la GPU y la memoria del host, y el uso de la red. La alineación tensorial por sí sola no garantiza un mejor rendimiento.

Warning

El presupuesto predeterminado del búfer de carga asíncrona del cliente público nativo es de 400 GiB en 0.1.0. No es una asignación previa de memoria ni un límite de memoria seguro para el pod. La carga inicial en frío de la caché de un modelo de gran tamaño puede agotar la memoria de un pod más pequeño. Para cargas de trabajo con limitaciones de memoria, prueba el llenado síncrono (SI_cacheEnableSyncUpload=true) o un presupuesto limitado para carga asíncrona (SI_cacheMaxUploadBufferSizePerProcessGB). Modelo de presupuesto para staging, búferes nativos de subida/prelectura, memoria GPU y /dev/shm por separado. Estas salvaguardas son configuraciones opcionales específicas de la carga de trabajo, no requisitos adicionales para el ejemplo de modelos pequeños.

Troubleshoot

Síntoma Check
Error en la extracción de imágenes Permisos de extracción de Kubelet, modo de permisos del registro, digest de imagen y acceso a la red.
La biblioteca nativa no carga Entorno de Python de la aplicación, ruta explícita, compatibilidad con glibc y bibliotecas nativas ubicadas en el mismo directorio.
Error de autorización de Blob Identidad seleccionada, rol de lector, propagación de rol, federación y etiqueta de Pod. Para otros métodos de autenticación, sigue la guía de autenticación de Azure en el upstream que se ha enlazado anteriormente.
El modelo se carga sin tráfico de caché Ambas opciones de configuración de detección, la carga del proveedor, la conectividad de DNS y de red, y los contadores de lectura de datos nativos.
Las cargas en caliente siguen leyendo datos de Blob Finalización del llenado de la caché, versiones de los blobs, coincidencia de los tamaños de fragmento, expulsiones de la caché y lecturas parciales.
Falta ImageVolume Campos Live Pod y soporte de nodos/runtime; usar el método incorporado si no está disponible.
El pod se termina por falta de memoria (OOM) Memoria del modelo y de almacenamiento provisional, búferes nativos, dimensionamiento de la GPU y de la caché KV, y /dev/shm.

Para una comparación directa separada de Blob, establece RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 y recrea un Pod de prueba. En cambio, si se establece en 1, los errores de carga del proveedor provocan un error de inicio en lugar de recurrir silenciosamente a una alternativa. Ninguna de las dos opciones de configuración demuestra que se hayan producido aciertos de caché; compruebe los contadores de lectura de datos.

Limpia el ejemplo

Si creaste el Pod de ejemplo independiente, bórralo cuando lo termines:

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

Elimina solo los prefijos de modelos, imágenes, identidades, federaciones, espacios de nombres y asignaciones de roles que hayas creado para este ejemplo y que ya no necesites. No elimines una caché o identidad compartida existente. Los datos del modelo conservados ya están en la caché precalentada; utilice un prefijo nuevo para realizar otra validación de la caché en frío.

Pasos siguientes