KServe モデルサービスをデプロイおよび管理する際、モデル推論サービスの非常に動的な負荷変動に対応する必要があります。KServe は、ネイティブの Kubernetes Horizontal Pod Autoscaler (HPA) とスケーリングコントローラーを統合しています。これにより、CPU 使用率、メモリ使用量、GPU 使用率、およびカスタムパフォーマンスメトリックに基づいてモデルサービスの Pod 数を自動的に調整し、サービスのパフォーマンスと安定性を確保できます。このトピックでは、Qwen-7B-Chat-Int8 モデルと V100 GPU を使用して、KServe を用いたサービスの弾性スケーリングを設定する方法を説明します。
前提条件
バージョン 0.9.15 以降の Arena クライアントがインストールされていること。詳細については、「Arena クライアントの設定」をご参照ください。
ack-kserve コンポーネントがインストールされていること。詳細については、「ack-kserve コンポーネントのインストール」をご参照ください。
CPU またはメモリに基づくオートスケーリングポリシーの設定
Raw Deployment モードでのオートスケーリングは、Kubernetes Horizontal Pod Autoscaler (HPA) の仕組みに依存します。HPA は、Pod の CPU またはメモリ使用量に基づいて ReplicaSet 内の Pod レプリカ数を動的に調整する基本的なオートスケーリング手法です。
このセクションでは、CPU 使用率に基づいてオートスケーリングを設定する方法を説明します。HPA メカニズムの詳細については、Kubernetes ドキュメントの「水平 Pod オートスケーリング」をご参照ください。
次のコマンドを実行して、サービスを送信します。
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
スケーリングメトリック。有効な値は
cpuとmemoryです。この例では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 サービスが作成されたことを示しています。
次のコマンドを実行して、推論入力リクエストを準備します。
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次のコマンドを実行して、サービスにアクセスし、推論を実行します。
# 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 つの推論が実行され、応答が一致していることを示しています。
次のコマンドを実行して、ストレステストを開始します。
説明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ストレステストの実行中に、別のターミナルを開き、次のコマンドを実行してサービスのスケーリングステータスを表示します。
kubectl describe hpa sklearn-iris-predictor予想される出力:
出力の
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 使用率に基づいてカスタムメトリックベースのオートスケーリングを設定する方法を説明します。
Qwen-7B-Chat-Int8 モデルデータを準備します。詳細については、「vLLM 推論サービスのデプロイ」をご参照ください。
カスタム GPU メトリックを設定します。詳細については、「GPU メトリックに基づく弾性スケーリングの実装」をご参照ください。
次のコマンドを実行して、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この出力は、推論サービスがデプロイされたことを示しています。
次のコマンドを実行して、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 応答を返したことを示しています。
次のコマンドを実行して、サービスに対してストレステストを実行します。
説明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ストレステスト中に、新しいターミナルを開き、次のコマンドを実行してサービスのスケーリングステータスを表示します。
kubectl describe hpa qwen-hpa予想される出力:
この出力は、ストレステスト中に Pod の数が 2 にスケールアウトすることを示しています。テスト終了後、約 5 分で Pod の数は 1 にスケールインします。これは、KServe が Pod の GPU 使用率に基づいてカスタムメトリックベースのオートスケーリングを実行できることを示しています。
定時オートスケーリングポリシーの設定
定時オートスケーリングには、ACK が提供する ack-kubernetes-cronhpa-controller コンポーネントが必要です。このコンポーネントを使用すると、特定の時間または間隔でアプリケーションのレプリカ数を変更して、予測可能な負荷変動に対応できます。
CronHPA コンポーネントをインストールします。詳細については、「CronHPA を使用したコンテナの定時水平スケーリング」をご参照ください。
Qwen-7B-Chat-Int8 モデルデータを準備します。詳細については、「vLLM 推論サービスのデプロイ」をご参照ください。
次のコマンドを実行して、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次のコマンドを実行して、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 応答を返したことを示しています。
次のコマンドを実行して、定時オートスケーリングを設定します。
予想される出力:
この出力は、
qwen-cronhpaCRD に対して定時オートスケーリングプランが設定されたことを示しています。スケジュールに基づき、qwen-cronhpa-predictorデプロイメントの Pod 数は、プリセットされたスケーリング要件を満たすために毎日特定の時間に自動的に調整されます。
関連ドキュメント
ACK の弾性スケーリングに関する詳細については、「Auto Scaling」をご参照ください。