本文将介绍如何在火山引擎容器服务的集群中,部署满血版 DeepSeek-V3/R1 模型推理服务,实现 Kubernetes 集群中的 DeepSeek-V3/R1 模型分布式推理。
说明
本文仅适用于普通 GPU 场景,mGPU 场景暂不支持。
DeepSeek 是由中国 AI 初创公司深度求索(DeepSeek)发布的大语言模型。其主要的开源模型包含:
为了方便您使用 DeepSeek 模型,火山引擎提前在对象存储(TOS)服务中预置了部分模型。您可以直接通过 TOS 提供的工具,将预置模型转存至您自己的 TOS 存储桶(Bucket)中,作为之后推理服务的基础模型。
TOS 中的预置模型如下表所示。
模型名称 | TOS 路径 | 模型说明 |
---|---|---|
DeepSeek-R1 | tos://ai-public-models-cn-beijing/models/DeepSeek-R1/ | DeepSeek R1 模型 |
DeepSeek-V3 | tos://ai-public-models-cn-beijing/models/DeepSeek-V3/ | DeepSeek V3 模型 |
您可以将火山引擎预置的 DeepSeek 模型转存至自建 TOS 桶中,作为后续模型推理服务的基础模型。操作步骤如下:
登录 对象存储控制台。
在左侧菜单栏中选择 桶列表,单击 创建桶,创建一个 TOS 桶。
配置存储桶信息。需要注意 区域 选择 华北 2(北京)。详细的操作步骤和参数说明,请参见 创建存储桶。
在本地环境中,下载 TOS 官方提供的 tosutil 工具到本地,后续模型的复制需要依赖该工具。详情请参见 tosutil 下载与安装。
说明
tosutil 工具同时支持 Windows、Linux 及 macOS 系统,您可以根据实际环境下载和安装合适的版本。
在本地环境执行以下命令,配置 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访问密钥管理。
在本地环境中执行以下命令,将预置模型复制到您的自建 TOS 桶中。
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}
:您在步骤 3 中创建的 TOS 存储桶名称。高性能计算集群,用于实现高性能计算 GPU 实例(计算节点)的逻辑隔离,同一集群内实例间 RDMA 网络互联互通。详情请参见 创建高性能计算集群。
说明
高性能计算集群的 地域 选择 华北 2(北京),可用区 需要与 VKE 节点的可用区一致即可。
在容器服务中创建集群,需要注意以下列举的参数配置。其余参数说明和详细的操作步骤,请参见 创建集群。
配置项 | 说明 |
---|---|
集群配置 | |
Kubernetes 版本 | 选择 v1.28 及以上版本。 |
容器网络模型 | 选择 VPC-CNI。 |
节点池配置 | |
托管节点池 | 开启 托管节点池。 |
可用区 | 与 高性能计算计算集群 所在的可用区相同。 |
计算规格 | 由于 Deepseek 模型参数较大,因此需要选择有较大显存的 GPU 实例 ,如 ecs.hpcpni3ln, ecs.ebmhpcpni3ln, ecs.ebmhpcpni3l(H20 8 卡) 等。 |
高性能计算机群 | 选择之前创建的高性能计算集群。 |
节点数量 | 2 个。 |
数据盘 | 选择 1 TiB 极速型 SSD 盘。 |
节点标签 (Labels) | 设置节点标签来配置 RDMA 使用模式。 |
Kubelet 自定义参数 | 通过 Kubelet 自定义参数配置 RDMA 设备的 NUMA 亲和策略。 |
组件配置 | |
平台功能组件 | 在集群中安装如下组件:
|
在 VKE 集群中创建对象存储静态存储卷,实现基于 TOS 的 VKE 集群网络存储能力。详情请参见 使用对象存储静态存储卷。
配置项 | 说明 |
---|---|
存储类型 | 选择 对象存储。 |
访问密钥 | 单击 创建秘钥,完成秘钥配置。其中 AccessKey ID 和 AccessKey Secret 为您火山引擎账号的 AK/SK。获取方法,请参见 API访问密钥管理。 |
存储桶 | 选择已创建的 TOS 桶。 |
子目录 | 设置为DeepSeek-R1/ 。 |
完成部署模型前的准备工作后,开启正式部署满血版 DeepSeek-R1 模型的步骤。
本文使用 LWS (LeaderWorkerSet) 来编排多节点的推理负载 (例如 DeepSeek V3/R1 需要跨两个节点部署),LWS 支持把一组 Pod 作为 Replicate 的对象。
说明
该操作方式仅支持 华北 2 地域。
kubectl apply --server-side -f manifest.yaml
说明
该安装方式需要访问公网镜像仓库,因此需要集群开启公网访问和 Proxy,或者集群位于海外地域。
VERSION=v0.5.1 kubectl apply --server-side -f https://github.com/kubernetes-sigs/lws/releases/download/$VERSION/manifests.yaml
sglang.yaml
如下所示。其中,LWS 控制器会创建一个 StatefulSet 管理所有 leader Pod,并为每一组负载 (此处固定 2 个 Pod 一组分布在两个节点上) 创建 StatefulSet。说明
下方 YAML 文件的 SGLang 命令中 NCCL_IB_GID_INDEX 参数值,需要在容器中执行show_gids
命令获取。如下图所示,选择使用 IPv4 地址且 VER 为 V2 的 INDEX,图中 INDEX 取值为 3。
apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: sglang spec: replicas: 1 # pod group 数量 startupPolicy: LeaderCreated rolloutStrategy: type: RollingUpdate rollingUpdateConfiguration: maxSurge: 0 maxUnavailable: 2 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader annotations: # 如需创建多张网卡设备,需要在 k8s.volcengine.com/pod-networks 中配置重复 N(网卡数)次。 k8s.volcengine.com/pod-networks: | [ { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } } ] spec: containers: - name: sglang-head image: ai-containers-cn-beijing.cr.volces.com/deeplearning/sglang:v0.4.3.post4-cu124 imagePullPolicy: IfNotPresent workingDir: /sgl-workspace command: - bash - -c - 'cd /sgl-workspace && GLOO_SOCKET_IFNAME=eth0 NCCL_SOCKET_IFNAME=eth0 NCCL_IB_DISABLE=0 NCCL_IB_GID_INDEX=3 NCCL_IB_HCA=mlx5_ python3 -m sglang.launch_server --model-path /models/deepseek --tp 16 --dist-init-addr $LWS_LEADER_ADDRESS:20000 --nnodes $LWS_GROUP_SIZE --node-rank 0 --trust-remote-code --context-length 131072 --mem-fraction-static 0.9 --enable-metrics --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: "4" # 此处设置的网卡数量,需要与 Annotation:k8s.volcengine.com/pod-networks 中 RDMA 配置的重复次数相同。 requests: nvidia.com/gpu: "8" vke.volcengine.com/rdma: "4" securityContext: capabilities: add: - IPC_LOCK terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /models/deepseek name: models - mountPath: /dev/shm name: shared-mem readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumes: - name: models persistentVolumeClaim: claimName: deepseekr1 - emptyDir: medium: Memory name: shared-mem dnsPolicy: ClusterFirst workerTemplate: metadata: annotations: # 如需创建多张网卡设备,需要在 k8s.volcengine.com/pod-networks 中配置重复 N(网卡数)次。 k8s.volcengine.com/pod-networks: | [ { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } }, { "cniConf":{ "name":"rdma" } } ] spec: containers: - name: sglang-worker image: ai-containers-cn-beijing.cr.volces.com/deeplearning/sglang:v0.4.3.post4-cu124 imagePullPolicy: IfNotPresent workingDir: /sgl-workspace command: - bash - -c - 'cd /sgl-workspace && GLOO_SOCKET_IFNAME=eth0 NCCL_SOCKET_IFNAME=eth0 NCCL_IB_DISABLE=0 NCCL_IB_GID_INDEX=3 NCCL_IB_HCA=mlx5_ python3 -m sglang.launch_server --model-path /models/deepseek --tp 16 --dist-init-addr $LWS_LEADER_ADDRESS:20000 --nnodes $LWS_GROUP_SIZE --node-rank $LWS_WORKER_INDEX --trust-remote-code --context-length 131072 --mem-fraction-static 0.9 --enable-metrics --host 0.0.0.0 --port 8080' env: - name: LWS_WORKER_INDEX valueFrom: fieldRef: fieldPath: metadata.labels['leaderworkerset.sigs.k8s.io/worker-index'] ports: - containerPort: 8080 name: http protocol: TCP - containerPort: 20000 name: distributed protocol: TCP resources: limits: nvidia.com/gpu: "8" vke.volcengine.com/rdma: "4" # 此处设置的网卡数量,需要与 Annotation:k8s.volcengine.com/pod-networks 中 RDMA 配置的重复次数相同。 requests: nvidia.com/gpu: "8" vke.volcengine.com/rdma: "4" securityContext: capabilities: add: - IPC_LOCK terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /models/deepseek name: models - mountPath: /dev/shm name: shared-mem dnsPolicy: ClusterFirst volumes: - name: models persistentVolumeClaim: claimName: deepseekr1 - emptyDir: medium: Memory name: shared-mem
kubectl apply -f sglang.yaml
为所有 leader 节点,即 HTTP 服务所在的节点,创建服务。示例文件service-demo.yaml
代码如下:
apiVersion: v1 kind: Service metadata: name: sglang-api-svc labels: app: sglang spec: selector: leaderworkerset.sigs.k8s.io/name: sglang role: leader ports: - protocol: TCP port: 8080 targetPort: http name: http type: ClusterIP
执行以下命令,创建服务。
kubectl apply -f service-demo.yaml
在集群管理页面的左侧导航栏中,选择 服务与路由 > 路由规则,单击 创建路由规则。使用 API 网关对外暴露集群内的模型服务。配置详情,请参见 通过控制台创建 APIG Ingress。
说明
使用 API 网关(APIG)暴露集群中的模型服务时,配置建议如下:
503
错误码,以及具体的错误详情。apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: sglang-api-svc-discover # 配置采集规则名称 namespace: default # 配置 ServiceMonitor 命名空间 labels: volcengine.vmp: "true" # 配置 ServiceMonitor 的标签,允许被 Prometheus-agent 发现 spec: endpoints: - port: http # 填写服务端口名称 namespaceSelector: matchNames: - default # 配置为服务所在的命名空间 selector: matchLabels: app: sglang # 配置服务的 Label 值,以定位和选择目标 Service
配置完成后,sglang 的应用指标就被采集到托管 Prometheus(VMP)了,您可以在托管 Prometheus 控制台中使用 Explore 查询指标,示例如下:
为了提高资源利用率,您可以在集群中配置工作负载弹性伸缩和节点资源弹性伸缩。
说明
支持使用流量指标、GPU 指标和大模型指标,基于 KEDA 组件对 AI 负载进行伸缩。其中:
DCGM_FI_PROF_SM_ACTIVE
作为工作负载弹性伸缩的指标,请确保该指标采集已被选择。apiVersion: v1 kind: Secret metadata: name: keda-prom-secret namespace: default data: username: "cm9vdA==" # Base64 编码后的工作区用户名,请根据实际修改 password: "UHdk******" # Base64 编码后的工作区密码,请根据实际修改 --- apiVersion: keda.sh/v1alpha1 kind: TriggerAuthentication metadata: name: keda-prom-creds namespace: default spec: secretTargetRef: - parameter: username name: keda-prom-secret key: username - parameter: password name: keda-prom-secret key: password --- apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: sglang-scale spec: scaleTargetRef: name: sglang # 指定部署推理负载时创建的 lws kind: LeaderWorkerSet apiVersion: leaderworkerset.x-k8s.io/v1 pollingInterval: 15 # 如果希望启用缩容到零能力,取消以下 3 行的注释。缩容到零可以在在没有流量时把副本数缩容到零,最大程度的减少资源闲置。 # idleReplicaCount: 0 # for keda trigger 0->1关键定义 # cooldownPeriod: 30 # 副本从1缩容到0的观察窗口期 # initialCooldownPeriod: 0 # cooldownPeriod 首次创建之后触发的观察窗口期 # 最小副本数(HPA) minReplicaCount: 1 # 最大副本数(HPA) maxReplicaCount: 2 triggers: # APIG 流量指标 - type: prometheus metadata: serverAddress: http://query.prometheus-cn-beijing.ivolces.com/workspaces/64bc5ed*** threshold: '50' query: sum(rate(istio_requests_total{request_host="example.com"}[1m])) by (request_host) authModes: "basic" authenticationRef: name: keda-prom-creds # sglang 指标 - type: prometheus metadata: serverAddress: http://query.prometheus-cn-beijing.ivolces.com/workspaces/64bc5ed*** threshold: '5' query: avg(sglang:num_queue_reqs{cluster="ccu6***", service="sglang-api-svc"}) by (pod) authModes: "basic" authenticationRef: name: keda-prom-creds # GPU 指标 - type: prometheus metadata: serverAddress: http://query.prometheus-cn-beijing.ivolces.com/workspaces/64bc5ed*** threshold: '0.3' query: avg(DCGM_FI_PROF_SM_ACTIVE{cluster="ccu6***", pod=~"sglang.*"}) authModes: "basic" authenticationRef: name: keda-prom-creds
上述示例中的部分参数需要根据实际环境修改,参数说明如下表所示。
参数 | 说明 |
---|---|
keda-prom-secret | 托管 Prometheus 工作区的 BasicAuth 认证信息。详情请参见 管理工作区。
说明 原始用户名和密码必须首先进行 Base64 编码处理,然后再填写到此处。例如:如果您的原始密码为 |
serverAddress | 托管 Prometheus 工作区 的 Query URL 地址。详情请参见 获取工作区地址。 |
query | 指标查询语句,其中cluster=="ccu6***" 为集群 ID,请填写为实际的集群 ID。 |
大模型部署完成后,可以在本地环境中,使用自定义域名和接入点调用大模型并获取应答。示例如下。
curl http://example.com/v1/chat/completions -X POST \ -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?"} ] }'
开启 API 网关的认证鉴权功能时,需要在请求中添加认证 Token,示例如下。
curl http://example.com/v1/chat/completions -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtp***" \ -d '{ "model": "/models/deepseek", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Who won the world series in 2020?"} ] }'
除使用 API 调用外,您也可以将上述模型添加到其他第三方客户端进行调用。例如:Dify 、cherrystudio、open-webui 等。