部署DeepSeek-R1系列模型并实现弹性扩缩容
本文以部署DeepSeek-R1-Distill-Qwen-7B模型为例,演示如何使用DataCache快速部署DeepSeek-R1系列模型,同时通过配置HPA实现基于自定义指标的弹性扩缩容。
为什么使用ECI部署DeepSeek
前提条件
集群中已部署DataCache CRD。
集群所属VPC已绑定公网NAT网关,并配置SNAT条目允许该VPC或下属交换机的资源可以访问公网。
说明如果VPC没有绑定公网NAT网关,您需要在创建DataCache和部署应用时绑定EIP,以便可以拉取公网数据。
集群中已部署阿里云Prometheus监控组件。具体操作,请参见使用阿里云Prometheus监控。
集群中已部署ack-alibaba-cloud-metrics-adapter组件。
您可以登录容器服务管理控制台,在 页面部署ack-alibaba-cloud-metrics-adapter组件。
集群中已部署KServe。
KServe是一个基于Kubernetes的机器学习模型服务框架,支持以Kubernetes CRD的形式将单个或多个经过训练的模型部署到模型服务运行时。更多信息,请参见安装ack-kserve️。
准备运行环境
不同的DeepSeek模型对于运行环境的要求不同,本文以DeepSeek-R1-Distill-Qwen-7B模型为例。
规格推荐
需使用的GPU规格要求如下。ECI支持的GPU规格,请参见规格说明。
CPU:无严格限制
内存:>16 GiB
GPU:≥1
显存:≥20 GB,例如A10(显存过低可能会出现OOM)
软件环境
大模型部署依赖的库和配置较多,vLLM是目前一个主流的大模型推理引擎,本文使用vLLM进行推理服务的部署。ECI已经制作好了一个公共容器镜像,您可以直接使用该镜像或者将其作为基础镜像进行二次开发,镜像地址为
registry.cn-hangzhou.aliyuncs.com/eci_open/vllm-openai:v0.7.2
,镜像大小约为16.5 GB。
步骤一:创建DataCache
首次使用时,提前创建DataCache,可以免去在Pod中拉取模型数据的等待时间,加速部署DeepSeek。
访问HuggingFace,获取模型ID。
本示例使用DeepSeek-R1-Distill-Qwen-7B模型的main版本。在HuggingFace找到目标模型后,在模型详情页面顶部可以复制模型ID。
编写DataCache的YAML配置文件,然后使用该YAML文件创建DataCache拉取DeepSeek-R1-Distill-Qwen-7B模型。
kubectl create -f datacache-test.yaml
datacache-test.yaml的内容示例如下:
apiVersion: eci.aliyun.com/v1alpha1 kind: DataCache metadata: name: deepseek-r1-distill-qwen-7b spec: bucket: test path: /model/deepseek-r1-distill-qwen-7b dataSource: type: URL options: repoSource: HuggingFace/Model # 指定数据源为HuggingFace的模型 repoId: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B # 指定模型ID revision: main # 指定模型版本 netConfig: securityGroupId: sg-bp1*********** vSwitchId: vsw-bp1uo************ # 指定已配置SNAT的交换机 # 如果交换机没有配置SNAT接入公网,需要自动创建并绑定EIP eipCreateParam: bandwidth: 5 # EIP带宽
查询DataCache状态。
kubectl get edc
当数据下载完成,DataCache的状态为Available时,表示可以使用DataCache。阿里云为DeepSeek-R1系列模型提供了热加载能力,能实现DataCache秒级制作完成。
NAME AGE DATACACHEID STATUS PROGRESS BUCKET PATH deepseek-r1-distill-qwen-7b 40s edc-uf6btsb4q5j4b9ue**** Available 100% test /model/deepseek-r1-distill-qwen-7b
步骤二:配置GPU指标Adapter Rules
自定义指标的扩缩容依赖ACK提供的ack-alibaba-cloud-metrics-adapter组件与Kubernetes HPA机制实现。GPU HPA目前支持的指标如下,更多信息,请参见基于GPU指标实现弹性伸缩。
指标名称 | 说明 | 单位 |
DCGM_FI_DEV_GPU_UTIL | GPU卡的利用率。该指标仅在独占GPU调度时有效。 | % |
DCGM_FI_DEV_FB_USED | GPU卡显存使用量。该指标仅在独占GPU调度时有效。 | MiB |
DCGM_CUSTOM_PROCESS_SM_UTIL | 容器的GPU利用率。 | % |
DCGM_CUSTOM_PROCESS_MEM_USED | 容器的GPU显存使用量。 | MiB |
登录容器服务管理控制台,在集群列表页面,单击目标集群名称。
在集群管理页的左侧导航栏,选择
。在Helm列表的操作列,单击ack-alibaba-cloud-metrics-adapter对应的更新。
请根据需要在
custom
字段下添加rules
。
步骤三:部署弹性扩缩容的Deepseek模型推理服务
编写应用的YAML配置文件,然后使用该YAML文件部署DeepSeek推理应用。
kubectl create -f deepseek-r1-7b-kserve.yaml
deepseek-r1-7b-kserve.yaml的内容示例和相关说明如下:
使用GPU规格,并挂载了DeepSeek-R1-Distill-Qwen-7B模型。
InferenceService的predictor使用包含vLLM的镜像,容器启动后会运行
vllm serve /deepseek-r1-7b --tensor-parallel-size 1 --max-model-len 24384 --enforce-eager
启动OpenAI-Compatible Server。使用DCGM_CUSTOM_PROCESS_SM_UTIL(容器的GPU利用率)指标进行扩缩容,在平均利用率达到50%时,HPA会根据配置进行自动扩容,最多扩展到
maxReplicas
配置的数量。
apiVersion: serving.kserve.io/v1beta1 kind: InferenceService metadata: name: deepseek-r1-7b-kserve labels: alibabacloud.com/eci: "true" annotations: serving.kserve.io/autoscalerClass: external k8s.aliyun.com/eci-use-specs: ecs.gn7i-c16g1.4xlarge,ecs.gn7i-c32g1.8xlarge # 指定GPU实例规格,指定多规格可以降低库存不足的概率 k8s.aliyun.com/eci-extra-ephemeral-storage: "20Gi" # 启动依赖的框架较大,需要配置额外的临时存储空间(付费) k8s.aliyun.com/eci-data-cache-bucket: "test" # 指定DataCache Bucket # 对加载速度有更高要求的可以开启AutoPL云盘 k8s.aliyun.com/eci-data-cache-provisionedIops: "15000" # 设置ESSD AutoPL云盘预配置的读写IOPS k8s.aliyun.com/eci-data-cache-burstingEnabled: "true" # 设置ESSD AutoPL云盘开启Burst,加速应用启动 spec: predictor: containers: - name: vllm command: - /bin/sh args: - -c - vllm serve /deepseek-r1-7b --port 8080 --tensor-parallel-size 1 --max-model-len 24384 --enforce-eager image: registry-vpc.cn-hangzhou.aliyuncs.com/eci_open/vllm-openai:v0.7.2 resources: limits: cpu: "16" memory: "60Gi" nvidia.com/gpu: "1" requests: cpu: "16" memory: "60Gi" nvidia.com/gpu: "1" volumeMounts: - mountPath: /deepseek-r1-7b # 模型所在的路径 name: llm-model volumes: - name: llm-model hostPath: path: /model/deepseek-r1-distill-qwen-7b # 挂载数据存储的路径 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: deepseek-r1-7b-kserve-predictor namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: deepseek-r1-7b-kserve-predictor metrics: - pods: metric: name: DCGM_CUSTOM_PROCESS_SM_UTIL # 要监控的指标名称 target: type: Utilization # 定义目标值的类型,例如利用率或原始值 averageValue: '50' # 设定指标的目标平均值 type: Pods minReplicas: 1 # 指定保持运行的最小Pod数量 maxReplicas: 100 # 指定允许的最大Pod数量
预期返回:
inferenceservice.serving.kserve.io/deepseek-r1-7b-kserve created horizontalpodautoscaler.autoscaling/deepseek-r1-7b-kserve-predictor created
确认应用部署状态。
kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor
预期返回:
NAME READY STATUS RESTARTS AGE deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx 1/1 Running 0 116s
步骤四:测试效果
获取DeepSeek推理应用所对应负载均衡服务的IP地址和主机名,并设置为变量。
NGINX_INGRESS_IP=$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}') SERVICE_HOSTNAME=$(kubectl get inferenceservice deepseek-r1-7b-kserve -o jsonpath='{.status.url}' | cut -d "/" -f 3)
测试模型推理服务效果。
向模型推理服务发送一条模型推理请求。示例如下:
curl POST http://$NGINX_INGRESS_IP:80/v1/chat/completions \ -H "Host: $SERVICE_HOSTNAME" \ -H "Content-Type: application/json" \ -d '{ "model": "/deepseek-r1-7b", "messages": [ { "role": "user", "content": "用一句话简单介绍一下容器" } ], "temperature": 0.6, "max_tokens": 3000 }' \ --verbose
预期返回:
{"id":"chatcmpl-56e6ff393d999571ce6ead1b72f9302d","object":"chat.completion","created":1739340308,"model":"/deepseek-r1-7b","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"<think>\n嗯,我需要简单介绍一下容器。容器是什么?我记得在编程中,特别是使用Docker的时候,容器好像是一个隔离的环境,可以让应用独立运行。容器化让开发和部署更方便,对吧?所以,容器应该是一个轻量级的运行时,能够隔离应用程序和依赖,让开发和部署过程更高效。对吧?所以,用一句话来介绍容器的话,应该涵盖隔离、轻量、资源独立运行这些特点。可能还要提到容器化技术的应用场景,比如云原生、微服务架构等。嗯,现在把这些想法组织成一句话。\n</think>\n\n容器是一种隔离的运行环境,允许应用程序独立运行,提供资源的轻量化和高效管理,支持云原生和微服务架构。","tool_calls":[]},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"usage":{"prompt_tokens":8,"total_tokens":168,"completion_tokens":160,"prompt_tokens_details":null},"prompt_logprobs":null}
其中
<think></think>
中的内容表示的是模型在生成最终答案之前进行的内部思考过程或中间推理步骤。这些标记并不是最终输出的一部分,而是模型在生成答案时的一种自我提示或逻辑推理的记录。提取最终答案如下:
容器是一种隔离的运行环境,允许应用程序独立运行,提供资源的轻量化和高效管理,支持云原生和微服务架构。
测试弹性扩缩容效果。
查看Pod。
kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor
预期返回如下,当前有1个Pod。
NAME READY STATUS RESTARTS AGE deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx 1/1 Running 0 6m54s
查看HPA。
kubectl get hpa
预期返回:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE deepseek-r1-7b-kserve-predictor Deployment/deepseek-r1-7b-kserve-predictor 9/50 1 100 1 8m
使用Hey进行压测。
Hey压测工具请参见Hey。
hey -z 2m -c 20 -m POST -host $SERVICE_HOSTNAME -H "Content-Type: application/json" -d '{"model": "/deepseek-r1-7b", "messages": [{"role": "user", "content": "hello world!"}], "max_tokens": 512, "temperature": 0.7, "top_p": 0.9, "seed": 10}' http://$NGINX_INGRESS_IP:80/v1/chat/completions
查看Pod,确认扩容结果。
kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor
预期返回如下,可以看到已自动扩容。
NAME READY STATUS RESTARTS AGE deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx 1/1 Running 0 8m5s deepseek-r1-7b-kserve-predictor-6785df7b7f-6l2kj 1/1 Running 0 104s deepseek-r1-7b-kserve-predictor-6785df7b7f-3q5dz 1/1 Running 0 104s
查看HPA。
kubecl get hpa
预期返回:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE deepseek-r1-7b-kserve-predictor Deployment/deepseek-r1-7b-kserve-predictor 5/50 1 100 3 10m