在部署與管理KServe模型服務過程中,需應對模型推理服務面臨的高度動態負載波動。KServe通過整合Kubernetes原生的HPA(Horizontal Pod Autoscaler)技術及擴縮容控制器,實現了根據CPU利用率、記憶體佔用情況、GPU利用率以及自訂效能指標,自動靈活地調整模型服務Pod的規模,以確保服務效能與穩定性。本文以Qwen-7B-Chat-Int8模型、GPU類型為V100卡為例,介紹如何基於KServe為服務配置彈性擴縮容。
前提條件
已安裝Arena用戶端,且版本不低於0.9.15。具體操作,請參見配置Arena用戶端。
已安裝ack-kserve。具體操作,請參見安裝ack-kserve️。
基於CPU或Memory配置自動擴縮容策略
Raw Deployment模式下的自動擴縮容依賴Kubernetes的HPA(Horizontal Pod Autoscaler)機制,這是最基礎的自動擴縮容方式,HPA根據Pod的CPU或Memory的利用率動態調整ReplicaSet中的Pod副本數量。
以下介紹如何基於CPU利用率配置自動擴縮容。HPA機制可參考社區文檔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內容寫入iris-input.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的Inference Service的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]}%輸出結果表明請求導致了兩次推理的發生,且兩次推理的響應一致。
執行以下命令,發起壓測。
說明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利用率配置自訂指標的彈性擴縮容策略
自訂指標的擴縮容依賴ACK提供的ack-alibaba-cloud-metrics-adapter組件與Kubernetes HPA機制實現。詳細資料,請參見基於阿里雲Prometheus指標的容器水平伸縮。
以下樣本示範如何基於Pod的GPU利用率配置自訂指標的擴縮容。
準備Qwen-7B-Chat-Int8模型資料。具體操作,請參見部署vLLM推理服務。
配置自訂GPU Metrics指標。具體操作,請參見基於GPU指標實現Auto Scaling。
執行以下命令,部署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的Hostname。 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": "測試一下"}], "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":"好的,請問您有什麼需要測試的?<|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": "測試一下"}], "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的Hostname。 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 -X POST \ -d '{"model": "qwen", "messages": [{"role": "user", "content": "你好"}], "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":"好的,請問您有什麼需要測試的?<|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的Deployment中的Pod數量,以滿足預設的擴縮容需求。
相關文檔
如需瞭解ACK彈性擴縮容的詳細資料,請參見Auto Scaling概述。