すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:TensorRT-LLM を使用した Qwen2 モデル推論サービスのデプロイ

最終更新日:Mar 13, 2026

このトピックでは、Triton Inference Server と TensorRT-LLM を使用して、Container Service for Kubernetes (ACK) に Qwen モデル推論サービスをデプロイする方法について説明します。例として、Qwen2-1.5B-Instruct モデルと A10 GPU を使用します。モデルのデプロイ中、Fluid Dataflow がモデルを準備し、Fluid がモデルの読み込みを高速化します。

背景情報

Qwen2-1.5B-Instruct

Qwen2-1.5B-Instruct は、Transformer アーキテクチャに基づく大規模言語モデルです。15億のパラメーターを持ち、大規模な事前学習データセットでトレーニングされています。多様で広範な事前学習データには、大量の Web テキスト、専門書、コードが含まれています。モデルの詳細については、Qwen2 GitHub リポジトリをご参照ください。

Triton (Triton Inference Server)

Triton Inference Server は、NVIDIA が提供するオープンソースの推論サービングフレームワークであり、AI 推論アプリケーションを迅速に構築するのに役立ちます。Triton は、TensorRT、TensorFlow、PyTorch、ONNX、vLLM など、さまざまな機械学習フレームワークをランタイムバックエンドとしてサポートしています。Triton は、リアルタイム、バッチ、およびオーディオ/ビデオストリーミングの推論に最適化されており、最適なパフォーマンスを提供します。Triton 推論サービングフレームワークの詳細については、Triton Inference Server GitHub リポジトリをご参照ください。

TensorRT-LLM

TensorRT-LLM は、大規模言語モデル (LLM) を最適化するための NVIDIA のオープンソースライブラリです。LLM を TensorRT エンジンにビルドして、NVIDIA GPU での推論効率を向上させます。TensorRT-LLM は、TensorRT-LLM Backend として Triton フレームワークと統合することもできます。TensorRT-LLM でビルドされたモデルは、単一または複数の GPU で実行でき、テンソル並列処理とパイプライン並列処理の両方をサポートします。TensorRT-LLM の詳細については、TensorRT-LLM GitHub リポジトリをご参照ください。

前提条件

  • A10 GPU を含む ACK Managed Cluster Pro Edition が作成されていること。クラスターのバージョンは 1.22 以降である必要があります。詳細については、「ACK マネージドクラスターの作成」をご参照ください。

    GPU ノードはドライバーバージョン 525 を使用する必要があります。ドライバーバージョン 525.105.17 を指定するには、GPU ノードプールに ack.aliyun.com/nvidia-driver-version:525.105.17 ラベルを追加します。詳細については、「バージョン番号を指定してノードの GPU ドライバーバージョンをカスタマイズする」をご参照ください。

  • クラウドネイティブ AI スイートがインストールされ、ack-fluid コンポーネントがデプロイされていること。

    重要

    オープンソースの Fluid をインストールしている場合は、ack-fluid コンポーネントをデプロイする前に Fluid をアンインストールしてください。

    • クラウドネイティブ AI スイートをインストールしていない場合:Fluid をデプロイし、データキャッシュアクセラレーションを有効にします。詳細については、「クラウドネイティブ AI スイートのデプロイ」をご参照ください。

    • クラウドネイティブ AI スイートをすでにインストールしている場合は、ACK コンソール[マーケットプレイス]ページに移動して、[ack-fluid] コンポーネントをデプロイします。

  • Object Storage Service (OSS) を有効化し、バケットが作成されていること。詳細については、「OSS の有効化」および「バケットの作成」をご参照ください。

ステップ1:Dataset と JindoRuntime の作成

Dataset はデータを整理し、処理します。JindoRuntime を統合して、キャッシュポリシーを使用してデータアクセスを高速化できます。これらを組み合わせることで、データ処理とモデルサービスのパフォーマンスが大幅に向上します。

  1. 次のコマンドを実行して、OSS のアクセス認証情報を格納する Secret を作成します。

    kubectl apply -f-<<EOF                                            
    apiVersion: v1
    kind: Secret
    metadata:
      name: fluid-oss-secret
    stringData:
      fs.oss.accessKeyId: <ご利用の AccessKey ID>
      fs.oss.accessKeySecret: <ご利用の AccessKey Secret>
    EOF

    コマンド内の fs.oss.accessKeyIdfs.oss.accessKeySecret は、OSS へのアクセスに使用する AccessKey ID と AccessKey Secret です。AccessKey ID と AccessKey Secret の取得方法の詳細については、「AccessKey の取得」をご参照ください。

    想定される出力:

    secret/fluid-oss-secret created
  2. dataset.yaml という名前のファイルを作成し、次の内容をコピーします。この構成では、キャッシュサービスを提供する Dataset と JindoRuntime を作成します。Dataset と JindoRuntime の構成方法の詳細については、「JindoFS を使用した OSS ファイルへのアクセスの高速化」をご参照ください。

    # リモートデータセットと UFS 情報を記述する Dataset を作成します。
    apiVersion: data.fluid.io/v1alpha1
    kind: Dataset
    metadata:
      name: qwen2-oss
    spec:
      mounts:
      - mountPoint: oss://<oss_bucket>/qwen2-1.5b # 実際のモデルストレージの場所に置き換えます。
        name: qwen2
        path: /
        options:
          fs.oss.endpoint: <oss_endpoint> # 実際の OSS エンドポイントアドレスに置き換えます。
        encryptOptions:
          - name: fs.oss.accessKeyId
            valueFrom:
              secretKeyRef:
                name: fluid-oss-secret
                key: fs.oss.accessKeyId
          - name: fs.oss.accessKeySecret
            valueFrom:
              secretKeyRef:
                name: fluid-oss-secret
                key: fs.oss.accessKeySecret
      accessModes:
        - ReadWriteMany
    # キャッシュサービスを提供する JindoFS クラスターを起動する JindoRuntime を作成します。
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: JindoRuntime
    metadata:
      name: qwen2-oss
    spec:
      replicas: 2
      tieredstore:
        levels:
          - mediumtype: MEM
            volumeType: emptyDir
            path: /dev/shm
            quota: 20Gi
            high: "0.95"
            low: "0.7"
      fuse:
        properties:
          fs.oss.read.buffer.size: "8388608" # 8M
          fs.oss.download.thread.concurrency: "200"
          fs.oss.read.readahead.max.buffer.count: "200"
          fs.oss.read.sequence.ambiguity.range: "2147483647"
        args:
          - -oauto_cache
          - -oattr_timeout=1
          - -oentry_timeout=1
          - -onegative_timeout=1
  3. 次のコマンドを実行して、JindoRuntime と Dataset を作成します。

    kubectl apply -f dataset.yaml

    想定される出力:

    dataset.data.fluid.io/qwen2-oss created
    jindoruntime.data.fluid.io/qwen2-oss created

    この出力は、Dataset と JindoRuntime リソースが作成されたことを示します。

  4. 次のコマンドを実行して、Dataset のデプロイステータスを確認します。

    kubectl get dataset qwen2-oss

    想定される出力:

    NAME        UFS TOTAL SIZE   CACHED   CACHE CAPACITY   CACHED PERCENTAGE   PHASE   AGE
    qwen2-oss   0.00B            0.00B    20.00GiB         0.0%                Bound   57s

ステップ2:Dataflow の作成

TensorRT-LLM でモデル推論を高速化するには、モデルファイルをダウンロードし、モデルファイル形式を変換し、TensorRT エンジンをビルドし、構成ファイルを変更する必要があります。このトピックでは、Fluid Dataflow を使用してこれらのステップを実行します。

  1. dataflow.yaml という名前のファイルを作成し、次の内容をコピーします。これにより、次の 3 つのステップを含む Dataflow が作成されます。

    1. ModelScope から Qwen2-1.5B-Instruct モデルをダウンロードします。

    2. TensorRT-LLM ツールを使用してモデル形式を変換し、エンジンをビルドします。

    3. DataLoad を使用してデータセットを更新します。

    # ModelScope プラットフォームから指定されたストレージパスに Qwen2-1.5B-Instruct モデルをダウンロードします。
    apiVersion: data.fluid.io/v1alpha1
    kind: DataProcess
    metadata:
      name: step1-download-model
    spec:
      dataset:
        name: qwen2-oss
        namespace: default
        mountPath: /mnt/models/
      processor:
        script:
          image: ac2-registry.cn-hangzhou.cr.aliyuncs.com/ac2/base
          imageTag: ubuntu22.04
          imagePullPolicy: IfNotPresent
          restartPolicy: OnFailure
          command:
          - bash
          source: |
            #!/bin/bash
            echo "Downloading model..."
            if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct" ]; then
                echo "Directory ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct exists. Skipping model download."
            else
                apt update && apt install -y git git-lfs
                git clone https://www.modelscope.cn/qwen/Qwen2-1.5B-Instruct.git Qwen2-1.5B-Instruct
                mv Qwen2-1.5B-Instruct ${MODEL_MOUNT_PATH}
            fi
          env:
          - name: MODEL_MOUNT_PATH
            value: "/mnt/models"
    # ダウンロードしたモデルを TensorRT-LLM が要求する形式に変換し、推論エンジンをビルドします。
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: DataProcess
    metadata:
      name: step2-trtllm-convert
    spec:
      runAfter:
        kind: DataProcess
        name: step1-download-model
        namespace: default
      dataset:
        name: qwen2-oss
        namespace: default
        mountPath: /mnt/models/
      processor:
        script:
          image: kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/tritonserver-build
          imageTag: 24.07-trtllm-python-py3
          imagePullPolicy: IfNotPresent
          restartPolicy: OnFailure
          command:
          - bash
          source: |
            #!/bin/bash
            set -ex
    
            cd /tensorrtllm_backend/tensorrt_llm/examples/qwen
            if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt" ]; then
                echo "Directory ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt exists. Skipping checkpoint conversion."
            else
                echo "Converting checkpoint..."
                python3 convert_checkpoint.py --model_dir ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct --output_dir /root/Qwen2-1.5B-Instruct-ckpt --dtype float16
    
                echo "Writing TensorRT-LLM model checkpoint to OSS bucket..."
                mv /root/Qwen2-1.5B-Instruct-ckpt ${MODEL_MOUNT_PATH}
            fi
    
            sleep 2
            
            if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-engine" ]; then
                echo "Directory $OUTPUT_DIR/Qwen2-1.5B-Instruct-engine exists. Skipping engine build."
            else
                echo "Building TensorRT-LLM engine..."
                trtllm-build --checkpoint_dir ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt \
                --gemm_plugin float16 \
                --paged_kv_cache enable \
                --output_dir /root/Qwen2-1.5B-Instruct-engine
    
                echo "Writing TensorRT-LLM engine to OSS bucket..."
                mv /root/Qwen2-1.5B-Instruct-engine ${MODEL_MOUNT_PATH}
            fi
    
            if [ -d "${MODEL_MOUNT_PATH}/tensorrtllm_backend" ]; then
                echo "Directory $OUTPUT_DIR/tensorrtllm_backend exists. Skipping tensorrtllm_backend configuration."
            else
                echo "Configuring model..."
                cd /tensorrtllm_backend
                cp all_models/inflight_batcher_llm/ qwen2_ifb -r
                export QWEN2_MODEL=${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct
                export ENGINE_PATH=${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-engine
    
                python3 tools/fill_template.py -i qwen2_ifb/preprocessing/config.pbtxt tokenizer_dir:${QWEN2_MODEL},triton_max_batch_size:8,preprocessing_instance_count:1
                python3 tools/fill_template.py -i qwen2_ifb/postprocessing/config.pbtxt tokenizer_dir:${QWEN2_MODEL},triton_max_batch_size:8,postprocessing_instance_count:1
                python3 tools/fill_template.py -i qwen2_ifb/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:8,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False
                python3 tools/fill_template.py -i qwen2_ifb/ensemble/config.pbtxt triton_max_batch_size:8
                python3 tools/fill_template.py -i qwen2_ifb/tensorrt_llm/config.pbtxt triton_backend:tensorrtllm,triton_max_batch_size:8,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:1280,max_attention_window_size:1280,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_fused_batching,max_queue_delay_microseconds:0
    
                echo "Writing TensorRT-LLM configuration to OSS bucket..."
                mkdir -p ${MODEL_MOUNT_PATH}/tensorrtllm_backend
                mv /tensorrtllm_backend/qwen2_ifb ${MODEL_MOUNT_PATH}/tensorrtllm_backend
            fi
          env:
          - name: MODEL_MOUNT_PATH
            value: "/mnt/models"
          resources:
            requests:
              cpu: 2
              memory: 10Gi
              nvidia.com/gpu: 1
            limits:
              cpu: 12
              memory: 30Gi
              nvidia.com/gpu: 1
    # 変換・最適化されたモデルと構成をメモリにロードし、高速応答の推論サービスを有効にします。
    ---
    apiVersion: data.fluid.io/v1alpha1
    kind: DataLoad
    metadata:
      name: step3-warmup-cache
    spec:
      runAfter:
        kind: DataProcess
        name: step2-trtllm-convert
        namespace: default
      dataset:
        name: qwen2-oss
        namespace: default
      loadMetadata: true
      target:
      - path: /Qwen2-1.5B-Instruct-engine
      - path: /tensorrtllm_backend

    これら 3 つのステップは、オリジナルモデルのダウンロード、モデルの変換と最適化、およびモデルのキャッシュへの事前ロードを含む、完全で自動化されたスケーラブルなモデルデプロイワークフローを構成します。

  2. 次のコマンドを実行して、Dataflow を作成します。

    kubectl create -f dataflow.yaml

    想定される出力:

    dataprocess.data.fluid.io/step1-download-model created
    dataprocess.data.fluid.io/step2-trtllm-convert created
    dataload.data.fluid.io/step3-warmup-cache created

    この出力は、dataflow.yaml ファイルで定義されたカスタムリソースオブジェクトが作成されたことを示します。

  3. 次のコマンドを実行して Dataflow の実行ステータスを確認し、ジョブが完了するのを待ちます。

    kubectl get dataprocess

    想定される出力:

    NAME                   DATASET     PHASE      AGE   DURATION
    step1-download-model   qwen2-oss   Complete   23m   3m2s
    step2-trtllm-convert   qwen2-oss   Complete   23m   19m58s

    この出力は、qwen2-oss データセットに関連する 2 つのデータ処理ジョブ (モデルのダウンロードと trtllm 形式への変換) が正常に完了したことを示します。

ステップ3:推論サービスのデプロイ

  1. 次の Arena コマンドを実行して、カスタムサービングサービスをデプロイします。

    このサービスは qwen2-chat という名前で、バージョンは v1、1 つの GPU を必要とし、1 つのレプリカを持ち、readiness プローブが構成されています。モデルはデータの一種であるため、--data パラメーターを使用して、Fluid によって作成された qwen2-oss PersistentVolumeClaim (PVC) をコンテナ内の /mnt/models ディレクトリにマウントします。

    arena serve custom \
    --name=qwen2-chat \
    --version=v1 \
    --gpus=1 \
    --replicas=1 \
    --restful-port=8000 \
    --readiness-probe-action="tcpSocket" \
    --readiness-probe-action-option="port: 8000" \
    --readiness-probe-option="initialDelaySeconds: 30" \
    --readiness-probe-option="periodSeconds: 30" \
    --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/tritonserver:24.07-trtllm-python-py3 \
    --data=qwen2-oss:/mnt/models \
    "tritonserver --model-repository=/mnt/models/tensorrtllm_backend/qwen2_ifb --http-port=8000 --grpc-port=8001 --metrics-port=8002 --disable-auto-complete-config --backend-config=python,shm-region-prefix-name=prefix0_"

    想定される出力:

    service/qwen2-chat-v1 created
    deployment.apps/qwen2-chat-v1-custom-serving created
    INFO[0003] The Job qwen2-chat has been submitted successfully
    INFO[0003] You can run `arena serve get qwen2-chat --type custom-serving -n default` to check the job status

    この出力は、推論サービスが正常にデプロイされたことを示します。

  2. 次のコマンドを実行して推論サービスの詳細を表示し、準備が完了するのを待ちます。

    arena serve get qwen2-chat

    想定される出力:

    Name:       qwen2-chat
    Namespace:  default
    Type:       Custom
    Version:    v1
    Desired:    1
    Available:  1
    Age:        1m
    Address:    192.XX.XX.XX
    Port:       RESTFUL:8000
    GPU:        1
    
    Instances:
      NAME                                           STATUS   AGE  READY  RESTARTS  GPU  NODE
      ----                                           ------   ---  -----  --------  ---  ----
      qwen2-chat-v1-custom-serving-657869c698-hl665  Running  1m   1/1    0         1    ap-southeast-1.192.XX.XX.XX

    この出力は、推論サービスの Pod である qwen2-chat-v1-custom-serving-657869c698-hl665 が実行中であり、リクエストを処理する準備ができていることを示します。

ステップ4:推論サービスの検証

  1. 次のコマンドを実行して、推論サービスとローカル環境の間でポートフォワーディングを設定します。

    重要
    kubectl port-forward svc/qwen2-chat-v1 8000:8000

    想定される出力:

    Forwarding from 127.0.0.1:8000 -> 8000
    Forwarding from [::1]:8000 -> 8000
  2. 次のコマンドを実行して、モデル推論リクエストを送信します。

    curl -X POST localhost:8000/v2/models/ensemble/generate -d '{"text_input": "What is machine learning?", "max_tokens": 20, "bad_words": "", "stop_words": "", "pad_id": 2, "end_id": 2}'

    想定される出力:

    {"context_logits":0.0,"cum_log_probs":0.0,"generation_logits":0.0,"model_name":"ensemble","model_version":"1","output_log_probs":[0.0,0.0,0.0,0.0],"sequence_end":false,"sequence_id":0,"sequence_start":false,"text_output":" Machine learning is a type of artificial intelligence that allows computer systems to learn from data without being explicitly programmed."}

    この出力は、モデルが提供された入力に基づいて応答を生成することを示します。

(オプション) ステップ5:環境のクリーンアップ

デプロイしたモデル推論サービスが不要になった場合は、次のコマンドを実行して削除します。

arena serve delete qwen2-chat

付録:コマンドパラメーターリファレンス

パラメーター

説明

serve custom

Arena サブコマンド。tfservingtriton などのプリセットタイプを使用する代わりに、カスタムモデルサービスをデプロイします。

(N/A)

--name

サービス名。デプロイするサービスの一意の名前を指定します。この名前は、ログの表示やサービスの削除など、後続の管理操作で使用されます。

modelscope

--version

サービスバージョン。サービスのバージョン番号を指定して、バージョン管理や段階的リリースなどの操作を容易にします。

v1

--gpus

GPU リソース。各サービス (Pod) に割り当てられる GPU の数。モデルが推論に GPU を必要とする場合、このパラメーターは必須です。

1

--replicas

レプリカ数。実行するサービスインスタンス (Pod) の数。レプリカ数を増やすと、サービスの並行処理能力と可用性を向上させることができます。

1

--restful-port

RESTful ポート。サービスが推論リクエストを受信するために RESTful API を公開するポート。

8000

--readiness-probe-action

readiness プローブのタイプ。コンテナがトラフィックを受信する準備ができているかどうかを判断する Kubernetes の readiness プローブのチェックメソッドを設定します。

tcpSocket

--readiness-probe-action-option

プローブタイプのオプション。選択したプローブタイプに固有のパラメーターを提供します。tcpSocket の場合、チェックするポートを指定します。

port: 8000

--readiness-probe-option

その他のプローブオプション。readiness プローブの動作に関する追加のパラメーターを設定します。このパラメーターは複数回使用できます。例では、初期遅延とチェック間隔を設定しています。

initialDelaySeconds: 30
periodSeconds: 30

--data

ボリュームマウント。PVC をコンテナ内の指定されたパスにマウントします。形式は PVC 名:マウントパス です。これは一般的にモデルファイルをマウントするために使用されます。

llm-model:/Qwen1.5-4B-Chat

--image

コンテナイメージ。サービスのデプロイに使用されるコンテナイメージの完全な URL。これは、サービスのコア実行環境を定義します。

kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/quick-deploy-llm:v1

[COMMAND]

起動コマンド。コンテナの起動後に実行するコマンド。例では、MODEL_ID 環境変数を設定し、server.py スクリプトを起動します。

"MODEL_ID=/Qwen1.5-4B-Chat python3 server.py"