このトピックでは、Qwen3-32B モデルを例として、prefill-decode (PD) 分離アーキテクチャを持つ Dynamo フレームワークを使用して、Container Service for Kubernetes (ACK) クラスターにモデル推論サービスをデプロイする方法を説明します。
背景
Qwen3-32B
Qwen3-32B は、Qwen シリーズの最新の進化形であり、推論効率と会話の流暢さの両方に最適化された 32.8B パラメーターの高密度アーキテクチャを特徴としています。
主な特徴:
デュアルモードパフォーマンス: 論理的推論、数学、コード生成などの複雑なタスクに優れている一方で、一般的なテキスト生成においても高い効率を維持します。
高度な機能: 命令追従、マルチターン対話、創造的な文章作成、および AI エージェントタスクのためのクラス最高のツール使用において、優れたパフォーマンスを発揮します。
大きなコンテキストウィンドウ: ネイティブで最大 32,000 トークンのコンテキストを処理し、YaRN テクノロジーを使用することで 131,000 トークンまで拡張できます。
多言語サポート: 100 以上の言語を理解し、翻訳できるため、グローバルなアプリケーションに最適です。
Dynamo
Dynamo は、NVIDIA が提供する高スループット、低レイテンシーの推論フレームワークであり、マルチノードの分散環境で大規模言語モデル (LLM) を提供するために特別に設計されています。

主な特徴:
エンジン非依存: Dynamo は特定の推論エンジンに縛られず、TensorRT-LLM、vLLM、SGLang などのさまざまなバックエンドをサポートします。
LLM 固有の最適化機能:
PD 分離: 計算集約的な prefill ステージをメモリバウンドな decode ステージから分離し、レイテンシーを削減してスループットを向上させます。
動的 GPU スケジューリング: リアルタイムの負荷変動に基づいてパフォーマンスを最適化します。
スマート LLM ルーティング: ノードのキー値 (KV) キャッシュに基づいてリクエストをルーティングし、不要な KV キャッシュの再計算を回避します。
高速化されたデータ転送: NVIDIA Inference Xfer Library (NIXL) テクノロジーを使用して、中間計算結果と KV キャッシュの転送を高速化します。
KV キャッシュのオフロード: KV キャッシュをメモリ、ディスク、さらにはクラウドディスクにオフロードして、システム全体のスループットを向上させることができます。
高性能と拡張性: コアは最高のパフォーマンスを実現するために Rust で構築されており、ユーザーの拡張性のために Python インターフェイスを提供します。
完全なオープンソース: Dynamo は完全にオープンソースであり、透明性の高いオープンソースファーストの開発哲学に従っています。
Dynamo フレームワークの詳細については、「Dynamo GitHub」および「Dynamo ドキュメント」をご参照ください。
PD 分離
PD 分離アーキテクチャは、LLM 推論のための主要な最適化技術です。推論の 2 つのコアステージの競合するリソース要求を解決します:
Prefill ステージ (プロンプト処理): これは計算バウンドなプロセスで、入力プロンプト全体を並列処理して初期のキー値 (KV) キャッシュを生成します。計算集約的ですが、リクエストの最初に一度だけ実行されます。
Decode ステージ (トークン生成): これはメモリバウンドな自己回帰プロセスで、新しいトークンが 1 つずつ生成されます。各ステップは計算量が少ないですが、GPU メモリ内の大規模なモデルの重みと KV キャッシュへの繰り返しの高速アクセスが必要です。

中心的な問題: 非効率な混合ワークロードのスケジューリング
課題は、これら 2 つの異なるワークロードを同じ GPU でスケジューリングすることが非常に非効率であることです。推論エンジンは通常、継続的バッチ処理を使用して複数のユーザーリクエストを同時に処理し、同じバッチ内で異なるリクエストの prefill ステージと decode ステージを混合します。これによりリソースの競合が発生します。計算集約的な prefill ステージ (プロンプト全体の処理) が GPU のリソースを占有し、はるかに軽量な decode ステージ (単一トークンの生成) が待機することになります。このリソース競合は decode ステージのレイテンシーを増加させ、結果としてシステム全体のレイテンシーを増加させ、スループットを著しく低下させます。

PD 分離アーキテクチャは、2 つのステージを分離し、それぞれを異なる専用の GPU にデプロイすることで、この競合を解決します。
この分離により、システムは各ワークロードのスケジューリングを個別に最適化できます。特定の GPU を prefill タスクに、他の GPU を decode タスクに割り当てることで、リソースの競合が解消されます。これにより、平均出力トークンあたりの時間 (TPOT) が大幅に短縮され、システム全体のスループットが大幅に向上します。
RoleBasedGroup
RoleBasedGroup (RBG) は、PD 分離などの複雑なアーキテクチャの大規模なデプロイと O&M を簡素化するために ACK チームによって設計された新しい Kubernetes ワークロードです。詳細については、「RBG GitHub プロジェクト」をご参照ください。
RBG はロールのグループによって定義され、各ロールは StatefulSet、Deployment、または他のワークロードタイプに基づいて構築できます。主な特徴:
柔軟なマルチロール定義: RBG を使用すると、任意の名前で任意の数のロールを定義できます。それらの間の起動依存関係を指定し、各ロールを個別にスケーリングできます。
グループレベルのランタイム管理: グループ内での自動サービス検出を提供し、さまざまな再起動ポリシー、ローリングアップデート、およびギャングスケジューリングをサポートします。

前提条件
Kubernetes 1.22 以降を実行し、少なくとも 6 つの GPU (各 GPU には少なくとも 32 GB のメモリ) を搭載した ACK マネージドクラスター。詳細については、「ACK マネージドクラスターの作成」および「クラスターへの GPU ノードの追加」をご参照ください。
ecs.ebmgn8is.32xlargeインスタンスタイプを推奨します。インスタンスタイプの詳細については、「ECS ベアメタルインスタンスファミリー」をご参照ください。ack-rbgs コンポーネントがクラスターにインストールされていること。コンポーネントをインストールするには、次の手順を実行します。
Container Service 管理コンソールにログインします。左側のナビゲーションウィンドウで、[クラスターリスト] を選択します。ターゲットクラスターの名前をクリックします。クラスターの詳細ページで、Helm を使用して [ack-rbgs] コンポーネントをインストールします。コンポーネントに [アプリケーション名] や [名前空間] を設定する必要はありません。[次へ] をクリックすると、[確認してください] ダイアログボックスが表示されます。[はい] をクリックして、デフォルトのアプリケーション名 ([ack-rbgs]) と名前空間 ([rbgs-system]) を受け入れます。次に、最新の Chart バージョンを選択し、[OK] をクリックしてインストールを完了します。

モデルのデプロイ
次のシーケンス図は、Dynamo PD 分離アーキテクチャにおけるリクエストのライフサイクルを示しています:
リクエストの取り込み: ユーザーのリクエストは、まず processor コンポーネントに送信されます。processor 内の router は、利用可能な decode worker を選択し、リクエストを転送します。
Prefill の決定: decode worker は、prefill 計算をローカルで実行するか、リモートの prefill worker に委任するかを決定します。リモート計算が必要な場合、prefill リクエストを prefill queue に送信します。
Prefill の実行: prefill worker はキューからリクエストを取得し、prefill 計算を実行します。
KV キャッシュの転送: 計算が完了すると、prefill worker は結果の KV キャッシュを指定された decode worker に転送し、decode worker は decode ステージに進みます。

ステップ 1: Qwen3-32B モデルファイルの準備
次のコマンドを実行して、ModelScope から Qwen3-32B モデルをダウンロードします。
git-lfsプラグインがインストールされていない場合は、yum install git-lfsまたはapt-get install git-lfsを実行してインストールします。その他のインストール方法については、「Git Large File Storage のインストール」をご参照ください。git lfs install GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen3-32B.git cd Qwen3-32B/ git lfs pullOSS コンソールにログインし、バケットの名前を記録します。まだ作成していない場合は、「バケットの作成」をご参照ください。Object Storage Service (OSS) にディレクトリを作成し、モデルをアップロードします。
ossutil のインストールと使用方法の詳細については、「ossutil のインストール」をご参照ください。
ossutil mkdir oss://<your-bucket-name>/Qwen3-32B ossutil cp -r ./Qwen3-32B oss://<your-bucket-name>/Qwen3-32Bクラスター用に
llm-modelという名前の永続ボリューム (PV) と永続ボリューム要求 (PVC) を作成します。詳細な手順については、「PV と PVC の作成」をご参照ください。コンソールを使用した例
PV の作成
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、目的のクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。
[ボリューム] ページで、右上隅にある [作成] をクリックします。
[ボリュームの作成] ダイアログボックスで、パラメーターを設定します。
次の表に、サンプル PV の基本設定を示します:
パラメーター
説明
PV タイプ
この例では、[OSS] を選択します。
ボリューム名
この例では、[llm-model] と入力します。
アクセス証明書
OSS バケットへのアクセスに使用する AccessKey ID と AccessKey シークレットを設定します。
バケット ID
前の手順で作成した OSS バケットを選択します。
OSS パス
モデルが配置されているパス (例:
/Qwen3-32B) を入力します。
PVC の作成
[クラスター] ページで、目的のクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。
[PersistentVolumeClaims] ページで、右上隅にある [作成] をクリックします。
[PersistentVolumeClaim の作成] ページで、パラメーターを設定します。
次の表に、サンプル PVC の基本設定を示します。
設定項目
説明
PVC タイプ
この例では、[OSS] を選択します。
名前
この例では、[llm-model] と入力します。
割り当てモード
この例では、[既存のボリューム] を選択します。
既存のボリューム
[PV の選択] ハイパーリンクをクリックし、作成した PV を選択します。
kubectl を使用した例
次の YAML テンプレートを使用して、Secret、静的 PV、および 静的 PVC の設定を含む
llm-model.yamlという名前のファイルを作成します。apiVersion: v1 kind: Secret metadata: name: oss-secret stringData: akId: <your-oss-ak> # OSS バケットへのアクセスに使用する AccessKey ID。 akSecret: <your-oss-sk> # OSS バケットへのアクセスに使用する AccessKey シークレット。 --- apiVersion: v1 kind: PersistentVolume metadata: name: llm-model labels: alicloud-pvname: llm-model spec: capacity: storage: 30Gi accessModes: - ReadOnlyMany persistentVolumeReclaimPolicy: Retain csi: driver: ossplugin.csi.alibabacloud.com volumeHandle: llm-model nodePublishSecretRef: name: oss-secret namespace: default volumeAttributes: bucket: <your-bucket-name> # バケット名。 url: <your-bucket-endpoint> # エンドポイント (例: oss-cn-hangzhou-internal.aliyuncs.com)。 otherOpts: "-o umask=022 -o max_stat_cache_size=0 -o allow_other" path: <your-model-path> # この例では、パスは /Qwen3-32B/ です。 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: llm-model spec: accessModes: - ReadOnlyMany resources: requests: storage: 30Gi selector: matchLabels: alicloud-pvname: llm-modelSecret、静的 PV、および 静的 PVC を作成します。
kubectl create -f llm-model.yaml
ステップ 2: etcd および NATS サービスのインストール
Dynamo フレームワークは、サービス検出のための etcd とメッセージングのための NATS という 2 つの主要な外部サービスに依存しています。具体的には、Dynamo はノード間通信に NIXL を使用し、NIXL は etcd に登録して他のノードを検出します。NATS は、prefill worker と decode worker の間のメッセージバスとして使用されます。したがって、推論サービスを開始する前に、etcd と NATS の両方をデプロイする必要があります。
etcd.yamlという名前のファイルを作成します。etcd サービスをデプロイします。
kubectl apply -f etcd.yamlnats.yamlという名前のファイルを作成します。NATS サービスをデプロイします。
kubectl apply -f nats.yaml
ステップ 3: Dynamo PD 分離推論サービスのデプロイ
このトピックでは、RBG を使用して 2 つの prefill、1 つの decode (2P1D) の Dynamo サービスをデプロイします。prefill ロールと decode ロールの両方で、テンソル並列 (TP) サイズ 2 を使用します。デプロイアーキテクチャ:

Dynamo と qwen3 モデルの設定を保存するために、
dynamo-configs.yamlという名前の ConfigMap を作成します。kubectl apply -f dynamo-configs.yamlDynamo ランタイムイメージを準備します。
Dynamo コミュニティの手順に従って、vLLM を推論フレームワークとして使用するイメージをビルドまたはプルします。
RBG を定義するために
dynamo.yamlという名前のファイルを作成します。プレースホルダーを Dynamo ランタイムイメージのアドレスに置き換えてください。サービスをデプロイします。
kubectl apply -f ./dynamo.yaml
ステップ 4: 推論サービスの検証
テストのために、推論サービスとローカル環境の間でポートフォワーディングを確立します。
重要kubectl port-forwardによって確立されたポートフォワーディングには、本番環境レベルの信頼性、セキュリティ、スケーラビリティがありません。開発およびデバッグ目的でのみ適しており、本番環境では使用しないでください。Kubernetes クラスターでの本番環境に対応したネットワークソリューションについては、「Ingress 管理」をご参照ください。kubectl port-forward svc/dynamo-service 8000:8000期待される出力:
Forwarding from 127.0.0.1:8000 -> 8000 Forwarding from [::1]:8000 -> 8000モデル推論サービスにサンプルリクエストを送信します。
curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "qwen","messages": [{"role": "user","content": "Let's test it"}],"stream":false,"max_tokens": 30}'期待される出力:
{"id":"31ac3203-c5f9-4b06-a4cd-4435a78d3b35","choices":[{"index":0,"message":{"content":"<think>\nOkay, the user sent 'Let's test it'. I need to confirm their intent first. They might be testing my response speed or functionality, or maybe they want to","refusal":null,"tool_calls":null,"role":"assistant","function_call":null,"audio":null},"finish_reason":"length","logprobs":null}],"created":1753702438,"model":"qwen","service_tier":null,"system_fingerprint":null,"object":"chat.completion","usage":null}JSON 応答が成功すると、Dynamo PD 推論サービスが正しく実行されていることを示します。
参考資料
LLM のワークロードは頻繁に変動するため、リソースの過剰プロビジョニングやトラフィックスパイク時のパフォーマンス低下につながります。ack-alibaba-cloud-metrics-adapter と統合された Kubernetes の Horizontal Pod Autoscaler (HPA) は、次の方法でこの問題を解決します:
リアルタイムの GPU、CPU、メモリ使用率に基づいてポッドを自動的にスケーリングします。
より高度なスケーリングトリガーのためにカスタムメトリックを定義できます。
ピーク時の高可用性を確保しつつ、アイドル期間中のコストを削減します。
OSS や File Storage NAS などのサービスに保存されている大規模なモデルファイル (>10 GB) は、ダウンロード時間が長いためにポッドの起動が遅くなる (コールドスタート) 可能性があります。Fluid は、クラスターのノード全体に分散キャッシングレイヤーを作成することでこの問題を解決します。これにより、次の 2 つの主要な方法でモデルの読み込みが大幅に高速化されます:
データスループットの高速化: Fluid は、クラスター内のすべてのノードのストレージ容量とネットワーク帯域幅をプールします。これにより、単一のリモートソースから大きなファイルを取得する際のボトルネックを克服する高速な並列データレイヤーが作成されます。
I/O レイテンシーの削減: モデルファイルを必要とされる計算ノードに直接キャッシュすることで、Fluid はアプリケーションにローカルでほぼ瞬時のデータアクセスを提供します。この最適化された読み取りメカニズムにより、ネットワーク I/O に関連する長い遅延が解消されます。