全部產品
Search
文件中心

Elastic Container Instance:部署DeepSeek-R1系列模型並實現彈性擴縮容

更新時間:Feb 15, 2025

本文以部署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。具體操作,請參見部署DataCache CRD

  • 叢集所屬VPC已綁定公網NAT Gateway,並配置SNAT條目允許該VPC或下屬交換器的資源可以訪問公網。

    說明

    如果VPC沒有綁定公網NAT Gateway,您需要在建立DataCache和部署應用時綁定EIP,以便可以拉取公網資料。

  • 叢集中已部署阿里雲Prometheus監控組件。具體操作,請參見使用阿里雲Prometheus監控

  • 叢集中已部署ack-alibaba-cloud-metrics-adapter組件。

    您可以登入Container Service管理主控台,在市場 > 應用市場頁面部署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指標實現Auto Scaling

指標名稱

說明

單位

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. 登入Container Service管理主控台,在叢集列表頁面,單擊目的地組群名稱。

  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