You need to enable JavaScript to run this app.
导航
基于 VKE 快速部署 DeepSeek-R1 模型(SGLang)
最近更新时间:2025.02.11 11:56:28首次发布时间:2025.02.10 21:16:21

本文介绍如何在火山引擎容器服务(VKE)集群中,快速部署 DeepSeek-R1 模型(SGLang)推理服务,满足您的业务需求。

背景信息

DeepSeek 是由中国 AI 初创公司深度求索(DeepSeek)发布的大语言模型。其主要的开源模型包含:

  • DeepSeek-V3:通用大语言大模型(MoE 结构,671B 参数,激活参数 37B),在 14.8T token 上进行了预训练,可以提供信息检索、数据分析、自然语言处理等服务,能够适应多种应用场景,如客户服务、教育辅导、内容创作等。
  • DeepSeek-R1:基于 DeepSeek-V3-Base 训练生成的推理模型,擅长数学、代码和自然语言推理等复杂任务,能够在复杂环境中稳定运行并完成指定任务,适用于工业自动化、家庭服务机器人等领域。

本文将介绍如何在火山引擎容器服务的集群中,部署满血版 DeepSeek-R1 模型推理服务,实现 Kubernetes 集群中的 DeepSeek-R1 模型分布式推理。

部署前准备

模型推送

为了方便用户使用 DeepSeek 模型,火山引擎提前在对象存储(TOS)服务中预置了部分模型。您可以直接通过 TOS 提供的工具,将预置模型放到您自己火山引擎业务相关的 TOS 存储桶(Bucket)中,作为之后推理服务的基础模型。

TOS 中的预置模型如下表所示。

模型名称TOS路径模型说明
DeepSeek-R1tos://ai-public-models-cn-beijing/models/DeepSeek-R1/DeepSeek R1 模型
DeepSeek-V3tos://ai-public-models-cn-beijing/models/DeepSeek-V3/DeepSeek V3 模型

具体操作步骤如下:

  1. 创建 TOS Bucket,需要注意 区域 选择 华北 2(北京)。详细的操作步骤和参数说明,请参见 创建存储桶
    alt
  2. 下载 TOS 官方提供的 tosutil 工具到本地,后续模型的复制需要依赖该工具。详情请参见 tosutil 下载与安装

    说明

    tosutil 工具同时支持 Windows、Linux 及 macOS 系统,您可以根据实际环境下载和安装合适的版本。

  3. 通过本地curl命令,在本地配置 tosutil 工具信息。
    tosutil config -e=tos-cn-beijing.volces.com -i=${AK} -k=${SK} -re=cn-beijing
    
    其中,将${AK}${SK}替换为您火山引擎账号的 AccessKey ID(AK)和 Secret Access Key(SK)。AK/SK 获取方法,请参见 API访问密钥管理
  4. 通过本地curl命令,将预置模型复制到您自己的 TOS Bucket
    tosutil cp -r -j 6 -p 6 ${SOURCE_MODEL_TOS_PATH} tos://${TOS_BUCKET}
    
    其中:
    • ${SOURCE_MODEL_TOS_PATH}:预置模型的 TOS 路径,以 DeepSeek-R1 模型为例,${SOURCE_MODEL_TOS_PATH}即为tos://ai-public-models-cn-beijing/models/DeepSeek-R1/
    • ${TOS_BUCKET}:您在步骤 1 中创建的 TOS Bucket 名称。

创建高性能计算集群

高性能计算集群,用于实现高性能计算 GPU 实例(计算节点)的逻辑隔离,同一集群内实例间 RDMA 网络互联互通。详情请参见 创建高性能计算集群

说明

高性能计算集群的 地域 选择 华北 2(北京)可用区 需要与 VKE 节点的可用区一致即可。

创建 VKE 集群

在容器服务中创建集群,需要注意以下列举的参数配置。其余参数说明和详细的操作步骤,请参见 创建集群

说明

单击 创建集群 前,先在顶部导航栏选择 华北 2(北京) 地域。

配置项说明
集群配置
容器网络模型选择 VPC-CNI
节点池配置
托管节点池开启 托管节点池。
可用区高性能计算计算集群 所在的可用区相同。

计算规格

由于 Deepseek 模型参数较大,因此需要选择有较大显存的 GPU 实例 ,如 高性能计算 GPU 型 ecs.hpcpni3ln.45xlarge

说明

ecs.hpcpni3ln.45xlarge 规格实例在 GPU 云服务器侧正在邀测中。如需体验,请联系您的售前经理或解决方案经理。

高性能计算机群选择之前创建的高性能计算集群。
节点数量2 个。
数据盘选择 1 TiB 极速型 SSD 盘。

节点标签 (Labels)

设置节点标签来配置 RDMA 使用模式。
标签键设置为:vke.node.rdma.mode,标签值设置为:exclusive(独占)。

Kubelet 自定义参数

通过 Kubelet 自定义参数配置 RDMA 设备的 NUMA 亲和策略。
参数选择:topology-manager-policy,参数值选择:best-effort

组件配置

平台功能组件

安装如下组件:

  • nvidia-device-plugin:GPU 使用依赖,使用 GPU 机器必备。
  • rdma-device-plugin:RDMA 设备插件,支持 RDMA 网卡设备的管理。
  • csi-tos:TOS 挂载依赖。
  • load-balancer-controller:自动配置负载均衡,对外暴露服务。

创建模型存储卷

在 VKE 集群中创建对象存储静态存储卷,实现基于 TOS 的 VKE 集群网络存储能力。详情请参见 使用对象存储静态存储卷

  1. 在已创建的 VKE 集群中创建存储卷(PV),需要注意以下列举的参数配置。
    alt

    配置项说明
    存储类型选择 对象存储
    存储桶选择之前已创建的 TOS Bucket。
    子目录设置为DeepSeek-R1/
  2. 创建存储卷声明(PVC),关联上一步创建的 PV。
    alt

部署模型

完成部署模型前的准备工作后,开启正式部署 DeepSeek-R1 模型(SGLang)的步骤。

  1. 通过 kubectl 连接已创建的 VKE 集群。详情请参见 连接集群
    您也可以直接通过 容器服务控制台,在集群的 工作负载 页面,选择任意一个类型的工作负载,单击 使用 YAML创建,以白屏化方式创建 YAML 文件。详情请参见 工作负载
    alt
  2. 创建 DeepSeek-R1 模型应用。示例 YAML 文件sglang.yaml如下所示。
    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
    #RDMA 网卡的数量需要与 GPU 卡的数量一致
    #如需创建多张网卡设备,需要在 k8s.volcengine.com/pod-networks 中配置重复 N(网卡数)次
        k8s.volcengine.com/pod-networks: |
          [
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            }
          ]
      name: sglang-head
      namespace: default
      labels:
        app.kubernetes.io/name: sglang-head 
    spec:
      initContainers:
        - name: resolve-head-ip
          image: ai-containers-cn-beijing.cr.volces.com/deeplearning/busybox
          imagePullPolicy: IfNotPresent
          command: 
          - /bin/sh
          - -c
          - 'echo HEAD_IP=$(nslookup sglang-head-svc | grep -oE "Address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)" | cut -d" " -f2) >> /env/head.env'
          volumeMounts:
          - mountPath: /env
            name: env
      containers:
        - name: sglang-head-main
          image: ai-containers-cn-beijing.cr.volces.com/deeplearning/sglang:v0.4.2.post2-cu124
          imagePullPolicy: IfNotPresent
          workingDir: /sgl-workspace
          command:
          - bash
          - -c
          - 'source /env/head.env && cd /sgl-workspace && GLOO_SOCKET_IFNAME=eth0 NCCL_SOCKET_IFNAME=eth0 NCCL_IB_DISABLE=0 NCCL_IB_HCA=mlx5_ python3 -m sglang.launch_server --model-path /models/deepseek --tp 16 --dist-init-addr $HEAD_IP:20000 --nnodes 2 --node-rank 0 --trust-remote-code --context-length 131072 --mem-fraction-static 0.7 --host 0.0.0.0 --port 8080'
          ports:
          - containerPort: 8080
            name: http
            protocol: TCP
          - containerPort: 20000
            name: distributed
            protocol: TCP
          resources:
            limits:
              nvidia.com/gpu: "8"
              vke.volcengine.com/rdma: "8"
            requests:
              nvidia.com/gpu: "8"
              vke.volcengine.com/rdma: "8"
          securityContext:
            capabilities:
              add:
              - IPC_LOCK
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
          - mountPath: /models/deepseek
            name: models
          - mountPath: /dev/shm
            name: shared-mem
          - mountPath: /env
            name: env
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      volumes:
      - name: models
    # persistentVolumeClaim.claimName 需要和之前创建模型 PV/PVC 步骤中的 PVC 名称对应 
        persistentVolumeClaim:
          claimName: deepseek-pvc
      - emptyDir:
          medium: Memory
        name: shared-mem
      - emptyDir:
        name: env
      # nodeSelector:
      #   cluster.vke.volcengine.com/machinepool-name: pcuho0r2clh*****   # 若集群有其他异构的 GPU 节点时,您可以去掉当前注释和 nodeSelector 注释,自主设置节点亲和性,确保模型调度到指定的高性能 GPU 计算型节点
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sglang-head-svc 
    spec:
      selector:
        app.kubernetes.io/name: sglang-head 
      ports:
        - protocol: TCP
          port: 20000
          targetPort: distributed
      type: ClusterIP
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sglang-api-svc 
    spec:
      selector:
        app.kubernetes.io/name: sglang-head 
      ports:
        - protocol: TCP
          port: 8080
          targetPort: http
      type: LoadBalancer # 对外暴露服务时,此处需设置为 LoadBalancer 类型
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
    #RDMA 网卡的数量需要与 GPU 卡的数量一致
    #如需创建多张网卡设备,需要在 k8s.volcengine.com/pod-networks 中配置重复 N(网卡数)次
        k8s.volcengine.com/pod-networks: |
          [
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            },
            {
              "cniConf":{
                  "name":"rdma"
              }
            }
          ]
      name: sglang-worker0
      namespace: default
    spec:
      initContainers:
        - name: resolve-head-ip
          image: ai-containers-cn-beijing.cr.volces.com/deeplearning/busybox
          imagePullPolicy: IfNotPresent
          command: 
          - /bin/sh
          - -c
          - 'echo HEAD_IP=$(nslookup sglang-head-svc | grep -oE "Address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)" | cut -d" " -f2) >> /env/head.env'
          volumeMounts:
          - mountPath: /env
            name: env
      containers:
        - name: sglang-worker0-main
          image: ai-containers-cn-beijing.cr.volces.com/deeplearning/sglang:v0.4.2.post2-cu124
          imagePullPolicy: IfNotPresent
          workingDir: /sgl-workspace
          command:
          - bash
          - -c
          - 'source /env/head.env && cd /sgl-workspace && GLOO_SOCKET_IFNAME=eth0 NCCL_SOCKET_IFNAME=eth0 NCCL_IB_DISABLE=0 NCCL_IB_HCA=mlx5_ python3 -m sglang.launch_server --model-path /models/deepseek --tp 16 --dist-init-addr $HEAD_IP:20000 --nnodes 2 --node-rank 1 --trust-remote-code --context-length 131072 --host 0.0.0.0 --port 8080'
          ports:
          - containerPort: 8080
            name: http
            protocol: TCP
          - containerPort: 20000
            name: distributed
            protocol: TCP
          resources:
            limits:
              nvidia.com/gpu: "8"
              vke.volcengine.com/rdma: "8"
            requests:
              nvidia.com/gpu: "8"
              vke.volcengine.com/rdma: "8"
          securityContext:
            capabilities:
              add:
              - IPC_LOCK
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
          - mountPath: /models/deepseek
            name: models
          - mountPath: /dev/shm
            name: shared-mem
          - mountPath: /env
            name: env
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      volumes:
      - name: models
    # persistentVolumeClaim.claimName 需要和之前创建模型 PV/PVC 步骤中的 PVC 名称对应
        persistentVolumeClaim:
          claimName: deepseekr1
      - emptyDir:
          medium: Memory
        name: shared-mem
      - emptyDir:
        name: env
      # nodeSelector:
      #   cluster.vke.volcengine.com/machinepool-name: pcuho0r2clh***** #  若集群有其他异构的 GPU 节点时,您可以去掉当前注释和 nodeSelector 注释,自主设置节点亲和性,确保模型调度到指定的高性能 GPU 计算型节点 
    
  3. 执行如下命令创建 YAML。

    说明

    通过控制台白屏化方式创建 YAML 文件时,不需要进行该步骤。

    kubectl apply -f sglang.yaml
    

模型验证

上述 部署模型 步骤中创建的 Service(名称为sglang-api-svc)提供 HTTP API 端点,默认使用 8080 端口。您可以按照 OpenAI 兼容 API 方式调用模型。调用示例如下所示:

curl localhost:8080/v1/chat/completions     -H "Content-Type: application/json"     -d '{
        "model": "/models/deepseek",
        "messages": [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "Who won the world series in 2020?"}
        ]
    }'