首页 弹性容器实例 操作指南 通过ACK使用ECI 数据缓存 DataCache实践教程 部署DeepSeek-R1系列模型并实现弹性扩缩容

部署DeepSeek-R1系列模型并实现弹性扩缩容

更新时间: 2025-03-13 14:01:29

本文以部署DeepSeek-R1-Distill-Qwen-7B模型为例,演示如何使用DataCache快速部署DeepSeek-R1系列模型,同时通过配置HPA实现基于自定义指标的弹性扩缩容。

为什么使用ECI部署DeepSeek

  • ECI具有免运维、灵活部署、高弹性、低成本等优势。更多信息,请参见产品优势

  • ECI通过数据缓存镜像缓存功能,可以节约镜像拉取和模型下载的时间,降低网络资源消耗,提升系统效率。

    说明

    在容器化的大模型推理服务部署中,主要有几个阶段:容器创建与启动、镜像拉取、模型文件下载和推理服务加载模型并启动。由于大模型推理服务的镜像和模型都较大(例如vLLM镜像约16.5 GB,DeepSeek-R1-Distill-Qwen-7B模型约14 GB),需要花费大量时间与网络流量拉取。ECI通过镜像缓存和数据缓存功能,可以节约镜像拉取和模型下载的时间。

前提条件

  • 集群中已部署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。

  1. 访问HuggingFace,获取模型ID。

    本示例使用DeepSeek-R1-Distill-Qwen-7B模型的main版本。在HuggingFace找到目标模型后,在模型详情页面顶部可以复制模型ID。

  2. 编写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带宽
  3. 查询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

  1. 登录容器服务管理控制台,在集群列表页面,单击目标集群名称。

  2. 在集群管理页的左侧导航栏,选择应用 > Helm

  3. 在Helm列表的操作列,单击ack-alibaba-cloud-metrics-adapter对应的更新

    请根据需要在custom字段下添加rules

    展开查看详细rules信息

    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_GPU_UTIL{} # GPU使用率
    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_SM_UTIL{} # 容器GPU使用率。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_FB_USED{} # 显存使用量。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{} # 容器显存使用量。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>) / sum(DCGM_CUSTOM_CONTAINER_MEM_ALLOCATED{}) by (<<.GroupBy>>)
      name:
        as: ${1}_GPU_MEM_USED_RATIO
        matches: ^(.*)_MEM_USED
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{NamespaceName!="",PodName!=""}  # 容器GPU显存使用率。

步骤三:部署弹性扩缩容的Deepseek模型推理服务

  1. 编写应用的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
  2. 确认应用部署状态。

    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

步骤四:测试效果

  1. 获取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)
  2. 测试模型推理服务效果。

    向模型推理服务发送一条模型推理请求。示例如下:

    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>中的内容表示的是模型在生成最终答案之前进行的内部思考过程或中间推理步骤。这些标记并不是最终输出的一部分,而是模型在生成答案时的一种自我提示或逻辑推理的记录。

    提取最终答案如下:

    容器是一种隔离的运行环境,允许应用程序独立运行,提供资源的轻量化和高效管理,支持云原生和微服务架构。
  3. 测试弹性扩缩容效果。

    1. 查看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
    2. 查看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
    3. 使用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
    4. 查看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
    5. 查看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
上一篇: 部署DeepSeek-R1系列模型 下一篇: 部署Stable Diffusion应用
阿里云首页 弹性容器实例 相关技术圈