部署GPU共享推理服务

在某些场景下,您可能需要将多个模型推理任务共享在同一块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为例说明如何准备模型数据。

  1. 下载模型。本文以Qwen1.5-0.5B-Chat模型为例。

    1. 执行以下命令,安装Git。

      sudo yum install git
    2. 执行以下命令,安装Git LFS(Large File Support)插件。

      sudo yum install git-lfs
    3. 执行以下命令,将ModelScope上的Qwen1.5-0.5B-Chat仓库克隆到本地。

      GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/qwen/Qwen1.5-0.5B-Chat.git
    4. 执行以下命令,进入Qwen1.5-0.5B-Chat仓库目录。

      cd Qwen1.5-0.5B-Chat
    5. 执行以下命令,在Qwen1.5-0.5B-Chat目录下,下载LFS管理的大文件。

      git lfs pull
  2. 将下载的Qwen1.5-0.5B-Chat文件上传至OSS。

    1. 登录OSS控制台,查看并记录已创建的Bucket名称。

      如何创建Bucket,请参见创建存储空间

    2. 安装和配置ossutil。具体操作,请参见安装ossutil

    3. 执行以下命令,在OSS创建名为Qwen1.5-0.5B-Chat的目录。

      ossutil mkdir oss://<Your-Bucket-Name>/Qwen1.5-0.5B-Chat
    4. 执行以下命令,上传模型文件至OSS。

      ossutil cp -r ./Qwen1.5-0.5B-Chat oss://<Your-Bucket-Name>/Qwen1.5-0.5B-Chat
  3. 为目标集群配置名为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。

步骤二:部署推理服务

  1. 执行以下命令,检查集群中可用的GPU资源。

    arena top node

    确保集群中有可用于运行推理服务的GPU节点。

  2. 执行以下命令,启动两个Qwen推理服务,每个推理服务需使用6 GB显存。

    1. 启动第一个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 

      输出结果表明已经成功部署推理服务。

    2. 启动第二个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/目录下。

步骤三:验证推理服务

  1. 执行以下命令,查看两个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 上。

  2. 分别执行以下两条命令,进入两个推理服务所在的Pod中,查看Pod所分配的GPU显存大小。

    kubectl exec -it qwen1-predictor-856568bdcf-5pfdq  -- nvidia-smi # 进入第一个推理服务所在的pod。
    kubectl exec -it qwen2-predictor-6b477b587d-dpdnj  -- nvidia-smi # 进入第二个推理服务所在的pod。

    预期输出:

    • 第一个推理服务所分配的显存大小

      Fri Jun 28 06:20:43 2024       
      +---------------------------------------------------------------------------------------+
      | NVIDIA-SMI 535.161.07             Driver Version: 535.161.07   CUDA Version: 12.2     |
      |-----------------------------------------+----------------------+----------------------+
      | GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
      | Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
      |                                         |                      |               MIG M. |
      |=========================================+======================+======================|
      |   0  Tesla V100-SXM2-16GB           On  | 00000000:00:07.0 Off |                    0 |
      | N/A   39C    P0              53W / 300W |   5382MiB /  6144MiB |      0%      Default |
      |                                         |                      |                  N/A |
      +-----------------------------------------+----------------------+----------------------+
                                                                                               
      +---------------------------------------------------------------------------------------+
      | Processes:                                                                            |
      |  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
      |        ID   ID                                                             Usage      |
      |=======================================================================================|
      +---------------------------------------------------------------------------------------+
    • 第二个推理服务所分配的显存大小

      Fri Jun 28 06:40:17 2024       
      +---------------------------------------------------------------------------------------+
      | NVIDIA-SMI 535.161.07             Driver Version: 535.161.07   CUDA Version: 12.2     |
      |-----------------------------------------+----------------------+----------------------+
      | GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
      | Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
      |                                         |                      |               MIG M. |
      |=========================================+======================+======================|
      |   0  Tesla V100-SXM2-16GB           On  | 00000000:00:07.0 Off |                    0 |
      | N/A   39C    P0              53W / 300W |   5382MiB /  6144MiB |      0%      Default |
      |                                         |                      |                  N/A |
      +-----------------------------------------+----------------------+----------------------+
                                                                                               
      +---------------------------------------------------------------------------------------+
      | Processes:                                                                            |
      |  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
      |        ID   ID                                                             Usage      |
      |=======================================================================================|
      +---------------------------------------------------------------------------------------+

    输出结果表明,两个Pod内部显存上限均为6 GB,由于节点的GPU显存为16 GB,可以判断出节点GPU显存已被成功分配给了这两个推理服务所在的Pod。

  3. 执行以下命令,使用获取到的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