Utilize o acelerador distribuído para armazenamento na cloud com o Run:ai Model Streamer (pré-visualização)

O Run:ai Model Streamer lê os tensores do modelo em simultâneo e transmite-os para a memória da GPU, sobrepondo leituras do armazenamento às transferências da CPU para a GPU. Esta capacidade pode reduzir o tempo de carregamento do modelo e reduzir o tempo de inatividade da GPU durante o arranque e escalabilidade do servidor de inferência. Use-a para carregar modelos SafeTensors a partir do Armazenamento de Blobs do Azure no vLLM porque suporta carregamento direto de armazenamento de objetos e integra-se com o carregador de modelos do vLLM. Para a integração upstream, veja Carregar modelos com o Run:ai Model Streamer.

Ao utilizar o acelerador distribuído para cloud storage (DACS), este caminho de carregamento pode também reutilizar dados de modelos armazenados em cache entre cargas de trabalho. O vLLM utiliza o backend Azure do Run:ai para carregar a biblioteca cliente nativa do DACS. As leituras recuperam dados em cache ou obtêm os dados em falta 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 workload. Não requer uma imagem cliente DACS separada nem suporte Kubernetes ImageVolume.

Conclua Introdução ao acelerador distribuído para armazenamento na nuvem no AKS antes de utilizar este artigo. Para fornecer as bibliotecas clientes DACS sem reconstruir a imagem da carga de trabalho, veja Montar bibliotecas clientes DACS com ImageVolume.

Prerequisites

  • Uma implementação DACS existente e o seu hostname do serviço de deteção.
  • Um pool de nós de GPU AKS com drivers NVIDIA compatíveis, um plugin de dispositivo e memória GPU suficiente para o teu modelo. O exemplo seguinte utiliza 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 Microsoft Entra ativados. Veja Ativar emissor OIDC e ID de carga de trabalho Microsoft Entra num cluster AKS.
  • Uma imagem vLLM de GPU compatível e um ambiente Linux com glibc 2.35 ou mais recente. Usa o mesmo ambiente Python que a tua aplicação.
  • Um contentor privado de Blob para ficheiros de modelos.
  • Um utilizador de carregamento separado ou identidade gerida com a função Storage Blob Data Contributor no contentor do modelo.
  • Uma identidade de inferência com o Storage Blob Data Reader no contentor do modelo. Em Configurar autenticação do Blob, configure um método.
  • Permissão para criar e enviar a imagem da carga de trabalho, e permissão para o AKS obter a imagem.
  • CLI do Azure, AzCopy v10 e a CLI Hugging Face na tua máquina de preparação caso precises de carregar um modelo.

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

Carregar ficheiros de modelo para o Armazenamento de Blobs

Ignore esta secção se o modelo completo já estiver no seu contentor privado. Para um teste de cold cache, usa um prefixo de modelo que não tenhas consultado através do DACS.

Utilize a identidade de carregamento para este procedimento, não a identidade de inferência. Para atribuições de papéis com âmbito de contentor, veja Atribuir um papel do Azure para acesso a dados de blobs. O plano Owner de controlo do Azure ou Contributor sozinho não concede acesso a dados Blob através do Microsoft Entra ID.

Descarregue o modelo

O exemplo seguinte descarrega os ficheiros de inferência para o SmolLM2-135M-Instruct numa revisão fixa. O seu model card identifica a licença como Apache-2.0. Instale a CLI do Hugging Face e depois 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 um comando da CLI atual hf cache verify para verificar os ficheiros descarregados, comparando-os com os checksums do Hub:

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

Como este download seleciona apenas ficheiros de inferência, a verificação pode reportar ficheiros de repositório em falta, como variantes de modelo não utilizadas. Também pode reportar metadados locais adicionais de download do Hugging Face. Estas mensagens não são falhas de checksum. Investigue ficheiros inesperados ou incompatibilidades de soma de verificação antes de carregar.

Para outro modelo, inclua todos os fragmentos SafeTensors e qualquer índice de peso, configuração de modelo e geração, ficheiros tokenizer e ficheiros de licença e atribuição aplicáveis. Mantenha a estrutura de diretórios necessária. Não coloque em staging variantes ONNX não relacionadas, checkpoints de treino, ficheiros de otimizador ou credenciais.

Transferir com o AzCopy

Instala AzCopy v10. Inicie sessão através do CLI do Azure como utilizador carregador, depois copie o conteúdo do diretório local para um novo prefixo 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 carácter universal entre aspas copia o conteúdo do diretório diretamente para o prefixo sem adicionar um nível de diretório local. As exclusões ometem metadados de download e Git. Continue apenas depois de o AzCopy reportar que não houve transferências falhadas e o destino conter todos os ficheiros necessários. Para mais informações, consulte Carregar conteúdos do diretório com AzCopy e Autorizar AzCopy usando CLI do Azure.

Para um carregador a correr numa VM Azure, pode, em vez disso, autorizar o AzCopy com uma identidade gerida. Mantenha o contentor privado e remova as atribuições temporárias de funções de uploader após a preparação. Permitir tempo para que novas atribuições de funções se propaguem; não contorne erros de autorização adicionando chaves de armazenamento ou segredos de cliente.

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

Preparar a imagem da carga de trabalho sem o ImageVolume

Instala dependências durante a construção da imagem, não no arranque do pod. Mantém a tua aplicação existente, a imagem base e o ponto de entrada. Utilize o gestor de pacotes da aplicação e o fluxo de trabalho de requisitos ou de restrições para preservar dependências compatíveis, incluindo Torch, CUDA e NumPy.

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

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

  1. Se a sua imagem ainda não contiver pacotes compatíveis de núcleo Run:ai e 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 DACS. Se a sua aplicação já tiver pacotes Run:ai compatíveis, apenas é necessária a instalação do pacote cliente DACS.

  3. Constrói e faz push usando o teu Dockerfile e contexto de construção existentes. Executa os seguintes comandos no Bash na tua 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, resolve 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)'
    

    Utilize o caminho absoluto impresso ao configurar a carga de trabalho. Mantém a instalação completa do cliente, incluindo as bibliotecas nativas associadas.

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

Configurar autenticação de Blob

Utilize a identidade da carga de trabalho do AKS para autenticação de Blob. O exemplo de implementação utiliza este método com Storage Blob Data Reader com âmbito no contentor do modelo. A permissão de escrita do uploader não é necessária para inferência. Para outros métodos de autenticação, consulte autenticação Azure na documentação do Run:ai Model Streamer.

Utilize a identidade da carga de trabalho do AKS

O exemplo de implementação utiliza a runai-reader ServiceAccount no runai-dacs namespace. Conclua os seguintes passos antes de implementar a carga de trabalho:

  1. Ativa o emissor OIDC e o ID de carga de trabalho Microsoft Entra no teu cluster AKS existente, se ainda não estiverem ativados.

  2. Recuperar a URL do emissor do OIDC.

  3. Crie uma identidade gerida 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 Kubernetes ServiceAccount anotada com o ID do cliente dessa identidade.

  6. Crie a credencial de identidade federada para o namespace exato e ServiceAccount. Não precisas de completar os passos seguintes do Key Vault.

Atribua o papel de leitor Blob à identidade gerida federada à ServiceAccount da sua aplicação. Para um exemplo de atribuição com âmbito de contentor, veja Conceder acesso de leitura aos dados do modelo, substituindo esta identidade pela identidade kubelet do início rápido.

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

Configure separadamente o acesso para pull de imagens

Para imagens privadas de ACR, configure as permissões de pull da identidade kubelet conforme descrito em Adicionar o cliente a uma imagem de carga de trabalho. Utilize AcrPull para o clássico RBAC. Para um registo com ABAC habilitado, utilize Container Registry Repository Reader com o acesso adequado ao repositório. Não uses --attach-acr para esse registo.

O acesso por leitura de blobs para a identidade da aplicação não concede acesso para obter imagens ao kubelet. Para o ImageVolume, o acesso de extração deve abranger tanto a carga de trabalho como as imagens do cliente, incluindo registos ou repositórios separados quando aplicável.

Configurar e implementar a carga de trabalho

Defina estas quatro variáveis de aplicação antes de iniciar o vLLM. São separadas das definições de identidade fornecidas pelo seu método de autenticação:

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

Importante

A descoberta de cache não é opcional. Uma carga de modelo pode ter sucesso ao ler o Armazenamento de Blobs diretamente quando a cache não está configurada. Com o backend 0.17.0Run:ai Azure, também especifique 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 através de AZURE_STORAGE_ACCOUNT_NAME. Este formato URI difere do URI canónico do cliente Python nativo, que inclui o nome de host da conta.

Substitua os marcadores no exemplo seguinte e guarde-o como runai-dacs-pod.yaml. Usa o prefixo do modelo do teu upload e o caminho da biblioteca nativa impresso pela imagem construída. O exemplo utiliza a identidade da carga de trabalho e não contém ImageVolume nem init container:

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

Estes recursos ilustram um modelo pequeno, não um modelo 30B. Preserve o agendamento necessário, recursos, sondas, memória partilhada e outros argumentos vLLM exigidos pela sua carga de trabalho. Ajusta o número de GPUs, paralelismo tensorial, comprimento do modelo e dimensionamento da memória para o teu modelo. Para um Deployment ou StatefulSet, aplique etiquetas de Pod em spec.template.metadata e definições de Pod em spec.template.spec.

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

  1. Selecione dados do modelo que a cache não tenha lido, como o prefixo novo do procedimento de carregamento. Não removas dados de uma cache partilhada.

  2. Antes de implementar o Pod da aplicação, capture um snapshot de métricas de referência de cada Pod de servidor de cache, conforme descrito em Monitorizar o acelerador distribuído para armazenamento na cloud. Regista o carimbo temporal e cache_server_download_request_size_bytes_sum, cache_server_cache_size_bytes e cache_server_upload_request_size_bytes_sum de cada servidor.

  3. Implemente e inspecione o Pod aceite:

    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 runtime da carga de trabalho

Execute esta verificação dentro do contentor da aplicação vLLM, usando o executável Python da aplicação. Verifica a consistência dos pacotes e o carregamento da biblioteca nativa, não a autenticação por Blob ou o uso da 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 implementação da GPU, verifique também a visibilidade da GPU e os registos do motor do vLLM para confirmar a execução do CUDA e o dtype pretendido do modelo. A prontidão ou um carregamento bem-sucedido da biblioteca por si só não provam a execução da GPU ou o uso da cache do DACS.

Verificar o comportamento das caches frias e quentes

Utilize a linha de base das métricas de pré-implementação recolhidas em Configurar e implementar a carga de trabalho. O carregamento do modelo realizado durante a implementação é o carregamento a frio.

Verifica o arranque a frio

Inspecionar o registo da aplicação:

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

Procure conteúdo nativo ReadChunk stats. RemoteClient conta as leituras de peso do backing store; RemoteCache conta as leituras da cache remota. Alguns acessos à cache durante a primeira carga são normais porque leituras anteriores podem preencher dados. GetProperties Os acertos em cache descrevem metadados, não os acessos aos 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 em cold backing-store. Mantenha o Pod da aplicação a funcionar enquanto verifica a população de cache assíncrona:

  1. Recolha cache_server_upload_request_size_bytes_sum e cache_server_cache_size_bytes a partir de cada Pod do servidor de cache selecionado para o recurso de cache selecionado a cada 10 segundos, durante até cinco minutos. Utilize o procedimento do endpoint de métricas. Utilize amostras frescas, não cópias repetidas de uma extração armazenada.
  2. Compare as amostras com a linha de base pré-implantação. Exigir um aumento no total de bytes carregados e no total de bytes em cache nesses servidores. Não exija que cada servidor receba dados.
  3. Espere até que o contador de bytes de upload de cada servidor permaneça inalterado durante três intervalos consecutivos de amostragem após o aumento total de upload. Confirma que nenhum servidor reiniciou nem houve reinicialização do contador durante a comparação.
  4. Guarda esta amostra final como snapshot pós-frio, incluindo cache_server_download_request_size_bytes_sum de cada servidor como linha de base para a carga quente.

Se estas condições não forem cumpridas em cinco minutos, pare a comparação em vez de considerar a cache aquecida. Verifique os erros de upload do cliente, a saúde do servidor de cache e o tráfego em curso antes de tentar novamente. Modelos maiores podem necessitar de uma janela de observação mais longa. Uma métrica em falta ou um scrape falhado não é valor zero nem prova de que os uploads terminaram.

Contadores estáveis são um sinal de prontidão, não prova de que todos os blocos do modelo estão armazenados em cache. O tráfego de cache partilhada também pode impedir a estabilização ou explicar aumentos. Use uma janela de validação discreta sempre que possível e exija as verificações de leitura em quente do fresh-Pod abaixo para confirmar a reutilização da cache distribuída.

Verifica um carregamento a quente num pod novo

Guarda o cold log e o UID do pod. Recrie apenas o pod da aplicação usando os mesmos ficheiros 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 em tempo de execução e o pedido de inferência. Depois, capture um snapshot de métricas pós-aquecimento de cada servidor de cache. Confirme diferentes UIDs de pod, uma taxa de acerto aumentada na cache de origem remota e menos leituras na backing store. Compare cache_server_download_request_size_bytes_sum com o snapshot após arranque a frio para corroborar as leituras da cache quente. Um processo novo evita confundir o prefetch local em memória com um acerto na cache distribuída.

A taxa de acerto em fonte remota é RemoteCache / (RemoteCache + RemoteClient), excluindo a pré-busca local. Utilize o snapshot cumulativo mais recente para cada processo nativo, montagem e tamanho do bloco; não faça soma de amostras periódicas. Exclua medições afetadas por reinicios do servidor de cache ou resets de contadores. Contadores de servidores partilhados corroboram os registos da aplicação, mas não atribuem todo o tráfego a uma única carga de trabalho.

Os metadados ainda podem contactar o Armazenamento de Blobs mesmo quando os contadores de leituras ponderadas a quente mostram zero leituras do armazenamento de suporte.

Montar bibliotecas clientes DACS com o ImageVolume

Use esta alternativa apenas quando o runtime do nó suportar o ImageVolume e tiver uma imagem de cliente passível de pull construída a partir do wheel público do DACS. Não presuma que uma imagem ou tag proposta de MCR foi publicada. Se não houver uma imagem cliente adequada disponível, use o procedimento workload-image na secção anterior.

A imagem do vLLM da sua GPU já deve conter pacotes compatíveis com o núcleo Run:ai e o Azure. Não precisas de instalar o pacote cliente DACS no teu ambiente Python porque o volume de imagem fornece as bibliotecas nativas do cliente.

Adapte o exemplo do pod da seguinte forma:

  1. Mantém a tua imagem vLLM compatível existente em vez de a reconstruir para instalar as bibliotecas do cliente DACS.

  2. Adicione um volume de imagem do cliente apenas de 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 para o caminho absoluto de libStorageDirect.so sob /opt/cache-client, com base na disposição real dessa imagem. Preservar as dependências nativas de elementos irmãos.

  4. Implemente e confirme que o volume da imagem e a montagem só de leitura permanecem na especificação do pod live. Verifica se o ficheiro existe, depois executa o mesmo runtime do contentor da aplicação e faz as verificações a frio/quente.

Alguns clusters mais antigos podem remover campos e montagens de volume de imagem não suportados do pod admitido pelo sistema. A versão 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 juntamente com o cliente montado; um caminho absoluto de biblioteca não isola o seu espaço de nomes nativo de dependências.

Otimizar o desempenho de leitura

Por que ajustar o tamanho do bloco? Os modelos têm diferentes tamanhos de tensor e padrões de leitura, pelo que um tamanho de bloco pode não proporcionar o melhor desempenho no carregamento do modelo para todos os modelos. Blocos sobredimensionados vão buscar mais dados do que o necessário para uma leitura e aumentam a necessidade de memória intermédia. Blocos demasiado pequenos aumentam o número de pedidos e a sobrecarga por pedido. Escolher um tamanho adequado aos tensores que ocorrem mais frequentemente no modelo equilibra estes custos, melhora o débito efetivo de leitura de pesos e reduz o tempo de carregamento do modelo, incluindo carregamentos a quente a partir do DACS. Considere as seguintes recomendações como pontos de partida e meça separadamente os tempos de carregamento a frio e a quente. Os ganhos dependem do modelo, da concorrência do carregador e do desempenho do armazenamento e da rede.

Escolha o tamanho do bloco seguindo as seguintes recomendações específicas para cada modelo. Para outros modelos, inspecione os metadados do tensor conforme descrito na secção seguinte, ou utilize 32 MiB se essa inspeção não estiver disponível.

Modelo Tamanho recomendado do bloco 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 bloco para outro modelo

Utilize 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 tensoriais:

  1. Encontre o tamanho de cada tensor em bytes: o seu deslocamento final de dados menos o deslocamento inicial. Exclua a __metadata__ entrada.
  2. Trate todos os tamanhos 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 os 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, utilize 32 MiB (33554432bytes).

Configurar a aplicação

Defina RUNAI_STREAMER_CHUNK_BYTESIZE e SI_streamingChunkSize com o valor de byte resultante no ambiente do contentor 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 estes valores explicitamente; a tabela descreve recomendações, não a deteção automática de modelos ou os valores predefinidos incorporados. Recria o Pod da aplicação depois dessas alterações; os servidores de cache não precisam de ser reiniciados. Leitores e tarefas de população que partilham 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 controlos separados, configurados em conjunto acima. Compara a recomendação com a tua carga de trabalho e ajusta a concorrência do loader separadamente. Compare as cargas a frio e a quente separadamente. Alterar o tamanho do bloco de cache cria chaves de cache diferentes e pode aumentar temporariamente a ocupação da cache. Muda uma definição de cada vez e mede o tempo de carregamento, contadores nativos, métricas de cache, CPU, GPU e memória do host, e uso na rede. O alinhamento tensorial por si só não garante melhor desempenho.

Warning

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

Troubleshoot

Symptom Cheque
Falha na solicitação da imagem Permissões de pull do Kubelet, modo de permissões de registo, digest de imagem e acesso à rede.
A biblioteca nativa não é carregada Ambiente Python de aplicação, caminho explícito, compatibilidade glibc e bibliotecas nativas irmãs.
Falha na autorização do blob Identidade selecionada, papel do leitor, propagação do papel, federação e rótulo do Pod. Para outros métodos de autenticação, siga as orientações de autenticação do Azure cuja ligação foi fornecida anteriormente.
O modelo carrega sem tráfego de cache Ambas as definições de descoberta, o carregamento de fornecedores, a acessibilidade DNS/rede e os contadores nativos de leitura de dados.
Os carregamentos a quente continuam a ler dados do Blob Conclusão do preenchimento, versões de Blob, tamanhos de blocos correspondentes, expulsões e leituras parciais.
O ImageVolume está em falta Campos Live Pod e suporte a nós/runtime; use o método integrado de origem se não estiver disponível.
O pod é terminado por OOM Memória de modelo e staging, buffers nativos, dimensionamento da GPU/KV-cache e /dev/shm.

Para uma comparação direta separada do Blob, defina RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 e recrie um Pod de teste. Defini-lo como 1 em vez disso faz com que falhas de carregamento do fornecedor falhem no arranque em vez de recuem em silêncio para uma alternativa. Nenhuma das definições comprova acessos à cache; inspecione os contadores de leitura de dados.

Limpa o exemplo

Se criaste o Pod de exemplo independente, apaga-o quando terminares:

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 criou para este exemplo e que já não precisa. Não apague uma cache ou identidade partilhada existente. Os dados do modelo retidos estão agora em cache; use um prefixo novo para outra validação de cache fria.

Passos seguintes