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

Container Service for Kubernetes:スタンドアロンまたは分散 LLM 推論サービスの自動スケーリングを設定する

最終更新日:Sep 19, 2025

大規模言語モデル (LLM) 推論サービスを管理する場合、ワークロードの非常に動的な変動に対処することが重要です。このトピックでは、推論フレームワークのカスタムメトリックと Kubernetes Horizontal Pod Autoscaler (HPA) を組み合わせて、推論サービスポッドを自動的かつ柔軟にスケーリングする方法について説明します。これにより、LLM サービスの高い可用性と安定性が確保されます。

前提条件

課金

Managed Service for Prometheus との統合により、サービスはカスタムメトリックを発行し、これにより追加料金が発生する場合があります。これらの料金は、クラスターのサイズ、アプリケーションの数、データ量などの要因によって異なります。使用状況データをクエリすることで、リソースを監視および管理できます。

ステップ 1: メトリック収集の設定

従来のマイクロサービスとは異なり、LLM 推論サービスは、CPU やシステムメモリではなく、GPU の計算能力とメモリによってボトルネックになることがよくあります。GPU 使用率やメモリ使用量などの標準的なメトリックは、推論サービスの実際の負荷を判断する上で誤解を招く可能性があります。したがって、より効果的なアプローチは、リクエストの待機時間やキューの深さなど、推論エンジンによって直接公開されるパフォーマンスメトリックに基づいてスケーリングすることです。

LLM 推論サービスのモニタリングを設定している場合は、このステップをスキップできます。
  1. podmonitor.yaml という名前のファイルを作成し、Prometheus が推論ポッドからメトリックをスクレイプするように指示します。

    YAML テンプレート

    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      name: llm-serving-podmonitor
      namespace: default
      annotations:
        arms.prometheus.io/discovery: "true"
        arms.prometheus.io/resource: "arms"
    spec:
      selector:
        matchExpressions:
        - key: alibabacloud.com/inference-workload
          operator: Exists
      namespaceSelector:
        any: true
      podMetricsEndpoints:
      - interval: 15s
        path: /metrics
        port: "http"
        relabelings:
        - action: replace
          sourceLabels:
          - __meta_kubernetes_pod_name
          targetLabel: pod_name
        - action: replace
          sourceLabels:
          - __meta_kubernetes_namespace
          targetLabel: pod_namespace
        - action: replace
          sourceLabels:
          - __meta_kubernetes_pod_label_rolebasedgroup_workloads_x_k8s_io_role
          regex: (.+)
          targetLabel: rbg_role
        # 特定のラベルで workload-name をオーバーライドすることを許可
        - action: replace
          sourceLabels:
          - __meta_kubernetes_pod_label_alibabacloud_com_inference_workload
          regex: (.+)
          targetLabel: workload_name
        - action: replace
          sourceLabels:
          - __meta_kubernetes_pod_label_alibabacloud_com_inference_backend
          regex: (.+)
          targetLabel: backend
    
  2. 設定を適用します。

    kubectl apply -f ./podmonitor.yaml

ステップ 2: ack-alibaba-cloud-metrics-adapter の設定

  1. ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、ターゲットクラスターの名前をクリックします。左側のナビゲーションウィンドウで、[アプリケーション] > [Helm] をクリックします。

  3. [Helm] ページで、ack-alibaba-cloud-metrics-adapter を見つけ、[アクション] 列の [更新] をクリックします。

  4. [リリースを更新] パネルで、次の例に示すように YAML 設定を更新し、[OK] をクリックします。YAML のメトリックはデモンストレーションのみを目的としています。必要に応じて変更してください。

    vLLMSGLang、および Dynamo のメトリックの完全なリストについては、公式ドキュメントをご参照ください。

    YAML テンプレート

    AlibabaCloudMetricsAdapter:
    
      prometheus:
        enabled: true    # Prometheus アダプター機能を有効にするには、これを true に設定します。
        # Managed Service for Prometheus の URL を入力します。
        url: http://cn-beijing.arms.aliyuncs.com:9090/api/v1/prometheus/xxxx/xxxx/xxx/cn-beijing
        # Managed Service for Prometheus でトークンベースの認証が有効になっている場合は、prometheusHeader フィールドの Authorization パラメーターを設定します。
    #    prometheusHeader:
    #    - Authorization: xxxxxxx
    
        adapter:
          rules:
            default: false  			# デフォルトのメトリック収集設定。これを false のままにします。
            custom:
    
            # ** 例 1: これは vLLM の例です **
            # vllm:num_requests_waiting: 待機中のリクエスト数。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/vllm:num_requests_waiting"
            - seriesQuery: 'vllm:num_requests_waiting{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
    
            # vllm:num_requests_running: 処理中のリクエスト数。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/vllm:num_requests_running"
            - seriesQuery: 'vllm:num_requests_running{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
    
            # vllm:kv_cache_usage_perc: KV キャッシュ使用率。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/vllm:kv_cache_usage_perc"
            - seriesQuery: 'vllm:kv_cache_usage_perc{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
    
            # ** 例 2: これは SGLang の例です **
            # sglang:num_queue_reqs: 待機中のリクエスト数。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/sglang:num_queue_reqs"
            - seriesQuery: 'sglang:num_queue_reqs{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
            # sglang:num_running_reqs: 処理中のリクエスト数。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/sglang:num_running_reqs"
            - seriesQuery: 'sglang:num_running_reqs{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
              # sglang:token_usage: システム内のトークン使用量。KV キャッシュの使用率を反映できます。
              # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
              # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/sglang:token_usage"
            - seriesQuery: 'sglang:token_usage{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
    
            # 例 3: これは Dynamo の例です
            # nv_llm_http_service_inflight_requests: 処理中のリクエスト数。
            # 次のコマンドを実行して、メトリックが収集されているかどうかを確認します。
            # kubectl get --raw  "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/nv_llm_http_service_inflight_requests"
            - seriesQuery: 'nv_llm_http_service_inflight_requests{namespace!="",pod!=""}'
              resources:
                overrides:
                  namespace: { resource: "namespace" }
                  pod: { resource: "pod" }
              metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
    
    

ステップ 3: HPA の設定

推論サービスをターゲットとし、設定したカスタムメトリックのいずれかを使用する HPA リソースを作成します。

説明

次のスケーリングポリシーのパラメーター設定は、デモンストレーションのみを目的としています。パフォーマンステスト、リソースコスト、およびサービスレベル目標 (SLO) に基づいて、特定のユースケースに適したしきい値を決定してください。

  1. hpa.yaml という名前のファイルを作成します。推論フレームワークに一致する例を選択してください。

    vLLM

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: llm-inference-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: StatefulSet
        name: vllm-inference # vLLM 推論サービス名に置き換えます。
      minReplicas: 1
      maxReplicas: 3
      metrics:
      - type: Pods
        pods:
          metric:
            name: vllm:num_requests_waiting
          target:
            type: Value
            averageValue: 5
    

    SGLang

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: llm-inference-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: StatefulSet
        name: sgl-inference
      minReplicas: 1
      maxReplicas: 3
      metrics:
      - type: Pods
        pods:
          metric:
            name: sglang:num_queue_reqs
          target:
            type: Value
            averageValue: 5

    HPA 設定を適用します。

    kubectl apply -f hpa.yaml

ステップ 4: 自動スケーリング設定のテスト

benchmark ツールを使用してサービスに負荷をかけ、HPA をトリガーします。

benchmark ツールの詳細と使用方法については、「vLLM Benchmark」および「SGLang Benchmark」をご参照ください。
  1. benchmark.yaml という名前のファイルを作成します。

    • テストしている推論フレームワークに一致するコンテナイメージを指定します。次のいずれかのオプションを選択します。

      • vLLM の場合: kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:v0.10.0

      • SGLang の場合: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/anolis-docker-images/docker-temp:0.3.4.post2-sglang0.4.10.post2-pytorch2.7.1.8-cuda12.8.1-py312-alinux3.2104

    YAML テンプレート

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      labels:
        app: llm-benchmark
      name: llm-benchmark
    spec:
      selector:
        matchLabels:
          app: llm-benchmark
      template:
        metadata:
          labels:
            app: llm-benchmark
        spec:
          hostNetwork: true
          dnsPolicy: ClusterFirstWithHostNet
          containers:
          - command:
            - sh
            - -c
            - sleep inf
            image: # 推論サービスのデプロイに使用される SGLang または vLLM コンテナイメージ
            imagePullPolicy: IfNotPresent
            name: llm-benchmark
            resources:
              limits:
                cpu: "8"
                memory: 40 Gi
              requests:
                cpu: "8"
                memory: 40 Gi
            volumeMounts:
            - mountPath: /models/Qwen3-32B
              name: llm-model
          volumes:
          - name: llm-model
            persistentVolumeClaim:
              claimName: llm-model
  2. ベンチマーククライアントポッドをデプロイしてトラフィックを生成します。

    kubectl create -f benchmark.yaml
  3. クライアントポッド内からベンチマークスクリプトを実行して、推論サービスに高い負荷を生成します。

    vLLM

    python3 $VLLM_ROOT_DIR/benchmarks/benchmark_serving.py \
            --model /models/Qwen3-32B \
            --host inference-service \
            --port 8000 \
            --dataset-name random \
            --random-input-len 1500 \
            --random-output-len 100 \
            --random-range-ratio 1 \
            --num-prompts 400 \
            --max-concurrency 20

    SGLang

    python3 -m sglang.bench_serving --backend sglang \
            --model /models/Qwen3-32B \
            --host inference-service \
            --port 8000 \
            --dataset-name random \
            --random-input-len 1500 \
            --random-output-len 100 \
            --random-range-ratio 1 \
            --num-prompts 400 \
            --max-concurrency 20

負荷テストの実行中に、新しいターミナルを開き、HPA のステータスを監視します。

kubectl describe hpa llm-inference-hpa

イベントログには、SuccessfulRescale イベントが表示され、HPA が待機中のリクエスト数が高いことを検出し、レプリカ数を 1 から 3 にスケールアップしたことを示します。

Name:                                   llm-inference-hpa
Namespace:                              default
Labels:                                 <none>
Annotations:                            <none>
CreationTimestamp:                      Fri, 25 Jul 2025 11:29:20 +0800
Reference:                              StatefulSet/vllm-inference
Metrics:                                ( current / target )
  "vllm:num_requests_waiting" on pods:  11 / 5
Min replicas:                           1
Max replicas:                           3
StatefulSet pods:                       1 current / 3 desired
Conditions:
  Type            Status  Reason              Message
  ----            ------  ------              -------
  AbleToScale     True    SucceededRescale    HPA コントローラーはターゲットスケールを 3 に更新できました
  ScalingActive   True    ValidMetricFound    HPA はポッドメトリック vllm:num_requests_waiting からレプリカ数を正常に計算できました
  ScalingLimited  False   DesiredWithinRange  希望するカウントは許容範囲内です
Events:
  Type    Reason             Age   From                       Message
  ----    ------             ----  ----                       -------
  Normal  SuccessfulRescale  1s    horizontal-pod-autoscaler  新しいサイズ: 3; 理由: ポッドメトリック vllm:num_requests_waiting がターゲットを超えています