Run:ai Model Streamer を使用して、クラウド ストレージ向けの分散型アクセラレータを使用する (プレビュー)

Run:ai Model Streamer はモデルテンソルを同時に読み取り、GPUメモリにストリーミングします。ストレージの読み取りとCPUからGPUへの転送を重ね合わせます。 この機能は、推論サーバーの起動やスケールアウト時のモデルロード時間を短縮し、GPU のアイドル時間を短縮できます。Azure Blob Storage の SafeTensor モデルを vLLM にロードするために使うと、直接オブジェクトストレージの読み込みをサポートし、vLLM のモデル ローダーと統合されます。 アップストリーム統合については、 Run:ai Model Streamerでのモデルの読み込みを参照してください。

クラウドストレージ用の分散アクセラレータ(DACS)を使用することで、このロードパスはワークロード間でキャッシュされたモデルデータを再利用することも可能です。 vLLMはRun:aiのAzureバックエンドを使ってDACSネイティブクライアントライブラリを読み込みます。 読み取りはキャッシュデータを取得したり、Blob Storage から欠落データを取得したりします。

この記事は Run:ai Model Streamer 0.17.0、公開パッケージの dacs-client==0.1.0、そして v0.1.0 サーバー ビルドを使用しています。 メインの手順では、依存関係をワークロード イメージにインストールします。 別途DACSクライアントイメージやKubernetesのImageVolumeサポートは必要ありません。

この記事を読む前に、AKS 上のクラウド ストレージ向け分散アクセラレータの開始方法に記載の手順をすべて完了させてください。 ワークロードイメージを再構築せずにDACSクライアントライブラリを提供するには、 ImageVolumeでDACSクライアントライブラリをマウントする方法をご覧ください。

Prerequisites

  • 既存のDACS展開とそのディスカバリーサービスのホスト名。
  • AKS GPU ノード プールで、対応する NVIDIA ドライバー、デバイス プラグイン、そしてモデルに合う十分な GPU メモリが必要です。 次の例では bfloat16 を使用していますが、これには互換性のある GPU が必要です。
  • ワークロード ID 認証については、OIDC 発行者および Microsoft Entra ワークロード ID が有効になっている AKS クラスターが必要です。 AKS クラスターで OIDC 発行者と Microsoft Entra ワークロード ID を有効にするをご覧ください。
  • 互換性のあるGPU vLLMイメージと、glibc 2.35以降のLinux環境が必要です。 アプリケーションと同じPython環境を使いましょう。
  • モデルファイル用のプライベートBlobコンテナです。
  • モデル コンテナー上で Storage Blob Data Contributor を持つ別個のアップローダー ユーザーまたはマネージド ID
  • モデル コンテナー上でストレージ BLOB データ閲覧者を持つ推論 ID。 Blob 認証を構成するで、1 つの方法を設定します。
  • ワークロード イメージをビルドおよびプッシュする許可と、AKS がそれをプルする許可。
  • モデルをアップロードする必要がある場合は、準備マシン上の Azure CLI、AzCopy v10、そして Hugging Face CLI が必要です。

モデル準備にはGPUは必要ありません。 また、互換性のあるアプリケーションイメージを持つCPUノード上でパッケージインストール、ネイティブライブラリの読み込み、Blob認証もチェックできます。 これらのチェックは GPU のスケジューリングやメモリ容量のサイジング、推論を検証するものではありません。

モデルファイルをBlob Storageにアップロードする

もし完全なモデルがすでにプライベートコンテナにあるなら、このセクションは飛ばしてください。 コールドキャッシュテストでは、DACS経由で読み取っていないモデルプレフィックスを使いましょう。

この手続きには推論識別子ではなく、アップローダーの識別子を使います。 コンテナ スコープのロール割り当てについては、「Blob データにアクセスするための Azure ロールを割り当てる」をご覧ください。 AzureコントロールプレーンOwnerやContributorだけではMicrosoft Entra IDを通じてブロブのデータアクセスは得られません。

モデルをダウンロード

以下の例は、SmolLM2-135M-Instruct の推論ファイルを固定リビジョンでダウンロードします。 モデルカードにはライセンスがApache-2.0と記載されています。 Hugging Face CLIをインストールして、次を実行してください:

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"

オプションとして、現在のCLIの hf cache verify コマンドを使ってダウンロードファイルをHubのチェックサムと照合して確認することもできます:

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

このダウンロードは推論ファイルのみを選択するため、検証は未使用のモデルバリアントなどのリポジトリファイルの欠落を報告できます。 また、追加のローカルHugging Faceダウンロードメタデータも報告できます。 これらのメッセージはチェックサムの失敗ではありません。 アップロード前に予期しないファイルやチェックサムの不一致を調べましょう。

別のモデルについては、すべてのSafeTensorsシャード、該当する重みインデックス、モデルおよび生成設定、トークナイザーファイル、ならびに該当するライセンスおよび帰属ファイルを含めます。 必要なディレクトリ構造を保持してください。 無関係な ONNX バリアント、トレーニングチェックポイント、オプティマイザファイル、または認証情報を配置しないでください。

AzCopyでアップロード

AzCopy v10をインストールしてください。 Azure CLIでアップローダーユーザーとしてサインインし、ローカルディレクトリの内容を新しい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"

引用符付きのワイルドカードは、ローカルディレクトリレベルを加えずにディレクトリの内容を直接プレフィックスにコピーします。 除外項目にはダウンロードや Git のメタデータが省かれています。 AzCopy が転送失敗を報告し、必要なファイルがすべて揃っている場合のみ継続してください。 詳細については、「AzCopy でディレクトリ内容をアップロードする」と「Azure CLI を使用して AzCopy を承認する」を参照してください。

Azure VM 上で動作するアップローダーの場合は、管理された ID で AzCopy を認証できます。 コンテナは非公開にし、準備後に一時的なアップローダーの役割割り当てを削除してください。 新しいロール割り当てが伝播するまでの時間を確保し、ストレージ キーやクライアント シークレットを追加して認証エラーを回避しないでください。

モデルのリビジョンとBlobバージョン、またはETagを記録します。 Run:aiのモデルの位置は az://<container>/<model-prefix>です。 これらのファイルはコールドロードとウォームロードの間、変更せずに保ちましょう。 もう一度コールドテストとして、共有キャッシュからデータを追い出すのではなく、別の新しいプレフィックスを使うのも良いでしょう。

ImageVolumeなしでワークロードイメージを準備する

依存関係はポッド起動時ではなく、イメージのビルド時にインストールします。 既存のアプリケーション、ベースイメージ、エントリーポイントを保持してください。 アプリケーションのパッケージ マネージャー、および要件や制約のワークフローを活用し、Torch、CUDA、NumPy を含む互換性のある依存関係を維持します。

GPU対応のvLLMイメージを使い、お使いのGPUノードおよびNVIDIAドライバーと互換性のあるTorchおよびCUDAのバージョンを使いましょう。 依存関係を追加する前に、イメージにインストールされているRun:aiコアとAzureバックエンドパッケージを確認してください。すべてのvLLMイメージにAzureバックエンドが含まれているわけではありません。

デプロイ前にワークロードイメージ内の依存性の競合を解決してください。 次のセクションの pip check ステップは無事に完了しなければなりません。 アプリケーションの依存制約を利用して、他のインストール済みパッケージとの互換性を維持しましょう。

  1. もしイメージにまだ互換性のあるRun:aiコアやAzureバックエンドパッケージが含まれていない場合は、Dockerファイルに以下の命令を追加してください:

    RUN python3 -m pip install --no-cache-dir "runai-model-streamer[azure]==0.17.0"
    
  2. ネイティブ クライアント ライブラリを提供するパブリック DACS クライアン トパッケージを同じ Python 環境にインストールします:

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

    Run:ai の Azure エクストラでは、DACS クライアント ライブラリはインストールされません。 もしアプリケーションにすでに対応するRun:aiパッケージがある場合は、DACSクライアントパッケージのインストールのみが必要です。

  3. 既存のDockerファイルとビルドコンテキストを使ってビルドとプッシュを行います。 準備機でBashの以下のコマンドを実行してください。 この例は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. 同じBashセッションで、ビルドイメージからネイティブライブラリパスを解決します:

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

    ワークロードの設定時は表示された絶対パスを使います。 クライアントの完全なインストールを維持し、関連ネイティブライブラリも含めます。

展開時には不変のイメージ ダイジェストを使用してください。 組み込みクライアントの更新には、ワークロードイメージを再構築・再デプロイする必要があります。

Blob認証の設定

Blob認証にはAKSワークロードアイデンティティを使いましょう。 デプロイの例では、モデルコンテナにスコープされた Storage Blob Data Reader を用いてこの手法を用いています。 アップローダーの書き込み許可は推論に必要ありません。 その他の認証方法については、Run:ai Model StreamerのドキュメントにあるAzure認証を参照してください。

AKS ワークロード ID を使用

デプロイの例では、runai-dacs 名前空間で runai-reader ServiceAccount を使用しています。 ワークロードを展開する前に以下のステップを完了してください:

  1. まだ有効になっていない場合は、既存の AKS クラスターで OIDC 発行者と Microsoft Entra ワークロード ID を有効にします。

  2. OIDC発行者のURLを取得してください。

  3. マネージドアイデンティティを作成するか、既存のアイデンティティを選択してください。

  4. runai-dacs名前空間がまだ存在しなければ、名前空間を作成してください。

    kubectl create namespace runai-dacs
    
  5. そのIDのクライアント ID で注釈を付けたKubernetesサービスアカウントを作成します。

  6. 正確な名前空間とServiceAccount用のフェデレーテッドID認証情報を作成します。 その後のKey Vaultの手順を完了する必要はありません。

Blobリーダーの役割を、 アプリケーションServiceAccountにフェデレーションされた管理IDに割り当てます。 コンテナ スコープの割り当ての例については、モデル データへの読み取りアクセスを許可するを参照し、この ID をクイックスタートの kubelet ID の代わりに使用してください。

ポッドは ServiceAccount を選択し、azure.workload.identity/use: "true" ラベルを付ける必要があります。 AKS は識別子設定と投影トークンを注入します。 クライアント シークレットやストレージ アカウント キーを手動で追加しないでください。

画像プルアクセスは別途設定してください

プライベート ACR イメージの場合は、「クライアントをワークロード イメージに追加する」で説明したように、kubelet ID のプル権限を設定します。 クラシックRBACには AcrPull を使いましょう。 ABAC対応レジストリの場合は、適切なリポジトリアクセスを持つ Container Registry Repository Reader を使用します。 そのレジストリには --attach-acr は使わないでください。

アプリケーションの ID に対する Blob-read アクセスでは、kubelet のイメージ プル アクセスは許可されません。 ImageVolumeの場合、プルアクセスはワークロードとクライアントイメージの両方をカバーし、該当する場合は別々のレジストリやリポジトリも含めて必要です。

ワークロードの設定と展開

vLLMを起動する前にこれら4つのアプリケーション変数を設定してください。 これらは認証方法が提供するID設定とは別です:

環境変数 Purpose
AZURE_STORAGE_ACCOUNT_NAME モデルを含むストレージアカウント。
CACHE_DISCOVERY_URL DACS の検出用ホスト名 (cache-sample-discovery.<namespace>.svc.cluster.local など)。
CACHE_SERVER_PORT キャッシュ ポート(通常は9065)
RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB ワークロード イメージから解決された絶対ネイティブ ライブラリ パス。

Important

キャッシュ発見はオプションではありません。 モデル ロードは、キャッシュが設定されていない場合に Blob Storage を直接読み込むことで成功することがあります。 Run:ai Azureバックエンド0.17.0では、自動検出に頼るのではなく、ネイティブライブラリのパスも明示的に指定してください。

Run:ai のモデル URI 形式 az://<container>/<model-prefix> を使用し、AZURE_STORAGE_ACCOUNT_NAME を通じて指定したアカウントを使用します。 このURI形式は、アカウントホスト名を含むネイティブPythonクライアントの標準的なURIとは異なります。

次の例のプレースホルダーを置き換え、 runai-dacs-pod.yamlとして保存してください。 アップロード時のモデル プレフィックスと、ビルドしたイメージが出力したネイティブ ライブラリ パスを使います。 この例ではワークロード ID を使用しており、ImageVolume も init コンテナも含みません。

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

これらの資料は30Bモデルではなく、小さなモデルを示しています。 ワークロードの必要なスケジューリング、リソース、プローブ、共有メモリ、その他のvLLM引数を保持してください。 GPU数、テンソル並列性、モデルの長さ、メモリサイズを調整してください。 Deployment や StatefulSet の場合は、spec.template.metadata の Podラベル、spec.template.spec の Pod 設定を適用します。

最初の展開はvLLMを起動し、ポッドが準備完了する前にモデルを読み込みます。 コールドキャッシュ比較のために、以下の手順を順番に行ってください:

  1. キャッシュが読み取っていないモデル データ、たとえばアップロード手順の最新のプレフィックスを選びます。 共有キャッシュからデータを追い出さないでください。

  2. アプリケーション Pod を展開する前に、クラウド ストレージ用分散アクセラレータの監視で説明されているように、各 cache-server Pod からベースライン メトリクス スナップショットを取得してください。 タイムスタンプと各サーバーの cache_server_upload_request_size_bytes_sum、 cache_server_download_request_size_bytes_sum、 cache_server_cache_size_bytesを記録します。

  3. 承認された Pod をデプロイして確認する:

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

ワークロードの実行時間を確認してください

このチェックはvLLMアプリケーションコンテナ内で、アプリケーションのPython実行ファイルを使って実行します。 パッケージの整合性やネイティブライブラリの読み込みを検証し、Blob 認証やキャッシュの使用を検証しません。

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

続行する前にエラーを解決してください。 GPUデプロイメントについては、GPUの可視性やvLLMのエンジンログも確認し、CUDAの実行と意図したモデルdtypeを確認してください。 準備状況やライブラリの読み込みが成功しただけではGPUの実行やDACSキャッシュ使用を証明できません。

コールドキャッシュとウォームキャッシュの挙動を確認する

「 ワークロードの構成とデプロイ」で収集した事前のメトリクスベースラインを活用してください。 展開時に行われるモデルのロードはコールドロードです。

コールドロードの確認

アプリケーションログを確認しましょう:

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

ネイティブ ReadChunk statsを探してください。 RemoteClient バックストアの weight read 数をカウントします。 RemoteCache はリモートキャッシュの読み込み数をカウントします。 最初のロード時にキャッシュヒットが起こることは、先行する読み取りでデータがキャッシュに格納されるため、正常な場合があります。 GetProperties キャッシュヒットはメタデータを表し、モデルの重みヒットではありません。

推論リクエストを送信する:

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

コールド backing-store の読み取り回数が 0 でないことを確認します。 非同期キャッシュの投入を確認している間、アプリケーションPodを実行したままにしてください:

  1. 選択した Cache リソースの各キャッシュ サーバー Pod から、10 秒ごとに cache_server_upload_request_size_bytes_sum と cache_server_cache_size_bytes を最大 5 分間サンプリングします。 メトリクス エンドポイントの手順を使用してください。 保存されたスクレープのコピーを使い回すのではなく、新しいサンプルを使用してください。
  2. サンプルをデプロイ前のベースラインと比較してください。 それらのサーバー全体で、合計アップロード バイト数と合計キャッシュ バイト数の増加を必須とします。 すべてのサーバーがデータを受信する必要はありません。
  3. 合計アップロードが増加した後、各サーバーのアップロードバイトカウンターが3回連続のサンプリング間隔で変化しない状態になるまで待機します。 比較中にサーバーが再起動しておらず、カウンターがリセットされていないことを確認してください。
  4. その最終サンプルをコールド後のスナップショットとして保存し、すべてのサーバーの cache_server_download_request_size_bytes_sum をウォームロードのベースラインとして含めてください。

これらの条件が5分以内に満たされない場合は、キャッシュがウォーム状態であると見なすのではなく、比較を中止してください。 再挑戦する前にクライアントのアップロードエラー、キャッシュサーバーの健康状態、進行中のトラフィックを確認してください。 大規模なモデルでは、より長い観測期間が必要になる場合があります。 指標の欠落やスクレイプ失敗はゼロ値やアップロード完了の証拠ではありません。

安定カウンターは準備状況のシグナルであり、すべてのモデルチャンクがキャッシュされている証拠ではありません。 共有キャッシュのトラフィックは、安定化を妨げたり、増加の原因となったりすることもあります。 可能な限り静かな検証時間帯を使用し、分散キャッシュの再利用を確認するために、以下の fresh-Pod ウォーム リード チェックを必須としてください。

新しいポッドでウォームロードを確認しましょう

コールドログとポッドUIDを保存してください。 同じモデルファイル、キャッシュエンドポイント、ライブラリ、チャンクサイズを使って、アプリケーションポッドのみを再作成してください:

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

ランタイムチェックと推論リクエストを繰り返します。 その後、すべてのキャッシュサーバーからウォーム後のメトリクススナップショットを取得します。 異なるポッドのUID、リモートソースキャッシュヒット率の向上、バックストア読み取りの減少を確認しましょう。 cache_server_download_request_size_bytes_sum をポスト コールド スナップショットと比較して、ウォーム キャッシュ読み取りであることを確認します。 新しく起動したプロセスを使うことで、ローカルのインメモリ・プリフェッチを分散キャッシュのヒットと混同することを避けられます。

リモートソースのヒット率はローカルプリフェッチを除き RemoteCache / (RemoteCache + RemoteClient)です。 各ネイティブプロセス、マウント、チャンクサイズごとに最新の累積スナップショットを使用し、周期的なサンプルを合計しないでください。 キャッシュサーバーの再起動やカウンターリセットによる測定値は除外します。 共有サーバーカウンターはアプリケーションのログを裏付けますが、すべてのトラフィックを1つのワークロードに割り当てるわけではありません。

ウォーム ウェイト リード カウンターでバックストア読み取りがゼロでも、メタデータは Blob Storage にアクセスできます。

ImageVolumeでDACSクライアントライブラリをマウントする

この代替案は、ノードランタイムがImageVolumeをサポートし、パブリックDACSホイールから構築されたプル可能なクライアントイメージがある場合のみ使用してください。 提案されたMCR画像やタグが公開されていると決めつけないでください。 適切なクライアントイメージがない場合は、前節のworkload-image の手順を用いてください。

GPU vLLMイメージには、すでに互換性のあるRun:aiコアとAzureパッケージが含まれている必要があります。 DACSクライアントパッケージをPython環境にインストールする必要はありません。なぜなら、イメージボリュームがネイティブクライアントライブラリを提供しているからです。

ポッドの例を以下のように調整します。

  1. 既存の互換性のあるvLLMイメージを使い続け、DACSクライアントライブラリをインストールするために再構築するのではなく、そのまま使い続けてください。

  2. 読み取り専用のクライアントイメージボリュームを追加してマウント:

    # 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. その画像の実際のレイアウトに基づいて、libStorageDirect.so 配下の /opt/cache-client の絶対パスを RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_LIB に設定してください。 同階層のネイティブ依存関係を保存しましょう。

  4. 展開し、イメージボリュームと読み取り専用マウントが live ポッド仕様に残っていることを確認してください。 ファイルの存在を確認し、同じアプリケーション コンテナー ランタイムを使用して、コールド/ウォーム チェックを実行します。

一部の古いクラスターでは、受け入れられたポッドからサポートされていない画像ボリューム フィールドやマウントを削除することができます。 Kubernetesのバージョンとサーバーのドライランだけでは不十分です。 マウントされたクライアントと並んで、DACSクライアントライブラリの競合するバージョンをインストールまたはプリロードしないでください。絶対ライブラリパスはネイティブの依存関係名空間を分離しません。

読み取り性能の最適化

なぜチャンクサイズを調整するのですか? モデルはテンソルサイズや読み取りパターンが異なるため、1つのチャンクサイズではすべてのモデルで最良のモデルロード性能が得られない場合があります。 過大チャンクは読み取りに必要なデータよりも多くのデータを取得し、バッファリングを増加させます。 チャンクが小さいとリクエスト数やリクエストあたりのオーバーヘッドが増えます。 モデルで一般的に現れるテンソルに適したサイズを選ぶことで、これらのコストを均衡させ、実効的なウェイトリードスループットを向上させ、DACSからのウォームロードを含むモデルロード時間を短縮します。 以下の推奨事項を出発点とし、コールドとウォームのロード時間を別々に測定してください。 利点はモデル、ローダーの同時実行性、ストレージおよびネットワーク性能に依存します。

以下のモデル固有の推奨事項を使ってチャンクサイズを選択してください。 他のモデルについては、次のセクションで説明するテンソルメタデータを検査するか、メタデータ検査が利用できない場合は 32 MiB を使用してください。

Model 推奨チャンクサイズ バイト単位の値
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 (別名) 2 MiB 2097152
ministral-3-8b-instruct-2512 2 MiB 2097152
ministral-3-8b-instruct (別名) 2 MiB 2097152
ministral-3-14b-instruct-2512 2 MiB 2097152
ministral-3-14b-instruct (別名) 2 MiB 2097152
メタデータ検査が利用できない場合のフォールバック 32 MiB 33554432

別のモデルのためにチャンクサイズを選ぶ

Safetensorsのメタデータビューアまたはヘッダー検査ツールを使って、テンソル内容を読み込まずに すべてのモデルシャードを検査してください:

  1. 各テンソルの格納サイズ(バイト単位)を求めます:終了データのオフセットから開始オフセットを引いたもの。 __metadata__の項目は除外してください。
  2. 32 MiBを超えるすべてのサイズは32 MiBとして扱い、発生数をカウントしてください。
  3. すべてのシャードで最も頻繁に発生するサイズを選択します。 複数のサイズが同じ頻度で起こる場合は、大きい方を選びましょう。
  4. 選択したサイズが2 MiB未満の場合は、2 MiBを使用してください。

たとえば、3-MiB テンソルが上限適用後に最も頻繁に発生する場合は、3 MiB (3145728 バイト) を指定します。 メタデータ検査ができない場合は、32 MiB (33554432 バイト) を使用します。

アプリケーションの構成

RUNAI_STREAMER_CHUNK_BYTESIZEとSI_streamingChunkSizeの両方をアプリケーション コンテナーの環境内で結果のバイト値に設定します。 たとえば、3 MiB のレコメンデーションの場合:

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

これらの値を明示的に設定してください。表は推奨事項を説明しており、自動モデル検出や組み込みのデフォルトを示すものではありません。 それらを変更した後にアプリケーションポッドを再作成してください。キャッシュサーバーは再起動の必要はありません。 キャッシュ データを共有するリーダーとデータ投入ジョブは同じチャンク サイズを使うべきです。

Run:aiの読み取りサイズとネイティブキャッシュチャンクサイズは別々のコントロールで、上で一緒に設定されています。 推奨事項をワークロードと合わせてベンチマークし、ローダーの並行性を別々に調整してください。 コールドロードとウォームロードを独立して比較してください。 キャッシュチャンクサイズを変更すると異なるキャッシュキーが作成され、一時的にキャッシュ占有率が増加します。 一度に一つの設定を変更し、ロード時間、ネイティブカウンター、キャッシュ指標、CPU、GPUとホストメモリ、ネットワーク使用状況を測定します。 テンソルアライメントだけでは性能が向上するわけではありません。

Warning

パブリック ネイティブ クライアントの既定の非同期アップロード バッファ予算は、0.1.0 では 400 GiB です。 これは、事前割り当てでも、安全な Pod メモリ制限でもありません。 大型モデルのコールド状態の集団は、より小さい Pod を枯渇させることがあります。 メモリに制約のあるワークロードについては、同期的なデータ投入 (SI_cacheEnableSyncUpload=true) または上限が設定された非同期アップロードの割り当て (SI_cacheMaxUploadBufferSizePerProcessGB) をテストしてください。 予算モデル ステージング、ネイティブのアップロード/プリフェッチ バッファ、GPU メモリ、および /dev/shm をそれぞれ個別に扱います。 これらのセーフガードは、小規模モデルの例に追加要件ではなく、ワークロード固有のオプション設定です。

Troubleshoot

症状: チェック
イメージの取得に失敗しました Kubeletのプル権限、レジストリ権限モード、イメージダイジェスト、ネットワークアクセス。
ネイティブライブラリが読み込まれません アプリケーションPython環境、明示的なパス、glibc互換性、そして同階層のネイティブライブラリ。
Blob認証が失敗します 選択されたアイデンティティ、閲覧者ロール、ロール伝播、フェデレーション、ポッドラベル。 その他の認証方法については、先ほどリンクされた上流のAzure認証ガイダンスに従ってください。
モデルはキャッシュトラフィックなしでロードされる ディスカバリー設定、プロバイダーの読み込み、DNS/ネットワークの到達可能性、ネイティブのデータ読み取りカウンター。
ウォームロードでもBlobデータを読み取れます 設定完了、ブロブ バージョン、チャンク サイズの一致、エビクション、および部分的な読み取り。
ImageVolumeが欠落しています ライブポッドフィールドとノード/ランタイムのサポート;利用できない場合は組み込みメソッドを使用してください。
Pod はOOM で終了する モデルとステージング メモリ、ネイティブ バッファ、GPU/KV キャッシュのサイズ、/dev/shm。

別の直接Blob比較のために、 RUNAI_STREAMER_EXPERIMENTAL_AZURE_CACHE_ENABLED=0 を設定してテストポッドを再作成してください。 1 に設定すると、プロバイダーのロードに失敗した場合、静かにフォールバックされるのではなく、起動自体が失敗するようになります。 どちらの設定もキャッシュヒットを証明するものではありません。データ読み取りカウンタを検査してください。

例をクリーンアップする

もし独立した例版Podを作成していたら、終わったら削除してください:

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

この例で作成したモデルプレフィックス、画像、アイデンティティ、フェデレーション、名前空間、ロール割り当てのうち、不要になったものだけを削除してください。 既存の共有キャッシュやアイデンティティを削除しないでください。 保持されたモデルデータはウォーム状態となり、新しいプレフィックスを使用して、別のコールドキャッシュ検証を行ってください。

次のステップ