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

Container Service for Kubernetes:KServe を使用したサービスのオートスケーリングポリシーの設定

最終更新日:Dec 27, 2025

KServe モデルサービスをデプロイおよび管理する際、モデル推論サービスの非常に動的な負荷変動に対応する必要があります。KServe は、ネイティブの Kubernetes Horizontal Pod Autoscaler (HPA) とスケーリングコントローラーを統合しています。これにより、CPU 使用率、メモリ使用量、GPU 使用率、およびカスタムパフォーマンスメトリックに基づいてモデルサービスの Pod 数を自動的に調整し、サービスのパフォーマンスと安定性を確保できます。このトピックでは、Qwen-7B-Chat-Int8 モデルと V100 GPU を使用して、KServe を用いたサービスの弾性スケーリングを設定する方法を説明します。

前提条件

CPU またはメモリに基づくオートスケーリングポリシーの設定

Raw Deployment モードでのオートスケーリングは、Kubernetes Horizontal Pod Autoscaler (HPA) の仕組みに依存します。HPA は、Pod の CPU またはメモリ使用量に基づいて ReplicaSet 内の Pod レプリカ数を動的に調整する基本的なオートスケーリング手法です。

このセクションでは、CPU 使用率に基づいてオートスケーリングを設定する方法を説明します。HPA メカニズムの詳細については、Kubernetes ドキュメントの「水平 Pod オートスケーリング」をご参照ください。

  1. 次のコマンドを実行して、サービスを送信します。

    arena serve kserve \
        --name=sklearn-iris \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/ai-sample/kserve-sklearn-server:v0.12.0 \
        --cpu=1 \
        --memory=200Mi \
        --scale-metric=cpu \
        --scale-target=10 \
        --min-replicas=1 \
        --max-replicas=10 \
        "python -m sklearnserver --model_name=sklearn-iris --model_dir=/models --http_port=8080"

    パラメーターは次のとおりです:

    パラメーター

    説明

    --scale-metric

    スケーリングメトリック。有効な値は cpumemory です。この例では cpu を使用します。

    --scale-target

    スケーリングのしきい値 (パーセンテージ)。

    --min-replicas

    最小レプリカ数。0 より大きい整数である必要があります。HPA ポリシーは 0 へのスケーリングをサポートしていません。

    --max-replicas

    最大レプリカ数。minReplicas の値より大きい整数である必要があります。

    予想される出力:

    inferenceservice.serving.kserve.io/sklearn-iris created
    INFO[0002] The Job sklearn-iris has been submitted successfully 
    INFO[0002] You can run `arena serve get sklearn-iris --type kserve -n default` to check the job status 

    この出力は、sklearn-iris サービスが作成されたことを示しています。

  2. 次のコマンドを実行して、推論入力リクエストを準備します。

    iris-input.json という名前のファイルを作成し、次の JSON コンテンツを追加します。このコンテンツは、モデル予測のための入力データです。

    cat <<EOF > "./iris-input.json"
    {
      "instances": [
        [6.8,  2.8,  4.8,  1.4],
        [6.0,  3.4,  4.5,  1.6]
      ]
    }
    EOF
  3. 次のコマンドを実行して、サービスにアクセスし、推論を実行します。

    # kube-system 名前空間から nginx-ingress-lb という名前のサービスのロードバランサー IP アドレスを取得します。これは外部アクセスのエントリーポイントです。
    NGINX_INGRESS_IP=`kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'`
    # sklearn-iris という名前の InferenceService の URL を取得し、後で使用するためにホスト名を抽出します。
    SERVICE_HOSTNAME=$(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    # curl コマンドを使用してモデルサービスにリクエストを送信します。リクエストヘッダーには、ターゲットホスト名 (先ほど取得した SERVICE_HOSTNAME) と JSON コンテンツタイプを指定します。-d @./iris-input.json は、リクエストボディがローカルファイル iris-input.json からのものであることを指定します。このファイルには、モデル予測に必要な入力データが含まれています。
    curl -H "Host: $SERVICE_HOSTNAME" -H "Content-Type: application/json" \
         http://$NGINX_INGRESS_IP:80/v1/models/sklearn-iris:predict -d @./iris-input.json

    予想される出力:

    {"predictions":[1,1]}%

    この出力は、2 つの推論が実行され、応答が一致していることを示しています。

  4. 次のコマンドを実行して、ストレステストを開始します。

    説明

    Hey ストレステストツールに関する詳細については、「Hey」をご参照ください。

    hey -z 2m -c 20 -m POST -host $SERVICE_HOSTNAME -H "Content-Type: application/json" -D ./iris-input.json http://${NGINX_INGRESS_IP}:80/v1/models/sklearn-iris:predict
  5. ストレステストの実行中に、別のターミナルを開き、次のコマンドを実行してサービスのスケーリングステータスを表示します。

    kubectl describe hpa sklearn-iris-predictor

    予想される出力:

    サービスのスケーリングステータスを展開して表示

    Name:                                                  sklearn-iris-predictor
    Namespace:                                             default
    Labels:                                                app=isvc.sklearn-iris-predictor
                                                           arena.kubeflow.org/uid=3399d840e8b371ed7ca45dda29debeb1
                                                           chart=kserve-0.1.0
                                                           component=predictor
                                                           heritage=Helm
                                                           release=sklearn-iris
                                                           serving.kserve.io/inferenceservice=sklearn-iris
                                                           servingName=sklearn-iris
                                                           servingType=kserve
    Annotations:                                           arena.kubeflow.org/username: kubecfg:certauth:admin
                                                           serving.kserve.io/deploymentMode: RawDeployment
    CreationTimestamp:                                     Sat, 11 May 2024 17:15:47 +0800
    Reference:                                             Deployment/sklearn-iris-predictor
    Metrics:                                               ( current / target )
      resource cpu on pods  (as a percentage of request):  0% (2m) / 10%
    Min replicas:                                          1
    Max replicas:                                          10
    Behavior:
      Scale Up:
        Stabilization Window: 0 seconds
        Select Policy: Max
        Policies:
          - Type: Pods     Value: 4    Period: 15 seconds
          - Type: Percent  Value: 100  Period: 15 seconds
      Scale Down:
        Select Policy: Max
        Policies:
          - Type: Percent  Value: 100  Period: 15 seconds
    Deployment pods:       10 current / 10 desired
    Conditions:
      Type            Status  Reason               Message
      ----            ------  ------               -------
      AbleToScale     True    ScaleDownStabilized  recent recommendations were higher than current one, applying the highest recent recommendation
      ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
      ScalingLimited  False   DesiredWithinRange   the desired count is within the acceptable range
    Events:
      Type    Reason             Age                  From                       Message
      ----    ------             ----                 ----                       -------
      Normal  SuccessfulRescale  38m                  horizontal-pod-autoscaler  New size: 8; reason: cpu resource utilization (percentage of request) above target
      Normal  SuccessfulRescale  28m                  horizontal-pod-autoscaler  New size: 7; reason: All metrics below target
      Normal  SuccessfulRescale  27m                  horizontal-pod-autoscaler  New size: 1; reason: All metrics below target

    出力の Events セクションは、HPA が CPU 使用率に基づいてレプリカ数を自動的に調整したことを示しています。たとえば、レプリカ数は異なる時点で 8、7、1 に変更されました。これは、HPA が CPU 使用率に基づいて自動的にスケーリングできることを示しています。

GPU 使用率に基づくカスタムメトリックベースの弾性スケーリングポリシーの設定

カスタムメトリックベースのオートスケーリングは、Container Service for Kubernetes (ACK) が提供する ack-alibaba-cloud-metrics-adapter コンポーネントと Kubernetes HPA の仕組みに依存します。詳細については、「Alibaba Cloud Prometheus メトリックに基づく水平 Pod オートスケーリング」をご参照ください。

次の例では、Pod の GPU 使用率に基づいてカスタムメトリックベースのオートスケーリングを設定する方法を説明します。

  1. Qwen-7B-Chat-Int8 モデルデータを準備します。詳細については、「vLLM 推論サービスのデプロイ」をご参照ください。

  2. カスタム GPU メトリックを設定します。詳細については、「GPU メトリックに基づく弾性スケーリングの実装」をご参照ください。

  3. 次のコマンドを実行して、vLLM サービスをデプロイします。

    arena serve kserve \
        --name=qwen \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \
        --gpus=1 \
        --cpu=4 \
        --memory=12Gi \
        --scale-metric=DCGM_CUSTOM_PROCESS_SM_UTIL \
        --scale-target=50 \
        --min-replicas=1 \
        --max-replicas=2 \
        --data="llm-model:/mnt/models/Qwen-7B-Chat-Int8" \
        "python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen-7B-Chat-Int8 --gpu-memory-utilization 0.95 --quantization gptq --max-model-len=6144"

    予想される出力:

    inferenceservice.serving.kserve.io/qwen created
    INFO[0002] The Job qwen has been submitted successfully 
    INFO[0002] You can run `arena serve get qwen --type kserve -n default` to check the job status 

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

  4. 次のコマンドを実行して、NGINX Ingress ゲートウェイアドレスを使用して推論サービスにアクセスし、vLLM サービスが正しく実行されているかをテストします。

    # Nginx Ingress の IP アドレスを取得します。
    NGINX_INGRESS_IP=$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}')
    # Inference Service のホスト名を取得します。
    SERVICE_HOSTNAME=$(kubectl get inferenceservice qwen -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    # リクエストを送信して推論サービスにアクセスします。
    curl -H "Host: $SERVICE_HOSTNAME" -H "Content-Type: application/json" http://$NGINX_INGRESS_IP:80/v1/chat/completions -d '{"model": "qwen", "messages": [{"role": "user", "content": "Test"}], "max_tokens": 10, "temperature": 0.7, "top_p": 0.9, "seed": 10}'

    予想される出力:

    {"id":"cmpl-77088b96abe744c89284efde2e779174","object":"chat.completion","created":1715590010,"model":"qwen","choices":[{"index":0,"message":{"role":"assistant","content":"OK, what do you need to test?<|im_end|>"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":10,"total_tokens":20,"completion_tokens":10}}%    

    この出力は、リクエストがサーバーに送信され、サーバーが期待される JSON 応答を返したことを示しています。

  5. 次のコマンドを実行して、サービスに対してストレステストを実行します。

    説明

    Hey ストレステストツールに関する詳細については、「Hey」をご参照ください。

    hey -z 2m -c 5 -m POST -host $SERVICE_HOSTNAME -H "Content-Type: application/json" -d '{"model": "qwen", "messages": [{"role": "user", "content": "Test"}], "max_tokens": 10, "temperature": 0.7, "top_p": 0.9, "seed": 10}' http://$NGINX_INGRESS_IP:80/v1/chat/completions 
  6. ストレステスト中に、新しいターミナルを開き、次のコマンドを実行してサービスのスケーリングステータスを表示します。

    kubectl describe hpa qwen-hpa

    予想される出力:

    qwen-hpa のスケーリングステータスを展開して表示

    Name:                                     qwen-hpa
    Namespace:                                default
    Labels:                                   <none>
    Annotations:                              <none>
    CreationTimestamp:                        Tue, 14 May 2024 14:57:03 +0800
    Reference:                                Deployment/qwen-predictor
    Metrics:                                  ( current / target )
      "DCGM_CUSTOM_PROCESS_SM_UTIL" on pods:  0 / 50
    Min replicas:                             1
    Max replicas:                             2
    Deployment pods:                          1 current / 1 desired
    Conditions:
      Type            Status  Reason            Message
      ----            ------  ------            -------
      AbleToScale     True    ReadyForNewScale  recommended size matches current size
      ScalingActive   True    ValidMetricFound  the HPA was able to successfully calculate a replica count from pods metric DCGM_CUSTOM_PROCESS_SM_UTIL
      ScalingLimited  True    TooFewReplicas    the desired replica count is less than the minimum replica count
    Events:
      Type    Reason             Age   From                       Message
      ----    ------             ----  ----                       -------
      Normal  SuccessfulRescale  43m   horizontal-pod-autoscaler  New size: 2; reason: pods metric DCGM_CUSTOM_PROCESS_SM_UTIL above target
      Normal  SuccessfulRescale  34m   horizontal-pod-autoscaler  New size: 1; reason: All metrics below target

    この出力は、ストレステスト中に Pod の数が 2 にスケールアウトすることを示しています。テスト終了後、約 5 分で Pod の数は 1 にスケールインします。これは、KServe が Pod の GPU 使用率に基づいてカスタムメトリックベースのオートスケーリングを実行できることを示しています。

定時オートスケーリングポリシーの設定

定時オートスケーリングには、ACK が提供する ack-kubernetes-cronhpa-controller コンポーネントが必要です。このコンポーネントを使用すると、特定の時間または間隔でアプリケーションのレプリカ数を変更して、予測可能な負荷変動に対応できます。

  1. CronHPA コンポーネントをインストールします。詳細については、「CronHPA を使用したコンテナの定時水平スケーリング」をご参照ください。

  2. Qwen-7B-Chat-Int8 モデルデータを準備します。詳細については、「vLLM 推論サービスのデプロイ」をご参照ください。

  3. 次のコマンドを実行して、vLLM サービスをデプロイします。

    arena serve kserve \
        --name=qwen-cronhpa \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \
        --gpus=1 \
        --cpu=4 \
        --memory=12Gi \
        --annotation="serving.kserve.io/autoscalerClass=external" \
        --data="llm-model:/mnt/models/Qwen-7B-Chat-Int8" \
       "python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen-7B-Chat-Int8 --gpu-memory-utilization 0.95 --quantization gptq --max-model-len=6144"

    予想される出力:

    inferenceservice.serving.kserve.io/qwen-cronhpa created
    INFO[0004] The Job qwen-cronhpa has been submitted successfully 
    INFO[0004] You can run `arena serve get qwen-cronhpa --type kserve -n default` to check the job status 
  4. 次のコマンドを実行して、vLLM サービスが正しく実行されているかをテストします。

    # Nginx Ingress の IP アドレスを取得します。
    NGINX_INGRESS_IP=`kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'`
    # Inference Service のホスト名を取得します。
    SERVICE_HOSTNAME=$(kubectl get inferenceservice qwen-cronhpa -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    # リクエストを送信して推論サービスにアクセスします。
    curl -H "Host: ${SERVICE_HOSTNAME}" -H "Content-Type: application/json" \
         http://$NGINX_INGRESS_IP:80/v1/chat/completions -X POST \
         -d '{"model": "qwen", "messages": [{"role": "user", "content": "Hello"}], "max_tokens": 512, "temperature": 0.7, "top_p": 0.9, "seed": 10, "stop":["<|endoftext|>", "<|im_end|>", "<|im_start|>"]}'

    予想される出力:

    {"id":"cmpl-b7579597aa284f118718b22b83b726f8","object":"chat.completion","created":1715589652,"model":"qwen","choices":[{"index":0,"message":{"role":"assistant","content":"OK, what do you need to test?<|im_end|>"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":10,"total_tokens":20,"completion_tokens":10}}% 

    この出力は、リクエストがサービスに送信され、サービスが期待される JSON 応答を返したことを示しています。

  5. 次のコマンドを実行して、定時オートスケーリングを設定します。

    定時オートスケーリングを設定するコマンドを展開して表示

    kubectl apply -f- <<EOF
    apiVersion: autoscaling.alibabacloud.com/v1beta1
    kind: CronHorizontalPodAutoscaler
    metadata:
      name: qwen-cronhpa
      namespace: default 
    spec:
       scaleTargetRef:
          apiVersion: apps/v1
          kind: Deployment
          name: qwen-cronhpa-predictor
       jobs:
       # 毎日 10:30 にスケールアウトします。
       - name: "scale-up"
         schedule: "0 30 10 * * *"
         targetSize: 2
         runOnce: false
      # 毎日 12:00 にスケールインします。
       - name: "scale-down"
         schedule: "0 0 12 * * *"
         targetSize: 1
         runOnce: false
    EOF

    予想される出力:

    プリセットされたスケーリング設定を展開して表示

    Name:         qwen-cronhpa
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  autoscaling.alibabacloud.com/v1beta1
    Kind:         CronHorizontalPodAutoscaler
    Metadata:
      Creation Timestamp:  2024-05-12T14:06:49Z
      Generation:          2
      Resource Version:    9205625
      UID:                 b9e72da7-262e-4***-b***-26586b7****c
    Spec:
      Jobs:
        Name:         scale-up
        Schedule:     0 30 10 * * *
        Target Size:  2
        Name:         scale-down
        Schedule:     0 0 12 * * *
        Target Size:  1
      Scale Target Ref:
        API Version:  apps/v1
        Kind:         Deployment
        Name:         qwen-cronhpa-predictor
    Status:
      Conditions:
        Job Id:           3972f7cc-bab0-482e-8cbe-7c4*******5
        Last Probe Time:  2024-05-12T14:06:49Z
        Message:          
        Name:             scale-up
        Run Once:         false
        Schedule:         0 30 10 * * *
        State:            Submitted
        Target Size:      2
        Job Id:           36a04605-0233-4420-967c-ac2********6
        Last Probe Time:  2024-05-12T14:06:49Z
        Message:          
        Name:             scale-down
        Run Once:         false
        Schedule:         0 0 12 * * *
        State:            Submitted
        Target Size:      1
      Scale Target Ref:
        API Version:  apps/v1
        Kind:         Deployment
        Name:         qwen-cronhpa-predictor
    Events:           <none>
    

    この出力は、qwen-cronhpa CRD に対して定時オートスケーリングプランが設定されたことを示しています。スケジュールに基づき、qwen-cronhpa-predictor デプロイメントの Pod 数は、プリセットされたスケーリング要件を満たすために毎日特定の時間に自動的に調整されます。

関連ドキュメント

ACK の弾性スケーリングに関する詳細については、「Auto Scaling」をご参照ください。