借助DeepSeek之东风扬帆AI海洋(四):分布式部署

# 借助DeepSeek之东风扬帆AI海洋(三):打造高可用大模型集群

基于 Ollama 的量化版 DeepSeek 的部署。虽然 Docker 容器的方式运行简单,一条 docker 命令便可以拉起,但通常只能够运用在测试环境,供研发人员快速地验证方案。

当我们真正要将 AI 服务模型投入到生产时,必须直面以下挑战:

  1. 服务高可用性:单容器部署存在单点故障风险
  2. 弹性伸缩需求:LLM 推理的算力消耗具有明显波峰波谷特征
  3. 资源配置优化:GPU 资源的精细化调度与管理
  4. 服务发现难题:多模型实例的动态流量分配

利用网关 + 多个 Ollama 实现负载均衡的大模型集群的方案。这种方案的本质还是单卡单模型,但通过负载均衡技术,可以将一次对话任务,分配到多个模型来共同完成,算是一种提高性能的曲线救国路线。

但 Ollama 毕竟提供的是量化模型,如果想要体验原版效果还是要部署原版模型。不过,随着 LLM 模型越来越大,单 GPU 已经无法加载一个模型。以 DeepSeek-R1-Distill-Llama-70B 为例,模型权重大概 140 GB,但是单个 NVIDIA A100 只有 80GB 显存。如果想要在 A100 上部署 DeepSeek-R1-Distill-Llama-70B 模型,我们至少需要将模型切分后部署到 2 个 A100 机器上,每个 A100 卡加载一半的模型,这种方式称之为分布式推理。

DeepSeek 各模型版本推荐的配置:

以下是DeepSeek各模型版本推荐的配置:

模型版本 显存要求(推理) 内存要求 CPU要求 最低显卡型号 适用场景
DeepSeek-R1-1.5B 4GB+ 8GB+ 4核处理器(如Intel i5) GTX 1660 本地测试、个人开发、简单文本生成
DeepSeek-R1-3B 8GB+ 16GB+ Xeon W-2400系列 RTX 3060 中小型企业应用、轻量级NLP任务
DeepSeek-R1-7B 14GB+ 16GB+ Xeon W-2400系列 RTX 4080 通用NLP任务、中等复杂度任务
DeepSeek-R1-8B 10-16GB 16-32GB i7/Ryzen 9多核处理器 RTX 3080 高精度轻量级任务、初创企业AI客服
DeepSeek-R1-14B 28GB+ 32GB+ Xeon W-3400系列 RTX 3090×2 企业级复杂任务、长文本理解与生成
DeepSeek-R1-32B 58GB+ 64GB+ Xeon W-3400系列 RTX 3090×4 高精度专业任务、多模态任务预处理
DeepSeek-R1-70B 120GB+ 128GB+ EPYC 7002系列 A100×2 科研机构、大型企业、高复杂度生成任务
DeepSeek-R1-671B 1200GB+ 512GB+ EPYC 7002系列 A100×8×2 超大规模AI研究、通用人工智能(AGI)探索

考虑到业界使用习惯和社区热度等因素,将基于 vLLM 的模型部署方式,这也是云厂商使用非常多的一种方式,包括阿里、腾讯等公司都在使用。

什么是 vLLM

vLLM 是一个快速且易于使用的库,专为大型语言模型 (LLM) 的推理和部署而设计,可以无缝集成 HuggingFace、Modelscope 上的模型。

在性能优化上,vLLM 通过引入创建的架构和算法,例如 Paged Attention、动态张量并行等,减少计算开销,提高吞吐量,实现推理过程的高效,从而加速大模型在推理阶段的性能。一定程度上解决了传统大模型在硬件资源有限情况下的性能瓶颈。

使用 vLLM 部署 DeepSeek

建议 CUDA 版本选用 12.1 以上版本,因为 vLLM 默认是使用 CUDA 12.1 版本编译的,如果使用 12.1 以下版本,可能会出现兼容性问题,导致启动失败。

安装 vLLM

安装 vLLM 非常简单,官方文档介绍了三种方式。

1. pip 安装:

这种方法对于 python 开发者来说最友好。直接一条 pip 命令即可搞定。

bash 复制代码
pip install vllm

从官方 Github Release 中,我们也可以找到使用较低 CUDA 版本的编译脚本。例如最新的 0.7.2 版本就提供了基于 CUDA 11.8 版本的编译脚本。

可以用以下代码进行编译:

bash 复制代码
# Install vLLM with CUDA 11.8.
pip install https://github.com/vllm-project/vllm/releases/download/v0.7.2/vllm-0.7.2+cu118-cp38-abi3-manylinux1_x86_64.whl


# Re-install PyTorch with CUDA 11.8.
pip uninstall torch -y
pip install torch --upgrade --index-url https://download.pytorch.org/whl/cu118


# Re-install xFormers with CUDA 11.8.
pip uninstall xformers -y
pip install --upgrade xformers --index-url https://download.pytorch.org/whl/cu118
2. 从源码安装

适合有经验的开发者做二开或者测试 main 分支的版本等。编译的方法如下:

bash 复制代码
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .
3. 使用 Docker 安装(推荐)

在本地搭建一套开发环境太麻烦,一旦更换机器,就需要重新搭建。因此更推荐使用 Docker 安装,所有的环境官方 Docker 镜像都帮我们搞定了,无需自己适配。可以从 DockerHub 选择合适的版本进行下载。下载命令为:

bash 复制代码
docker pull vllm/vllm-openai:v0.7.2

然后使用 docker run 命令运行:

bash 复制代码
docker run --runtime nvidia --gpus all \
    -v ~/.cache/modescope:/root/.cache/modescope\
    -p 8000:8000 \
    --ipc=host \
    vllm/vllm-openai:v0.7.2

使用 vLLM

使用 vLLM 做模型推理时,主要分为离线批量推理、在线推理两种方式。首先来看需要编写 python 代码的离线推理。使用 DeepSeek-R1-Distill-Qwen-7B 进行测试。

离线推理

离线推理的意思是一次性给大模型发送多条 prompt,让大模型针对每条 prompt 分别给出回答。

需要注意的是 vLLM 默认是从 HuggingFace 下载模型,对于不能科学上网的,可以设置环境变量,让 vLLM 从 ModelScope 下载。

bash 复制代码
export VLLM_USE_MODELSCOPE=True

环境变量设置好后,来编写代码。代码主要涉及到两类,分别是 LLM 和 SamplingParams。

python 复制代码
from vllm import LLM, SamplingParams

prompts = [
    "Hello, my name is",
    "The president of the United States is",
    "The capital of France is",
    "The future of AI is",
]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

llm = LLM(model="deepseek-ai/DeepSeek-R1-Distill-Qwen-7B")

outputs = llm.generate(prompts, sampling_params)


# Print the outputs.
# 打印输出


for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

在线推理

在线推理是日常使用大模型时的方式,比如与大模型进行实时对话等,都属于在线推理。之所以大家喜欢使用 Ollama,主要是因为它为大模型封装了统一的兼容 OpenAI 数据结果的 API,用户直接修改 base_url 即可使用。那既然这个特性这么好,vLLM 没理由不支持。

vLLM 做了一个兼容 OpenAI 的 server,实现了常用的 API。比如 Completions API (/v1/completions),Chat Completions API (/v1/chat/completions)、List Models API(/v1/models)等。可以让用户不写代码,直接通过命令拉起大模型后,便可以使用 OpenAI API 访问大模型。默认情况下,它在 http://localhost:8000 启动 server,可以使用 --host 和 --port 参数指定地址和端口。

目前,该 server 一次只能拉起一个模型。我们使用以下命令,启动 server,并拉起大模型:

bash 复制代码
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-7B

可按照和 OpenAI API 相同的格式进行查询。例如,列出模型:

bash 复制代码
curl http://localhost:8000/v1/models

还可以传入参数 --api-key 或设置环境变量 VLLM_API_KEY,以便 API 对外暴露后,用户需要传入 apiKey 才能访问,这增加了访问的安全性。

调整聊天模板

默认情况下,服务器使用存储在 tokenizer 中的预定义聊天模板。可以使用 --chat-template 参数覆盖此模板:

bash 复制代码
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
 --chat-template ./examples/template_chatml.jinja

前面讲过的强制 think 的方法吗?当时是通过修改 Ollama 的模型的聊天模板解决的。对于这里拉起的原版模型,其聊天模板是在 tokenizer_config.json 文件内。

同样可以在 Assistant 后面加入 think 标签来解决。目前最新版本的模型文件,已经替我们加好了,直接使用即可。

OpenAI Completions API

接下来测试一下 Completions 对话的效果。

bash 复制代码
curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
        "prompt": "你是什么模型?",
        "max_tokens": 100,
        "temperature": 0
    }'

如果是通过 OpenAI SDK 访问,只需修改 base_url, model,代码如下:

bash 复制代码
from openai import OpenAI


# Modify OpenAI's API key and API base to use vLLM's API server.
# 使用 vLLM 的 API 服务器需要修改 OpenAI 的 API 密钥和 API 库。


openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8000/v1"
client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)
completion = client.completions.create(model="deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
                                      prompt="你是什么模型?")
print("Completion result:", completion)
OpenAI Chat API

在日常与大模型的对话中,上文中的一次性对话的例子其实很少使用,带有上下文的对话才是最常使用的,也就是使用 /v1/chat/completions 路由,来测试一下 vLLM 对其支持的效果。

bash 复制代码
curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
        "messages": [
            {"role": "system", "content": "你是一个 python 编程专家"},
            {"role": "user", "content": "请帮我写一段计算加法的程序"}
        ]
    }'

在代码中的使用方法与上文 /v1/completions 的代码一样。

分布式推理

模型推理有哪几种策略?

第一种,是单 GPU (无分布式推理) 的情况,只有我们 GPU 卡的显存能够承载模型的运行时,这种策略才适用。例如上文中的例子,我的 T4 卡 显存是 16 G,而 DeepSeek-R1-Distill-Qwen-7B 所需要的显存是 14 G,单卡可以满足,因此就需要做分布式。

第二种,是单节点多 GPU(张量并行推理) 的情况,这种情况适用于一张卡无法承载模型的运行。例如,如果我要运行一个 32 B 的模型,需要显存为 64 G,则我至少需要 5 张 T4 卡(4 张卡是 64 G,考虑到通常要设置显存只能占用 95% 的阈值,防止推理时将显存压爆,造成模型运行崩溃,不能可丁可卯),才能运行。vLLM 提供了一个参数,--tensor-parallel-size,用于设置张量并行数量。例如 5 张卡,就设置 --tensor-parallel-size 为 5。

俗话说,一个和尚挑水喝,三个和尚没水喝。当我们把模型切分到多张卡运行后,并不见得就比一张卡运行要快。此时就需要用到 NVIDIA 的一项技术,那就是 NVLInk 技术。NVlink 相当于用一条高速公路,将多张卡串在了一起,保证了多卡之间数据交换的效率。

但 NVLink 也不是任意 GPU 都支持的,NVIDIA 高端系列的 GPU 卡,才支持。你可以访问后面的链接 NVLink 高速 GPU 互连 | NVIDIA Quadro,了解他们对不同卡的支持情况。

第三种,是多节点单(多) GPU(张量并行加管道并行推理) 的情况,当我们的单台节点上没有这么多卡了,就需要多个节点来凑。例如,我要部署一个 DeepSeek-R1 671B,需要 16 张 A100,则此时一般会使用两个节点,每个节点上 8 张卡。

把多节点的并行推理,叫做管道并行。可以用 --pipeline-parallel-size 设置 管道并行数量,例如 16 张 A100 的场景,就可以设置 --tensor-parallel-size 为 8,--pipeline-parallel-size 为 2。

单节点上多卡之间可以用 NVLink 技术保证效率,那么多节点怎么办呢?

此时就需要用到高速网络了,否则速度会非常慢。常用的高速网络方案是 IB 网络,一种专为高性能计算(HPC)和超大规模数据中心设计的网络技术,速度可达 400G/s。远非传统机房的万兆网可比。

什么是 Ray

Ray 是一个开源的分布式计算框架,旨在简化大规模机器学习和分布式应用程序的开发。它提供了高效的并行处理能力,支持数据预处理、分布式训练、超参数调优、模型服务和强化学习等任务。Ray 的核心概念包括任务(Tasks)、参与者(Actors)和对象(Objects),使得开发者能够轻松地在分布式环境中编写和执行并行代码。

由字节跳动技术团队牵头,联合 AnyScale、蚂蚁金服、微软等公司在 Ray 的基础上又开发了适配 Kubernetes 版本的 KubeRay。它采用了经典的 Operator 设计,提供了 RayCluster、RayJob 和 RayService 等自定义资源定义(CRD),使得在 Kubernetes 集群上部署和管理 Ray 集群变得更加简便。通过 KubeRay,用户可以高效地管理 Ray 集群的生命周期,实现弹性伸缩、资源调度和作业管理等功能。

Ray-Operator 是 KubeRay 项目中的核心组件,负责在 Kubernetes 集群中创建和管理 Ray 集群。它通过监听 RayCluster、RayJob 和 RayService 等 CRD 的变化,自动化地处理 Ray 集群的部署、扩缩容和故障恢复等任务。Ray-Operator 使得用户能够以声明式的方式管理 Ray 集群,简化了集群的运维工作。

下图是在 Kubernetes 上通过 Ray-operator 创建 Ray 集群的示意图。用户通过向 Ray-operator 提交 CR 的方式,来创建 Ray-Cluster。Ray-Cluster 包括一个 Head 和多个 Worker,会分别分布在不同的 GPU 节点上。以图中所示为例,含有两个 GPU 节点,则会有一个 Head 和一个 Worker 分别在这两个节点上以 pod 形式创建。

部署过程

测试使用多节点多卡的部署方式,通过云准备一台GPU版本的K8S,包含三个非 GPU 的 master 节点,以及两个 GPU 节点,每个节点上有一张 A100 卡。

这台 K8s 会通过 NVIDIA 的 GPU-operator 部署好 NVIDIA 相关的驱动等,CUDA 版本选择 12.2。

机器准备好后,接下来就是模型文件的准备。对于不能科学上网的同学,模型文件可以在魔搭社区下载,链接:www.modelscope.cn/models/deep... repo 大概有 131G 左右,因此推荐你将模型下载到对象存储或者云硬盘,再通过 PV、PVC 的方式挂载。我采用的是对象存储的方式,PV、PVC 的 YAML 如下:

yaml 复制代码
apiVersion: v1                                                                                                                                                           
kind: PersistentVolume                                                                                                                                                   
metadata:                                                                                                                                                                
  name: deepseek                                                                                                                                                    
spec:                                                                                                                                                                    
  accessModes:                                                                                                                                                           
  - ReadWriteMany                                                                                                                                                        
  capacity:                                                                                                                                                              
    storage: 200Gi                                                                                                                                                       
  csi:                                                                                                                                                                   
    driver: ossplugin.csi.cucloud.com                                                                                                                                    
    volumeAttributes:                                                                                                                                                    
      bucket: deepseek                                                                                                                                               
      url: http://obs-sh-internal.cucloud.cn                                                                                                                             
    volumeHandle: deepseek                                                                                                                                           
  persistentVolumeReclaimPolicy: Retain                                                                                                                                  
  volumeMode: Filesystem                                                                                                                                                 
---                                                                                                                                                                                                                                                                              
apiVersion: v1                                                                                                                                                           
kind: PersistentVolumeClaim                                                                                                                                              
metadata:                                                                                                                                                                
  name: deepseek                                                                                                                                                    
  namespace: kuberay-operator                                                                                                                                              
spec:                                                                                                                                                                    
  accessModes:                                                                                                                                                           
  - ReadWriteMany                                                                                                                                                        
  resources:                                                                                                                                                             
    requests:                                                                                                                                                            
      storage: 200Gi                                                                                                                                                     
  volumeMode: Filesystem                                                                                                                                                 
  volumeName: deepseek

在 ModelScope 上下载模型有多种方式,推荐使用 ModelScope Python SDK 的方式进行下载。执行以下命令即可下载。

bash 复制代码
pip install modelscope

modelscope download --model deepseek-ai/DeepSeek-R1-Distill-Llama-70B --cache_dir /mnt/deepseek

我们可以使通过--cache_dir 指定模型文件存放目录。例如在我的命令中的 /mnt/deepseek,意思是把模型下载到 /mnt/deepseek 目录。下载完成后,上传到对象存储即可。

为了节省一遍上传的时间,我们也可以在 K8s 上创建一个带有 python 环境的 pod,然后将上文中的对象存储 PVC 挂载到 pod 中,这样就可以直接在 pod 内访问到对象存储桶,也就可以直接将模型下载到对象存储桶内了。

当然,我还有种更简便的做法。可以先把 Ray 集群拉起来,Ray 集群内就带了 python 环境,然后把对象存储 PVC 挂载到 Ray 集群的 Head 中即可。

Ray 集群部署

接下来看一下 Ray 的部署。我们知道通过 kuberay-operator,可以方便的部署 Ray 集群。kuberay-operator 可以使用官方提供的 Helm Chart 包进行安装。命令如下:

bash 复制代码
helm repo add kuberay https://ray-project.github.io/kuberay-helm/helm repo update
helm repo update
helm install kuberay-operator -n kuberay-operator kuberay/kuberay-operator

之后看一下 kuberay-operator 的 pod 运行状况:

bash 复制代码
kubectl get po -n kuberay-operator

NAME                                          READY   STATUS    RESTARTS   AGE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
kuberay-operator-5c5cb548db-2q2br             1/1     Running   0          23h

确认它处于 Running 状态就可以了。

然后我们来创建 Ray-Cluster,向 kuberay-operator 提交 CR 即可。官方将 CR 封装成了 Helm Chart 包,可以通过如下命令部署。

bash 复制代码
helm install raycluster kuberay/ray-cluster -n kuberay-operator

但由于 CUDA 版本原因,我们需要找一个合适版本的 Ray 集群,因此我是将 Helm 包 fetch 下来,将 CR yaml 提取出来,手动进行了更改。YAML 如下:

yaml 复制代码
apiVersion: ray.io/v1                                                                                                                                                                                                                                                                                                                                  
kind: RayCluster                                                                                                                                                                                                                                                                                                                                       
metadata:                                                                                                                                                                                                                                                                                                                                              
  annotations:                                                                                                                                                                                                                                                                                                                                         
    meta.helm.sh/release-name: raycluster                                                                                                                                                                                                                                                                                                              
    meta.helm.sh/release-namespace: kuberay-operator                                                                                                                                                                                                                                                                                                   
  generation: 3                                                                                                                                                                                                                                                                                                                                        
  labels:                                                                                                                                                                                                                                                                                                                                              
    app.kubernetes.io/instance: raycluster                                                                                                                                                                                                                                                                                                             
    app.kubernetes.io/managed-by: Helm                                                                                                                                                                                                                                                                                                                 
    helm.sh/chart: ray-cluster-1.2.2                                                                                                                                                                                                                                                                                                                   
  name: raycluster-kuberay                                                                                                                                                                                                                                                                                                                             
  namespace: kuberay-operator                                                                                                                                                                                                                                                                                                                          
spec:                                                                                                                                                                                                                                                                                                                                                  
  headGroupSpec:                                                                                                                                                                                                                                                                                                                                       
    rayStartParams:                                                                                                                                                                                                                                                                                                                                    
      dashboard-host: 0.0.0.0                                                                                                                                                                                                                                                                                                                          
    serviceType: ClusterIP                                                                                                                                                                                                                                                                                                                             
    template:                                                                                                                                                                                                                                                                                                                                          
      metadata:                                                                                                                                                                                                                                                                                                                                        
        annotations: {}                                                                                                                                                                                                                                                                                                                                
        labels:                                                                                                                                                                                                                                                                                                                                        
          app.kubernetes.io/instance: raycluster                                                                                                                                                                                                                                                                                                       
          app.kubernetes.io/managed-by: Helm                                                                                                                                                                                                                                                                                                           
          helm.sh/chart: ray-cluster-1.2.2                                                                                                                                                                                                                                                                                                             
      spec:                                                                                                                                                                                                                                                                                                                                            
        affinity: {}                                                                                                                                                                                                                                                                                                                                   
        containers:                                                                                                                                                                                                                                                                                                                                    
        - image: docker.1ms.run/rayproject/ray-ml:2.11.0.a464b6-py310-gpu                                                                                                                                                                                                                                                                              
          imagePullPolicy: IfNotPresent                                                                                                                                                                                                                                                                                                                
          name: ray-head                                                                                                                                                                                                                                                                                                                               
          resources:                                                                                                                                                                                                                                                                                                                                   
            limits:                                                                                                                                                                                                                                                                                                                                    
              cpu: "4"                                                                                                                                                                                                                                                                                                                                 
              memory: 16G                                                                                                                                                                                                                                                                                                                              
            requests:                                                                                                                                                                                                                                                                                                                                  
              cpu: "1"                                                                                                                                                                                                                                                                                                                                 
              memory: 2G                                                                                                                                                                                                                                                                                                                               
          securityContext: {}                                                                                                                                                                                                                                                                                                                          
          volumeMounts:                                                                                                                                                                                                                                                                                                                                
          - mountPath: /tmp/ray                                                                                                                                                                                                                                                                                                                        
            name: log-volume                                                                                                                                                                                                                                                                                                                           
          - mountPath: /mnt/deepseek                                                                                                                                                                                                                                                                                                                   
            name: deepseek-r1                                                                                                                                                                                                                                                                                                                          
        imagePullSecrets: []                                                                                                                                                                                                                                                                                                                           
        nodeSelector: {}                                                                                                                                                                                                                                                                                                                               
        tolerations: []                                                                                                                                                                                                                                                                                                                                
        volumes:                                                                                                                                                                                                                                                                                                                                       
        - emptyDir: {}                                                                                                                                                                                                                                                                                                                                 
          name: log-volume                                                                                                                                                                                                                                                                                                                             
        - name: deepseek-r1                                                                                                                                                                                                                                                                                                                            
          persistentVolumeClaim:                                                                                                                                                                                                                                                                                                                       
            claimName: deepseek                                                                                                                                                                                                                                                                                                                        
  workerGroupSpecs:                                                                                                                                                                                                                                                                                                                                    
  - groupName: workergroup                                                                                                                                                                                                                                                                                                                             
    maxReplicas: 3                                                                                                                                                                                                                                                                                                                                     
    minReplicas: 1                                                                                                                                                                                                                                                                                                                                     
    numOfHosts: 1                                                                                                                                                                                                                                                                                                                                      
    rayStartParams:                                                                                                                                                                                                                                                                                                                                    
      num-gpus: "1"                                                                                                                                                                                                                                                                                                                                    
    replicas: 1                                                                                                                                                                                                                                                                                                                                        
    template:                                                                                                                                                                                                                                                                                                                                          
      metadata:                                                                                                                                                                                                                                                                                                                                        
        annotations: {}                                                                                                                                                                                                                                                                                                                                
        labels:                                                                                                                                                                                                                                                                                                                                        
          app.kubernetes.io/instance: raycluster                                                                                                                                                                                                                                                                                                       
          app.kubernetes.io/managed-by: Helm                                                                                                                                                                                                                                                                                                           
          helm.sh/chart: ray-cluster-1.2.2                                                                                                                                                                                                                                                                                                             
      spec:                                                                                                                                                                                                                                                                                                                                            
        affinity: {}                                                                                                                                                                                                                                                                                                                                   
        containers:                                                                                                                                                                                                                                                                                                                                    
        - image: docker.1ms.run/rayproject/ray-ml:2.11.0.a464b6-py310-gpu                                                                                                                                                                                                                                                                              
          imagePullPolicy: IfNotPresent                                                                                                                                                                                                                                                                                                                
          name: ray-worker                                                                                                                                                                                                                                                                                                                             
          resources:                                                                                                                                                                                                                                                                                                                                   
            limits:                                                                                                                                                                                                                                                                                                                                    
              cpu: "14"                                                                                                                                                                                                                                                                                                                                
              memory: 60G                                                                                                                                                                                                                                                                                                                              
            requests:                                                                                                                                                                                                                                                                                                                                  
              cpu: "1"                                                                                                                                                                                                                                                                                                                                 
              memory: 1G                                                                                                                                                                                                                                                                                                                               
          securityContext: {}                                                                                                                                                                                                                                                                                                                          
          volumeMounts:                                                                                                                                                                                                                                                                                                                                
          - mountPath: /tmp/ray                                                                                                                                                                                                                                                                                                                        
            name: log-volume                                                                                                                                                                                                                                                                                                                           
          - mountPath: /mnt/deepseek                                                                                                                                                                                                                                                                                                                   
            name: deepseek-r1                                                                                                                                                                                                                                                                                                                          
        imagePullSecrets: []                                                                                                                                                                                                                                                                                                                           
        nodeSelector: {}                                                                                                                                                                                                                                                                                                                               
        tolerations: []                                                                                                                                                                                                                                                                                                                                
        volumes:                                                                                                                                                                                                                                                                                                                                       
        - emptyDir: {}                                                                                                                                                                                                                                                                                                                                 
          name: log-volume                                                                                                                                                                                                                                                                                                                             
        - name: deepseek-r1                                                                                                                                                                                                                                                                                                                            
          persistentVolumeClaim:                                                                                                                                                                                                                                                                                                                       
            claimName: deepseek

首先是镜像,使用 rayproject/ray-ml:2.11.0.a464b6-py310-gpu,也就是 2.11.0 版本的 Ray 集群。之后是 Head 节点和 Worker 节点的配置。Head 节点很简单,就是将对象存储 PVC 挂载上即可。Worker 节点除了挂载 PVC 之后,还需要配置两个参数,即:

yaml 复制代码
numOfHosts: 1                                                                                                                                                                                                                                                                                                                                      
rayStartParams:                                                                                                                                                                                                                                                                                                                                    
  num-gpus: "1"  

numOfHosts 代表在一个节点上部署 worker,num-gpus 代表每个节点上有一张卡。这里是个坑,很多网上的教程在只有两个 GPU 节点的情况下会把 numOfHosts 设置成 2,这是没有理解 Ray 集群的组成。实际上,Head 本身会占用一个节点,因此 Worker 创建一个即可。

配好参数后,直接 kubectl apply 拉起:

bash 复制代码
kubectl get po -n kuberay-operator -owide

NAME                                          READY   STATUS    RESTARTS   AGE    IP             NODE           NOMINATED NODE   READINESS GATES                                                                                                                                                                                                                                                                                                                                                                                                                                    
raycluster-kuberay-head-zphgs                 1/1     Running   0          171m   10.43.0.35     192.168.0.34                                                                                                                                                                                                                              
raycluster-kuberay-workergroup-worker-kbsvr   1/1     Running   0          171m   10.43.140.28   192.168.0.68              

此时可以进入 raycluster-kuberay-head-zphgs 内,查看 ray 集群的状态。

bash 复制代码
(base) ray@raycluster-kuberay-head-zphgs:~$ ray status                                                                                                                                                                                                                                                                                                 
2025-02-13 00:54:12,571 - INFO - Note: NumExpr detected 16 cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 8.                                                                                                                                                                                                                      
2025-02-13 00:54:12,571 - INFO - NumExpr defaulting to 8 threads.                                                                                                                                                                                                                                                                                      
======== Autoscaler status: 2025-02-13 00:54:12.737576 ========                                                                                                                                                                                                                                                                                        
Node status                                                                                                                                                                                                                                                                                                                                            
---------------------------------------------------------------                                                                                                                                                                                                                                                                                        
Active:                                                                                                                                                                                                                                                                                                                                                
 1 node_a0dcf7b6cdb9c28191d6db6a44ba774ed04fb0bbda704a498112674f                                                                                                                                                                                                                                                                                       
 1 node_3804fd0732e483a2240e9f608d15362f415411fca7c69b58232a1174                                                                                                                                                                                                                                                                                       
Pending:                                                                                                                                                                                                                                                                                                                                               
 (no pending nodes)                                                                                                                                                                                                                                                                                                                                    
Recent failures:                                                                                                                                                                                                                                                                                                                                       
 (no failures)                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                       
Resources                                                                                                                                                                                                                                                                                                                                              
---------------------------------------------------------------                                                                                                                                                                                                                                                                                        
Usage:                                                                                                                                                                                                                                                                                                                                                 
 0.0/18.0 CPU                                                                                                                                                                                                                                                                                                                                          
 0.0/2.0 GPU                                                                                                                                                                                                                                                                                                                                           
 0B/70.78GiB memory                                                                                                                                                                                                                                                                                                                                    
 0B/20.90GiB object_store_memory                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                       
Demands:                                                                                                                                                                                                                                                                                                                                               
 (no resource demands)

可以看到有两个 Active 的节点,和两个没有使用的 GPU。Ray 集群自带了一个可视化 UI,可以直观地查看 CPU,内存,GPU 等的使用量以及任务执行情况等,因此可以通过 loadBalancer 或者 NodePort 将 UI 的端口暴露出去,即可在集群外部访问。我们在浏览器输入 http://xxxx:8265 进入 Web UI 查看。

在 Ray 中 部署 Vllm

在 Ray 容器中,默认提供了一个 Conda 环境,有很多基础包,但需要将 pynvml 包卸载掉,因为这会与另一个包 nvidia-ml-py 冲突,命令:

bash 复制代码
pip uninstall pynvml

之后就可以安装 vllm 了,为了适配 Ray 集群,我选择的版本是 0.6.1.post2,安装命令为:

bash 复制代码
pip install vllm==0.6.1.post2

安装完成后,便可以使用 vllm 拉起大模型。就像上节课讲得那样,此处可以使用 python 代码的方式,也可以直接使用 vllm serve 命令,它会拉起大模型,同时提供一个 OpenAI 兼容的服务器。命令:

bash 复制代码
vllm serve /mnt/deepseek/deepseek-ai/DeepSeek-R1-Distill-Llama-70B \
--port 8000 \
--trust-remote-code \
--served-model-name deepseek-r1 \
--gpu-memory-utilization 0.95 \
--tensor-parallel-size 2 \
--max-model-len 8096
相关推荐
行十万里人生8 分钟前
仓颉项目调试配置与多文件场景下的问题解析
开发语言·人工智能·机器学习·华为od·华为·华为云·harmonyos
路人与大师17 分钟前
对 `llamafactory-cli api -h` 输出的详细解读
人工智能·深度学习
YYXZZ。。28 分钟前
PyTorch——卷积操作(2)
人工智能·pytorch·python
豆浩宇29 分钟前
Halcon光度立体法
c++·人工智能·机器学习·计算机视觉
飞哥数智坊1 小时前
Coze实战第11讲:你也能一键生成独一无二的姓氏词语头像
人工智能·coze
hahaha60161 小时前
采摘机器人项目
人工智能·计算机视觉
算法如诗1 小时前
基于贝叶斯优化神经网络的光伏功率预测综述
人工智能·深度学习·神经网络
Leo.yuan3 小时前
数据资产是什么?数据资产平台如何发挥作用?
大数据·运维·数据仓库·人工智能·信息可视化
开开心心就好4 小时前
免费批量文件重命名软件
vue.js·人工智能·深度学习·typescript·pdf·excel·less
蹦蹦跳跳真可爱5896 小时前
Python----目标检测(《Fast R-CNN》和Fast R-CNN)
人工智能·python·深度学习·神经网络·目标检测·cnn