在某些场景下,您可能需要将多个模型推理任务共享在同一块GPU以提高GPU的利用率。本文以模型类型为Qwen1.5-0.5B-Chat,GPU类型为V100卡为例,演示如何使用KServe部署GPU共享的模型推理服务。
前提条件
已创建托管GPU集群或专有GPU集群,且集群版本需为1.22及以上,并指定CUDA版本为12.0及以上。具体操作,请参见创建GPU集群或创建专有GPU集群。
建议GPU节点使用525版本驱动,您可以通过为GPU节点池添加标签
ack.aliyun.com/nvidia-driver-version:525.105.17
指定驱动版本为525.105.17。具体操作,请参见通过指定版本号自定义节点GPU驱动版本。已安装共享GPU组件,并开启GPU共享调度能力。具体操作,请参见安装共享GPU调度组件。
已安装Arena客户端,且版本不低于0.9.15。具体操作,请参见配置Arena客户端。
已安装cert-manager和ack-kserve️组件,且ack-kserve️组件的部署模式为Raw Deployment。具体操作,请参见安装ack-kserve️。
步骤一:准备模型数据
您可以使用OSS或NAS准备模型数据,具体操作,请参见使用OSS静态存储卷、使用NAS静态存储卷。本文以OSS为例说明如何准备模型数据。
下载模型。本文以Qwen1.5-0.5B-Chat模型为例。
执行以下命令,安装Git。
sudo yum install git
执行以下命令,安装Git LFS(Large File Support)插件。
sudo yum install git-lfs
执行以下命令,将ModelScope上的Qwen1.5-0.5B-Chat仓库克隆到本地。
GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/qwen/Qwen1.5-0.5B-Chat.git
执行以下命令,进入Qwen1.5-0.5B-Chat仓库目录。
cd Qwen1.5-0.5B-Chat
执行以下命令,在Qwen1.5-0.5B-Chat目录下,下载LFS管理的大文件。
git lfs pull
将下载的Qwen1.5-0.5B-Chat文件上传至OSS。
为目标集群配置名为llm-model的存储卷PV和存储声明PVC。具体操作,请参见使用OSS静态存储卷。
以下为示例PV的基本配置信息:
配置项
说明
存储卷类型
OSS
名称
llm-model
访问证书
配置用于访问OSS的AccessKey ID和AccessKey Secret。
Bucket ID
选择上一步所创建的OSS Bucket。
OSS Path
选择模型所在的路径,如/Qwen1.5-0.5B-Chat。
以下为示例PVC的基本配置信息:
配置项
说明
存储声明类型
OSS
名称
llm-model
分配模式
选择已有存储卷。
已有存储卷
单击选择已有存储卷链接,选择已创建的存储卷PV。
步骤二:部署推理服务
执行以下命令,检查集群中可用的GPU资源。
arena top node
确保集群中有可用于运行推理服务的GPU节点。
执行以下命令,启动两个Qwen推理服务,每个推理服务需使用6 GB显存。
启动第一个Qwen推理服务。
arena serve kserve \ --name=qwen1 \ --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \ --gpumemory=6 \ --cpu=3 \ --memory=8Gi \ --data="llm-model:/mnt/models/Qwen1.5-0.5B-Chat" \ "python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen1.5-0.5B-Chat --dtype=half --max-model-len=4096"
预期输出:
inferenceservice.serving.kserve.io/qwen1 created INFO[0003] The Job qwen1 has been submitted successfully INFO[0003] You can run `arena serve get qwen1 --type kserve -n default` to check the job status
输出结果表明已经成功部署推理服务。
启动第二个Qwen推理服务。
arena serve kserve \ --name=qwen2 \ --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \ --gpumemory=6 \ --cpu=3 \ --memory=8Gi \ --data="llm-model:/mnt/models/Qwen1.5-0.5B-Chat" \ "python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen1.5-0.5B-Chat --dtype=half --max-model-len=4096"
预期输出:
inferenceservice.serving.kserve.io/qwen2 created INFO[0001] The Job qwen2 has been submitted successfully INFO[0001] You can run `arena serve get qwen2 --type kserve -n default` to check the job status
输出结果表明已经成功部署推理服务。
参数说明如下所示:
参数
是否必选
说明
--name
是
提交的推理服务名称,全局唯一。
--image
是
推理服务的镜像地址。
--gpumemory
否
申请显存的大小。
为了优化资源分配,请确保各个推理服务申请的显存之和不超过GPU的总显存量。例如,若某GPU具备8 GB显存,首次部署的推理服务请求分配3 GB(
--gpumemory=3
),则剩余5 GB显存可用。接着,若有第二个推理服务同样考虑运行于该GPU上并申请4 GB显存(--gpumemory=4
),由于两者总申请量(3 GB + 4 GB = 7 GB)未超出GPU的8 GB显存限制,因此这两个服务能够共存于同一张GPU卡上,实现了显存的有效共享。--cpu
否
推理服务需要使用的CPU数。
--memory
否
推理服务需要使用的内存数。
--data
否
推理服务的模型地址,本文指定模型的存储卷为
llm-model
,挂载到容器的/mnt/models/
目录下。
步骤三:验证推理服务
执行以下命令,查看两个Qwen推理服务部署情况。
kubectl get pod -owide |grep qwen
预期输出:
qwen1-predictor-856568bdcf-5pfdq 1/1 Running 0 7m10s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none> qwen2-predictor-6b477b587d-dpdnj 1/1 Running 0 4m3s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none>
预期输出表明,qwen1和qwen2被成功部署到同一个GPU节点
cn-beijing.172.16.XX.XX
上。分别执行以下两条命令,进入两个推理服务所在的Pod中,查看Pod所分配的GPU显存大小。
kubectl exec -it qwen1-predictor-856568bdcf-5pfdq -- nvidia-smi # 进入第一个推理服务所在的pod。 kubectl exec -it qwen2-predictor-6b477b587d-dpdnj -- nvidia-smi # 进入第二个推理服务所在的pod。
预期输出:
输出结果表明,两个Pod内部显存上限均为6 GB,由于节点的GPU显存为16 GB,可以判断出节点GPU显存已被成功分配给了这两个推理服务所在的Pod。
执行以下命令,使用获取到的Nginx Ingress网关地址访问推理服务。
# 获取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 qwen1 -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-bbca59499ab244e1aabfe2c354bf6ad5","object":"chat.completion","created":1719303373,"model":"qwen","choices":[{"index":0,"message":{"role":"assistant","content":"好的,请问您需要测试什么内容呢?"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":21,"total_tokens":31,"completion_tokens":10}}
输出结果表明模型可以根据给定的输入(在这个例子中是一条测试消息)生成相应的回复。
(可选)步骤四:清理环境
如果不再使用已创建的资源,请及时清理。
执行以下命令,删除已部署的模型推理服务。
arena serve delete qwen1 arena serve delete qwen2
执行以下命令,删除已创建的PV和PVC。
kubectl delete pvc llm-model kubectl delete pv llm-model