Kubernetes クラスターにおける大規模言語モデル (LLM) 推論サービス向けの従来の負荷分散は、単純なトラフィック割り当てに依存しているため、複雑なリクエストや動的なトラフィック負荷の処理には不十分なことがよくあります。このトピックでは、Gateway with Inference Extension コンポーネントを使用して、インテリジェントルーティングと効率的なトラフィック管理のための推論サービス拡張を構成する方法について説明します。
背景情報
KV キャッシュ
操作手順
次の図は、ワークフローを示しています。
-
inference-gateway では、ポート 8080 は標準の HTTP ルートを使用してリクエストをバックエンドの推論サービスに転送します。ポート 8081 は、LLM Route 拡張を介してリクエストをルーティングし、それが同じサービスにリクエストを転送します。
-
HTTP ルート内で、
InferencePoolリソースを使用して LLM 推論サービスワークロードのグループを宣言し、InferenceModelリソースを使用してそのInferencePool内のモデルのトラフィック分散ポリシーを指定します。この構成により、推論サービス向けに強化された負荷分散アルゴリズムを使用して、inference-gateway のポート 8081 からのリクエストが指定された LLM 推論サービスワークロードにルーティングされます。
前提条件
GPU ノードプールを持つ ACK マネージドクラスター が必要です。また、ACK マネージドクラスターに ACK Virtual Node コンポーネントをインストールして、ACS GPU コンピューティング能力 を使用することもできます。
操作手順
ステップ 1:サンプル推論サービスのデプロイ
-
次の内容で vllm-service.yaml という名前のファイルを作成します。
説明このイメージでは、ACK クラスターでは A10 カード、Alibaba Cloud Container Compute Service では L20 (GN8IS) カードの使用を推奨します。
また、LLM イメージはサイズが大きいため、Container Registry にプッシュし、内部アドレスを使用してプルすることを推奨します。パブリックネットワークから直接イメージをプルすると、クラスターの EIP (Elastic IP) アドレスの帯域幅によって速度が制限されるため、遅くなる可能性があります。
-
サンプル推論サービスをデプロイします。
kubectl apply -f vllm-service.yaml
ステップ 2:Gateway with Inference Extension コンポーネントのインストール
か、Gateway with Inference Extension コンポーネントをインストールし、Gateway API 推論拡張を有効にする (デプロイ済みの推論サービスが必要) が選択されていることを確認します。

ステップ 3:推論ルーティングのデプロイ
このステップでは、InferencePool および InferenceModel リソースを作成します。
-
inference-pool.yamlファイルを作成します。apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferencePool metadata: name: vllm-qwen-pool spec: targetPortNumber: 8000 selector: app: qwen extensionRef: name: inference-gateway-ext-proc --- apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferenceModel metadata: name: inferencemodel-qwen spec: modelName: /model/qwen criticality: Critical poolRef: group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool targetModels: - name: /model/qwen weight: 100 -
推論ルーティングをデプロイします。
kubectl apply -f inference-pool.yaml
ステップ 4:ゲートウェイのデプロイと検証
このステップでは、ポート 8080 と 8081 でリッスンするゲートウェイを作成します。
-
inference-gateway.yamlという名前のファイルを作成します。apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: qwen-inference-gateway-class spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: qwen-inference-gateway spec: gatewayClassName: qwen-inference-gateway-class listeners: - name: http protocol: HTTP port: 8080 - name: llm-gw protocol: HTTP port: 8081 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend spec: parentRefs: - name: qwen-inference-gateway sectionName: llm-gw rules: - backendRefs: - group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool matches: - path: type: PathPrefix value: / --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend-no-inference spec: parentRefs: - group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gateway sectionName: http rules: - backendRefs: - group: "" kind: Service name: qwen port: 8000 weight: 1 matches: - path: type: PathPrefix value: / --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: backend-timeout spec: timeout: http: requestTimeout: 1h targetRef: group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gateway -
ゲートウェイをデプロイします。
kubectl apply -f inference-gateway.yamlこの構成により、
envoy-gateway-systemという名前の名前空間と、envoy-default-inference-gateway-645xxxxxという名前のサービスがクラスターに作成されます。 -
ゲートウェイのパブリック IP アドレスを取得します。
export GATEWAY_HOST=$(kubectl get gateway/qwen-inference-gateway -o jsonpath='{.status.addresses[0].value}') -
ゲートウェイがポート 8080 で標準の HTTP ルーティングを使用して推論サービスにリクエストをルーティングすることを確認します。
curl -X POST ${GATEWAY_HOST}:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: San Francisco" } ] }'期待される出力:
{"id":"chatcmpl-aa6438e2-d65b-4211-afb8-ae8e76e7a692","object":"chat.completion","created":1747191180,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"San Francisco, a city that has long been a beacon of innovation, culture, and diversity, continues to captivate the world with its unique charm and character. As a critic, I find myself both enamored and occasionally perplexed by the city's multifaceted personality.\n\nSan Francisco's architecture is a testament to its rich history and progressive spirit. The iconic cable cars, Victorian houses, and the Golden Gate Bridge are not just tourist attractions but symbols of the city's enduring appeal. However, the","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null} -
ゲートウェイがポート 8081 で推論サービス拡張を使用して推論サービスにリクエストをルーティングすることを確認します。
curl -X POST ${GATEWAY_HOST}:8081/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: Los Angeles" } ] }'期待される出力:
{"id":"chatcmpl-cc4fcd0a-6a66-4684-8dc9-284d4eb77bb7","object":"chat.completion","created":1747191969,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"Los Angeles, the sprawling metropolis often referred to as \"L.A.,\" is a city that defies easy description. It is a place where dreams are made and broken, where the sun never sets, and where the line between reality and fantasy is as blurred as the smog that often hangs over its valleys. As a critic, I find myself both captivated and perplexed by this city that is as much a state of mind as it is a physical place.\n\nOn one hand, Los","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}
(オプション) ステップ 5:可観測性メトリクスとダッシュボードの構成
クラスターに対して Managed Service for Prometheus を有効にして構成する必要があります。これには追加料金が発生する場合があります。
-
vLLM サービス Pod に Prometheus アノテーションを追加して、メトリック収集を有効にできます。その後、Prometheus インスタンスは、その デフォルトのサービス検出 メカニズムを使用して vLLM サービスのメトリックをスクレイプし、サービスの内部状態を監視できます。
... annotations: prometheus.io/path: /metrics # メトリックが公開される HTTP パス。 prometheus.io/port: "8000" # メトリックを公開するポート。vLLM サーバーのリッスンポートです。 prometheus.io/scrape: "true" # 現在の Pod からメトリックをスクレイプするかどうか。 ...次の表は、vLLM サービスが提供する監視メトリックの一部を示しています:
メトリック
説明
vllm:gpu_cache_usage_perc
vLLM によって使用される GPU キャッシュの割合。vLLM が起動すると、KV キャッシュのために可能な限り多くの GPU ビデオメモリを事前に割り当てます。vLLM サーバーの場合、使用率が低いほど、GPU に新しいリクエストのための十分なスペースがあることを意味します。
vllm:request_queue_time_seconds_sum
リクエストが待機キューで費やした合計時間。LLM 推論リクエストが vLLM サーバーに到着した後、すぐに処理されない場合があります。代わりに、プレフィルとデコードのために vLLM スケジューラによってスケジュールされるのを待つ必要があります。
vllm:num_requests_running
vllm:num_requests_waiting
vllm:num_requests_swapped
現在実行中、待機中、またはメモリにスワップされたリクエストの数。これらのメトリックを使用して、vLLM サービスの現在のリクエスト負荷を評価できます。
vllm:avg_generation_throughput_toks_per_s
vllm:avg_prompt_throughput_toks_per_s
プレフィル段階で消費される 1 秒あたりのトークン数と、デコード段階で生成される 1 秒あたりのトークン数。
vllm:time_to_first_token_seconds_bucket
vLLM サービスにリクエストを送信してから最初のトークンを受信するまでのレイテンシー。一般に初回トークン生成時間 (TTFT) として知られ、このメトリックはクライアントがリクエストを送信してから応答の最初の部分を受信するまでの時間を測定します。TTFT は、LLM ユーザーエクスペリエンスの重要な指標です。
これらのメトリックに基づいてアラートルールを設定し、vLLM サービスを監視してリアルタイムで異常を検出できます。
-
LLM 推論サービスをリアルタイムで監視するために Grafana ダッシュボードを構成します。このダッシュボードを使用して、次のことができます:
-
LLM サービスのリクエストレートと合計トークンスループットを監視します。
-
推論ワークロードの内部状態を監視します。
Grafana のデータソースとして使用される Prometheus インスタンスが vLLM 監視メトリックを収集していることを確認してください。ダッシュボードを作成するには、次の JSON コンテンツを Grafana にインポートします。

プレビュー:

-
-
ACK クラスターで、vllm ベンチマーク を使用して推論サービスに負荷テストを行い、HTTP Route と LLM Route の負荷分散を比較します。
-
ベンチマークワークロードをデプロイします。
kubectl apply -f- <<EOF apiVersion: apps/v1 kind: Deployment metadata: labels: app: vllm-benchmark name: vllm-benchmark namespace: default spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: vllm-benchmark strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: vllm-benchmark spec: containers: - command: - sh - -c - sleep inf image: registry-cn-hangzhou.ack.aliyuncs.com/dev/llm-benchmark:random-and-qa imagePullPolicy: IfNotPresent name: vllm-benchmark resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 EOF -
負荷テストを開始します。
-
ゲートウェイの内部 IP アドレスを取得します。
export GW_IP=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=qwen-inference-gateway -o jsonpath='{.items[0].spec.clusterIP}') -
負荷テストを実行します。
HTTP ルート
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8080 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txtLLM ルート
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8081 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txt
-
両方のテストを完了した後、ダッシュボードを表示して、HTTP Route と LLM Route のルーティングパフォーマンスを比較します。

ダッシュボードを見ると、HTTP Route ワークロードのキャッシュ使用率の分布が不均一であるのに対し、LLM Route ワークロードは正規分布を示していることがわかります。
-
関連操作
は、さまざまな推論サービスのユースケースに対応する異なる負荷分散戦略をサポートしています。InferencePool 内の Pod にルーティングされる推論リクエストの負荷分散戦略を構成するには、InferencePool リソースに inference.networking.x-k8s.io/routing-strategy アノテーションを追加します。
次の例では、app: vllm-app セレクターを使用して推論サービス Pod を選択し、負荷分散戦略をデフォルトのメトリクスベースの戦略に設定します。
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: vllm-app-pool
annotations:
inference.networking.x-k8s.io/routing-strategy: "DEFAULT"
spec:
targetPortNumber: 8000
selector:
app: vllm-app
extensionRef:
name: inference-gateway-ext-proc
次の負荷分散戦略がサポートされています:
|
戦略 |
説明 |
|
DEFAULT |
メトリクスベースの負荷分散戦略。この戦略は、リクエストキューの長さや GPU キャッシュ使用率などの多次元メトリックを使用して推論サーバーの内部状態を評価します。その後、この状態に基づいて複数の推論サーバーワークロードにトラフィックを分散します。 |
|
PREFIX_CACHE |
リクエストプレフィックスマッチングを使用する負荷分散戦略。この戦略は、共通のプレフィックスを共有するリクエストを同じ推論サーバー Pod にルーティングしようとします。この戦略は、特に推論サーバーで自動プレフィックスキャッシングが有効になっている場合に、プレフィックスを共有するリクエストが大量に発生するシナリオに最適です。 典型的なユースケースは次のとおりです:
|