Usar o acelerador distribuído para armazenamento em nuvem com o Run:ai Model Streamer (versão prévia)

Run:ai Model Streamer lê tensores de modelo simultaneamente e os transmite para a memória da GPU, sobrepondo-se às leituras de armazenamento com transferências CPU para GPU. Essa capacidade pode reduzir o tempo de carregamento do modelo e reduzir o tempo ocioso da GPU durante a inicialização do servidor de inferência e a expansão horizontal. Use-a para carregar modelos SafeTensors do Armazenamento de Blobs do Azure no vLLM porque suporta carregamento direto de armazenamento de objetos e se integra ao carregador de modelos do vLLM. Para a integração upstream, confira Carregando modelos com o Run:ai Model Streamer.

Ao usar o acelerador distribuído para armazenamento em nuvem (DACS), esse caminho de carregamento também pode reutilizar dados de modelos armazenados em cache entre cargas de trabalho. O vLLM usa o backend do Azure do Run:ai para carregar a biblioteca cliente nativa do DACS. Leituras recuperam dados em cache ou buscam dados faltantes do Armazenamento de Blobs.

Este artigo utiliza o Run:ai Model Streamer 0.17.0, o pacote público dacs-client==0.1.0 e a compilação do servidor v0.1.0. O procedimento principal instala as dependências na imagem da sua carga de trabalho. Não requer uma imagem cliente DACS separada nem suporte ao Kubernetes ImageVolume.

Conclua Comece com o acelerador distribuído para armazenamento em nuvem no AKS antes de usar este artigo. Para fornecer as bibliotecas clientes DACS sem reconstruir sua imagem de carga de trabalho, veja Montar bibliotecas clientes DACS com ImageVolume.

Prerequisites

  • Uma implantação DACS existente e seu nome de host de serviço de descoberta.
  • Um pool de nós de GPU AKS com drivers NVIDIA compatíveis, um plugin de dispositivo e memória GPU suficiente para o seu modelo. O exemplo a seguir usa bfloat16, que requer uma GPU compatível.
  • Para autenticação de identidade de carga de trabalho, é necessário um cluster AKS com o emissor OIDC e o ID de carga de trabalho do Microsoft Entra habilitados. Veja Habilitar o emissor OIDC e o ID de carga de trabalho do Microsoft Entra em um cluster AKS.
  • Uma imagem compatível com GPU vLLM e um ambiente Linux com glibc 2.35 ou mais recente. Use o mesmo ambiente Python da sua aplicação.
  • Um contêiner privado de Blob para arquivos de modelos.
  • Um usuário ou identidade gerenciada separada com Storage Blob Data Contributor no contêiner do modelo.
  • Uma identidade de inferência com o Storage Blob Data Reader no contêiner do modelo. Configure um método em Configurar autenticação de Blob.
  • Permissão para criar e fazer push da imagem da carga de trabalho, e permissão para o AKS fazer pull dela.
  • CLI do Azure, AzCopy v10 e a CLI Hugging Face na sua máquina de preparação caso precise enviar um modelo.

A preparação do modelo não requer GPU. Você também pode verificar a instalação de pacotes, carregamento nativo de bibliotecas e autenticação Blob em nós de CPU com imagem de aplicação compatível. Essas verificações não validam o escalonamento da GPU, o tamanho da memória ou a inferência.

Enviar arquivos de modelo para o Armazenamento de Blobs

Pule esta seção se o modelo completo já estiver no seu contêiner privado. Para um teste de cold cache, use um prefixo de modelo que você não leu por meio do DACS.

Use a identidade do carregador para esse procedimento, não a identidade de inferência. Para atribuições de papéis com escopo de contêiner, veja Atribuir um papel Azure para acesso a dados de blob. O plano Owner de controle do Azure ou Contributor sozinho não concede acesso a dados do Blob via Microsoft Entra ID.

Baixe o modelo

O exemplo a seguir baixa os arquivos de inferência para o SmolLM2-135M-Instruct em uma revisão fixa. Seu cartão do modelo identifica a licença como Apache-2.0. Instale a CLI do Hugging Face e execute:

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, use o comando hf cache verify de uma CLI atual para verificar os arquivos baixados com as somas de verificação do Hub:

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

Como esse download seleciona apenas arquivos de inferência, a verificação pode relatar arquivos de repositório ausentes, como variantes de modelos não utilizadas. Também pode reportar metadados extras de download local do Hugging Face. Essas mensagens não são falhas de checksum. Investigue arquivos inesperados ou incompatibilidades de soma de verificação antes de fazer o upload.

Para outro modelo, inclua todos os fragmentos do SafeTensors e qualquer índice de peso, configuração de modelo e geração, arquivos tokenizadores e arquivos de licença e atribuição aplicáveis. Preservar a estrutura de diretórios necessária. Não prepare variantes ONNX não relacionadas, pontos de verificação de treinamento, arquivos de otimizador ou credenciais.

Fazer upload com AzCopy

Instale o AzCopy v10. Faça login por meio da CLI do Azure como o usuário de upload e, em seguida, copie o conteúdo do diretório local para um novo prefixo 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"

O curinga entre aspas copia o conteúdo do diretório diretamente no prefixo, sem adicionar o nível do diretório local. As exclusões não incluem os metadados de download e do Git. Continue apenas depois que o AzCopy não relatar nenhuma falha de transferência e o destino contiver todos os arquivos necessários. Para mais informações, consulte Carregar o conteúdo do diretório com o AzCopy e Autorizar o AzCopy usando a CLI do Azure.

Para um uploader rodando em uma VM Azure, você pode autorizar o AzCopy com uma identidade gerenciada. Mantenha o contêiner privado e remova as atribuições temporárias de funções de uploader após a preparação. Aguarde até que novas atribuições de funções sejam propagadas; não contorne erros de autorização adicionando chaves de armazenamento ou segredos do cliente.

Registre a revisão do modelo e as versões Blob ou ETags. A localização do modelo Run:ai é az://<container>/<model-prefix>. Mantenha esses arquivos inalterados entre cargas frias e quentes. Para outro teste a frio, use outro novo prefixo em vez de expulsar dados de um cache compartilhado.

Preparar a imagem da carga de trabalho sem o ImageVolume

Instale dependências durante a construção da imagem, não na inicialização do pod. Mantenha sua aplicação existente, imagem base e ponto de entrada. Use o gerenciador de pacotes do aplicativo e o fluxo de trabalho de requisitos ou restrições para preservar dependências compatíveis, incluindo Torch, CUDA e NumPy.

Use uma imagem vLLM com GPU e versões Torch e CUDA compatíveis com seus nós de GPU e drivers NVIDIA. Verifique os pacotes core do Run:ai e de backend do Azure instalados na imagem antes de adicionar dependências; nem toda imagem vLLM inclui o backend do Azure.

Resolva conflitos de dependências na imagem da sua carga de trabalho antes de implantar. A pip check etapa da seção seguinte deve ser concluída com sucesso. Use as restrições de dependência do seu aplicativo para preservar a compatibilidade com outros pacotes instalados.

  1. Se sua imagem ainda não contém pacotes compatíveis do núcleo Run:ai e do backend do Azure, adicione a seguinte instrução ao seu Dockerfile:

    RUN python3 -m pip install --no-cache-dir "runai-model-streamer[azure]==0.17.0"
    
  2. Instale o pacote cliente público DACS, que fornece as bibliotecas nativas do cliente, nesse mesmo ambiente Python:

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

    O Azure extra do Run:ai não instala as bibliotecas clientes do DACS. Se sua aplicação já tiver pacotes Run:ai compatíveis, apenas a instalação do pacote cliente DACS é necessária.

  3. Construa e faça push usando seu Dockerfile e contexto de build existentes. Execute os seguintes comandos em Bash na sua máquina de preparação. Este exemplo é compilado para nós 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. Na mesma sessão do Bash, resolva o caminho da biblioteca nativa a partir da imagem construída:

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

    Use o caminho absoluto impresso ao configurar o workload. Mantenha a instalação completa do cliente, incluindo as bibliotecas nativas relacionadas.

Prefira um digest imutável da imagem ao implantar. Atualizar o cliente incorporado requer reconstruir e reimplantar a imagem da carga de trabalho.

Configurar autenticação do Blob

Use a identidade da carga de trabalho do AKS para autenticação de blobs. O exemplo de implantação usa esse método com o Storage Blob Data Reader com escopo no contêiner do modelo. A permissão de escrita do uploader não é necessária para inferência. Para outros métodos de autenticação, veja autenticação do Azure na documentação do Run:ai Model Streamer.

Usar a identidade da carga de trabalho do AKS

O exemplo de implantação usa a runai-reader ServiceAccount no runai-dacs namespace. Conclua os seguintes passos antes de implantar a carga de trabalho:

  1. Ative o emissor OIDC e o ID de carga de trabalho do Microsoft Entra no seu cluster AKS existente, caso ainda não estejam ativados.

  2. Recupere a URL do emissor do OIDC.

  3. Crie uma identidade gerenciada ou selecione uma identidade existente.

  4. Se o runai-dacs namespace ainda não existir, crie-o.

    kubectl create namespace runai-dacs
    
  5. Crie uma Conta de Serviço Kubernetes anotada com o ID do cliente dessa identidade.

  6. Crie a credencial federada de identidade para o namespace exato e ServiceAccount. Você não precisa completar as etapas seguintes do Key Vault.

Atribua o papel de leitor de Blob à identidade gerenciada federada à ServiceAccount do seu aplicativo. Para um exemplo de atribuição com escopo de contêiner, veja Conceder acesso de leitura aos dados do modelo, substituindo essa identidade pela identidade kubelet do quickstart.

O Pod deve selecionar a ServiceAccount e ter o azure.workload.identity/use: "true" rótulo. O AKS injeta as configurações de identidade e o token projetado. Não adicione manualmente segredos de cliente ou chaves de conta de armazenamento.

Configure o acesso por pull de imagem separadamente

Para imagens particulares de ACR, configure as permissões de pull kubelet conforme descrito em Adicionar o cliente a uma imagem de carga de trabalho. Use AcrPull para RBAC clássico. Para um registro habilitado por ABAC, use Container Registry Repository Reader com acesso apropriado ao repositório. Não use --attach-acr para esse registro.

O acesso por leitura de blobs para a identidade do aplicativo não concede acesso para pull de imagem ao kubelet. Para o ImageVolume, a permissão de extração deve abranger tanto a carga de trabalho quanto as imagens do cliente, incluindo registries ou repositórios separados, quando aplicável.

Configurar e implantar a carga de trabalho

Defina essas quatro variáveis de aplicação antes de iniciar o vLLM. Eles são separados das configurações de identidade fornecidas pelo seu método de autenticação:

Variável de ambiente Purpose
AZURE_STORAGE_ACCOUNT_NAME Conta de armazenamento contendo o modelo.
CACHE_DISCOVERY_URL Nome de host de descoberta DACS, como cache-sample-discovery.<namespace>.svc.cluster.local.
CACHE_SERVER_PORT Porta de cache, normalmente 9065.
RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB Caminho absoluto de biblioteca nativa resolvido a partir da sua imagem de carga de trabalho.

Important

A descoberta de cache não é opcional. Um carregamento de modelo pode ter sucesso lendo o Armazenamento de Blobs diretamente quando o cache não está configurado. Com o backend 0.17.0do Run:ai Azure, especifique também explicitamente o caminho da biblioteca nativa, em vez de depender da descoberta automática.

Use o formato URI do modelo do Run:ai, az://<container>/<model-prefix>, com a conta fornecida por AZURE_STORAGE_ACCOUNT_NAME. Esse formato URI difere do URI canônico do cliente Python nativo, que inclui o nome de host da conta.

Substitua os marcadores no exemplo a seguir e salve como runai-dacs-pod.yaml. Use o prefixo do modelo do seu upload e o caminho da biblioteca nativa impresso pela imagem criada. O exemplo usa identidade de carga de trabalho e não contém ImageVolume nem contêiner de inicialização:

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

Esses recursos ilustram um modelo pequeno, não um modelo 30B. Preserve o agendamento exigido, recursos, sondas, memória compartilhada e outros argumentos de vLLM da sua carga de trabalho. Ajuste a contagem de GPUs, paralelismo tensorial, comprimento do modelo e tamanho da memória para o seu modelo. Para um Deployment ou StatefulSet, aplique rótulos de Pod em spec.template.metadata e configurações de Pod em spec.template.spec.

A primeira implantação inicia o vLLM e carrega o modelo antes que o Pod fique pronto. Para uma comparação de cold cache, complete estes passos em ordem:

  1. Selecione dados do modelo que o cache não tenha lido, como o prefixo novo do procedimento de upload. Não remova dados de um cache compartilhado.

  2. Antes de implantar o Pod de aplicação, capture um snapshot de métricas de referência de cada Pod de servidor de cache, conforme descrito em Monitorar o acelerador distribuído para armazenamento em nuvem. Registre o carimbo de tempo e o cache_server_cache_size_bytes, cache_server_upload_request_size_bytes_sum e cache_server_download_request_size_bytes_sum de cada servidor.

  3. Implante e inspecione o pod aceito:

    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
    

Verifique o tempo de execução da carga de trabalho

Execute essa verificação dentro do contêiner da aplicação vLLM, usando o executável em Python da aplicação. Ele verifica a consistência dos pacotes e o carregamento da biblioteca nativa, não a autenticação Blob ou o uso do cache:

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

Resolva erros antes de continuar. Para a implantação da GPU, também verifique a visibilidade da GPU e os logs do motor do vLLM para confirmar a execução do CUDA e o modelo dtype pretendido. A prontidão ou um carregamento bem-sucedido da biblioteca sozinhos não provam a execução da GPU ou o uso do cache do DACS.

Verifique o comportamento do cache frio e quente

Use a linha de base de métricas de pré-implantação coletada em Configurar e implantar a carga de trabalho. A carga do modelo realizada durante a implantação é a carga a frio.

Verifique a carga fria

Inspecione o log do aplicativo:

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

Procure o ReadChunk stats nativo. RemoteClient conta leituras de peso do repositório de backup; RemoteCache conta leituras em cache remoto. Alguns acessos de cache durante a primeira carga são normais porque leituras anteriores podem preencher dados. As ocorrências de cache GetProperties descrevem metadados, não as ocorrências de pesos do modelo.

Envie um pedido de inferência:

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

Confirme leituras diferentes de zero no armazenamento de apoio a frio. Mantenha o Pod da aplicação rodando enquanto você verifica a população do cache assíncrono:

  1. Obtenha amostras de cache_server_upload_request_size_bytes_sum e cache_server_cache_size_bytes de cada Pod de servidor de cache para o recurso de cache selecionado a cada 10 segundos, por até cinco minutos. Use o procedimento do ponto de extremidade de métricas. Use amostras novas, não cópias repetidas de uma coleta extraída armazenada.
  2. Compare as amostras com a linha de base pré-implantação. Exigir um aumento no total de bytes enviados e no total de bytes em cache nesses servidores. Não exija que todo servidor receba dados.
  3. Espere até que o contador de bytes enviados de cada servidor permaneça inalterado por três intervalos de amostragem consecutivos após o aumento total no upload. Confirme que nenhum servidor reiniciou e nenhum contador foi redefinido durante a comparação.
  4. Salve essa amostra final como o instantâneo após o resfriamento, incluindo cache_server_download_request_size_bytes_sum de cada servidor como linha de base para a carga a quente.

Se essas condições não forem atendidas em cinco minutos, pare a comparação em vez de tratar o cache como quente. Verifique erros de upload do cliente, saúde do servidor de cache e tráfego contínuo antes de tentar novamente. Modelos maiores podem precisar de uma janela de observação mais longa. Uma métrica faltando ou uma extração com falha não significa valor zero nem evidência de que os uploads terminaram.

Contadores estáveis são um sinal de prontidão, não prova de que todo bloco de modelo está armazenado em cache. O tráfego de cache compartilhado também pode impedir a estabilização ou explicar os aumentos. Use uma janela de validação silenciosa sempre que possível e exija as verificações de warm-read do fresh-Pod abaixo para confirmar o reuso do cache distribuído.

Verifique uma carga a quente em um pod novo

Salve o log a frio e o UID do pod. Recrie apenas o pod de aplicação usando os mesmos arquivos de modelo, endpoint de cache, biblioteca e tamanho do bloco:

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

Repita a verificação de tempo de execução e o pedido de inferência. Depois, capture um instantâneo das métricas após o aquecimento de cada servidor de cache. Confirma diferentes UIDs de pod, uma maior taxa de ocorrência no cache de origem remota e menos leituras no backing store. Compare cache_server_download_request_size_bytes_sum com o instantâneo após o resfriamento para corroborar as leituras de cache quente. Um processo novo evita confundir pré-busca local em memória com um acerto de cache distribuído.

A taxa de acerto de fonte remota é RemoteCache / (RemoteCache + RemoteClient), excluindo a pré-busca local. Use o instantâneo cumulativo mais recente para cada processo nativo, ponto de montagem e tamanho de parte; não faça soma de amostras periódicas. Exclua medições afetadas por reinicializações do servidor de cache ou resetações de contadores. Contadores de servidores compartilhados corroboram os logs de aplicação, mas não atribuem todo o tráfego a uma única carga de trabalho.

Os metadados ainda podem acessar o Armazenamento de Blobs mesmo quando contadores de leituras ponderadas a quente não mostram leituras no backing store.

Monte as bibliotecas de clientes do DACS com o ImageVolume

Use esta alternativa apenas quando o runtime do nó oferecer suporte a ImageVolume e você tiver uma imagem de cliente que possa ser obtida, criada a partir do pacote wheel público do DACS. Não presuma que uma imagem ou tag proposta do MCR foi publicada. Se não houver uma imagem do cliente adequada disponível, use o procedimento workload-image da seção anterior.

Sua imagem vLLM da GPU já deve conter pacotes compatíveis do Run:ai core e Azure. Você não precisa instalar o pacote cliente DACS no ambiente Python dele porque o volume de imagem fornece as bibliotecas clientes nativas.

Adapte o exemplo do pod da seguinte forma:

  1. Mantenha sua imagem vLLM compatível existente em vez de reconstruí-la para instalar as bibliotecas clientes do DACS.

  2. Adicione um volume de imagem do cliente somente leitura e monte:

    # 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. Defina RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB como o caminho absoluto de libStorageDirect.so em /opt/cache-client, com base no layout real dessa imagem. Preserve as dependências nativas de pacotes irmãos.

  4. Implante e confirme que o volume da imagem e a montagem somente leitura permanecem na especificação do pod live. Verifique se o arquivo existe, depois execute o mesmo runtime do contêiner de aplicativo e as verificações a frio/quente.

Alguns clusters mais antigos podem remover campos e montagens de image-volume não compatíveis do pod admitido. A versão do Kubernetes e o dry-run do servidor sozinhos não são suficientes. Não instale nem pré-carregue uma versão conflitante das bibliotecas cliente DACS junto com o cliente montado; um caminho absoluto de biblioteca não isola seu namespace nativo de dependências.

Otimizar o desempenho de leitura

Por que ajustar o tamanho da parte? Modelos têm diferentes tamanhos de tensor e padrões de leitura, então um único tamanho de parte pode não oferecer o melhor desempenho ao carregar modelos para todos os modelos. Partes muito grandes obtêm mais dados do que a leitura precisa e aumentam o buffering. Partes subdimensionadas aumentam a quantidade de solicitações e a sobrecarga por solicitação. Escolher um tamanho adequado aos tensores comuns do modelo equilibra esses custos, melhora a taxa de transferência efetiva de leitura de peso e reduz o tempo de carregamento do modelo, incluindo cargas a quente provenientes de DACS. Trate as seguintes recomendações como pontos de partida e meça separadamente os tempos de carregamento frio e quente. Os ganhos dependem do modelo, da simultaneidade do carregador e do desempenho do armazenamento e da rede.

Escolha o tamanho da parte usando as seguintes recomendações específicas para cada modelo. Para outros modelos, inspecione os metadados do tensor conforme descrito na próxima seção ou use 32 MiB se a inspeção dos metadados do tensor não estiver disponível.

Modelo Tamanho recomendado da parte Valor em 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 quando a inspeção de metadados não está disponível 32 MiB 33554432

Escolha um tamanho de pedaço para outro modelo

Use um visualizador de metadados Safetensors ou uma ferramenta de inspeção de cabeçalhos para inspecionar todos os fragmentos de modelo, sem carregar conteúdos de tensores:

  1. Encontre o tamanho ocupado em bytes de cada tensor: seu deslocamento final de dados menos o deslocamento inicial. Exclua a __metadata__ entrada.
  2. Trate todo tamanho acima de 32 MiB como 32 MiB antes de contar as ocorrências.
  3. Selecione o tamanho que ocorre com mais frequência em todos os fragmentos. Se vários tamanhos ocorrerem com a mesma frequência, escolha o maior.
  4. Se o tamanho selecionado for inferior a 2 MiB, use 2 MiB.

Por exemplo, se tensores de 3 MiB ocorrerem com mais frequência após o capping, use 3 MiB (3145728bytes). Se a inspeção de metadados não estiver disponível, use 32 MiB (33554432bytes).

Configurar o aplicativo

Defina ambos RUNAI_STREAMER_CHUNK_BYTESIZE e SI_streamingChunkSize para o valor de byte resultante no ambiente do contêiner da aplicação. Por exemplo, para uma recomendação de 3 MiB:

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

Defina esses valores explicitamente; a tabela descreve recomendações, não a detecção automática de modelos ou padrões embutidos. Recrie o pod do aplicativo depois de alterá-lo; servidores de cache não precisam ser reiniciados. Leitores e tarefas de população que compartilham dados em cache devem usar o mesmo tamanho de bloco.

O tamanho de leitura do Run:ai e o tamanho nativo do bloco de cache são controles separados, configurados juntos acima. Avalie a recomendação com sua carga de trabalho e ajuste a concorrência do loader separadamente. Compare as cargas frias e quentes separadamente. Alterar o tamanho do bloco de cache cria chaves de cache diferentes e pode aumentar temporariamente a ocupação do cache. Mude uma configuração de cada vez e meça o tempo de carregamento, contadores nativos, métricas de cache, CPU, GPU e memória do host, e uso da rede. O alinhamento do tensor sozinho não garante melhor desempenho.

Warning

O orçamento padrão de buffer assíncrono de upload do cliente nativo público é de 400 GiB em 0.1.0. Não é uma pré-realocação nem um limite seguro de memória de pod. A população a frio de modelos grandes pode esgotar um pod menor. Para cargas de trabalho com restrições de memória, teste o preenchimento síncrono (SI_cacheEnableSyncUpload=true) ou um orçamento limitado de upload assíncrono (SI_cacheMaxUploadBufferSizePerProcessGB). Preparo do modelo de orçamento, buffers nativos de upload/prefetch, memória GPU e /dev/shm separadamente. Essas salvaguardas são configurações opcionais específicas de carga de trabalho, não requisitos adicionais para o exemplo de modelos pequenos.

Troubleshoot

Sintoma Verificação
Falha ao baixar a imagem Permissões de pull do Kubelet, modo de permissão do registro, digest da imagem e acesso à rede.
A biblioteca nativa não carrega Ambiente Python de aplicação, caminho explícito, compatibilidade glibc e bibliotecas nativas irmãs.
Falha na autorização do Blob Identidade selecionada, função de leitor, propagação de função, federação e rótulo de Pod. Para outros métodos de autenticação, siga as orientações de autenticação do Azure indicadas anteriormente.
O modelo carrega sem tráfego de cache As configurações de descoberta, o carregamento do provedor, a acessibilidade de DNS/rede e os contadores nativos de leitura de dados.
Carregamentos a quente ainda leem dados do Blob Conclusão da população, versões do Blob, tamanhos de partes correspondentes, remoções e leituras parciais.
ImageVolume está ausente Campos de pod ao vivo e suporte a nós/runtime; use o método incorporado, caso não estejam disponíveis.
O pod é encerrado por falta de memória (OOM) Memória de modelagem e staging, buffers nativos, tamanho do cache GPU/KV e /dev/shm.

Para uma comparação direta separada com Blob, defina RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 e recrie um Pod de teste. Configurar para 1 faz com que falhas de carregamento do provedor façam a inicialização falhar, em vez de recorrer automaticamente. Nenhuma das configurações comprova acertos no cache; inspecione os contadores de leitura de dados.

Limpar o exemplo

Se você criou o exemplo independente do Pod, delete-o quando terminar:

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

Remova apenas prefixos de modelos, imagens, identidades, federação, namespaces e atribuições de funções que você criou para este exemplo e que não precisa mais. Não exclua uma identidade ou um cache compartilhado existente. Os dados do modelo retidos agora estão em cache aquecido; use um prefixo novo para outra validação de cold-cache.

Próximas Etapas