# 1. 技术选型概述
# 1.1 Ray分布式计算框架
Ray是 UC Berkeley riseLab针对机器学习领域开发的一种新的分布式计算框架,用于构建在任何规模下运行的分布式应用。其定位是一个通用的分布式编程框架,提供了统一的分布式底盘,能帮助用户将自己的程序快速分布式化。
- 项目地址:https://github.com/ray-project/ray (opens new window)
- 官方文档:https://docs.ray.io/en/latest/index.html (opens new window)
- 论文地址:https://arxiv.org/abs/1712.09381 (opens new window)
# 1.2 vLLM大模型推理框架
vLLM是一个大型语言模型推理加速工具,它通过优化内存管理、连续批处理、CUDA核心优化和分布式推理支持等技术手段,显著提高了大型语言模型的推理速度和效率。
- 项目地址:https://github.com/vllm-project/vllm (opens new window)
- 论文地址:https://dl.acm.org/doi/pdf/10.1145/3600006.3613165 (opens new window)
- 官方博客:vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention (opens new window)
注:在考虑并发量的服务端应用中,vLLM是目前最主流的大模型推理框架,它极大的提高了推理速度和吞吐量。而Ollama是给客户端用的,它的并发支持不行,且默认是4精度量化的模型,只适合个人自用。
# 2. 基础环境安装
# 2.1 准备服务器环境
# 2.1.1 部署环境说明
2台GPU服务器(每台 4×NVIDIA A16显卡,单卡16GB显存,总显存64GB),没有任何基础环境,从零开始安装部署。
网络地址:172.19.32.65、172.19.32.66,两台服务器之间的网络互通。
# 2.1.2 安装常用命令
$ apt-get install -y sudo # 安装sudo
$ sudo apt-get update # 更新apt-get
$ apt-get install iputils-ping -y # 安装ping
$ apt-get install -y wget # 安装wget
$ apt-get install curl -y # 安装curl
$ apt-get install xz-utils # 安装xz
$ apt-get install p7zip-full # 安装7z
$ apt-get install zip # 安装zip
$ apt-get install tree # 安装tree
$ apt-get install vim -y # 安装vim
$ apt-get install lsof # 安装lsof
$ apt-get install -y psmisc # 安装ps
$ apt-get install screen # 安装screen
2
3
4
5
6
7
8
9
10
11
12
13
# 2.1.3 下载模型权重
$ apt install git git-lfs
$ git lfs install
$ git clone https://hf-mirror.com/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B
2
3
# 2.2 安装显卡驱动与CUDA
# 2.2.1 安装CUDA环境
CUDA下载地址:https://developer.nvidia.com/cuda-toolkit-archive (opens new window),根据你的服务器情况进行选择,安装类型选择runfile (local),之后会自动给出安装命令。
根据给出的命令进行下载安装,出来协议时直接输入accept
,之后在CUDA Installer里选择Install。
$ wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda_12.1.0_530.30.02_linux.run
$ sudo chmod u+x cuda_12.1.0_530.30.02_linux.run
$ sudo ./cuda_12.1.0_530.30.02_linux.run
2
3
第一次安装失败,先查看cat /var/log/cuda-installer.log,再查看 cat /var/log/nvidia-installer.log,报错信息如下:
解决办法是手动禁止Nouveau kernel driver的运行。
$ sudo vim /etc/modprobe.d/blacklist-nouveau.conf
在文件里写入:
blacklist nouveau
options nouveau modeset=0
$ sudo update-initramfs -u
$ sudo reboot
2
3
4
5
6
7
8
之后重新安装CUDA,这次就安装成功了。
$ sudo ./cuda_12.1.0_530.30.02_linux.run
# 2.2.1 NVIDIA GPU资源查看
安装 nvidia-smi 及 nvidia-cuda-toolkit 工具
$ sudo apt update
$ sudo apt install nvidia-utils-520
$ sudo apt install nvidia-cuda-toolkit
2
3
使用 nvidia-smi
命令可以显示出GPU的所有基础信息。
$ nvidia-smi // 查询GPU详情
$ nvidia-smi -q // 查询GPU型号
2
查看CUDA驱动版本:
$ nvcc --version
# 2.3 安装Docker并配置
# 2.3.1 安装Docker环境
$ apt install -y docker.io
$ cp ./docker-compose /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ systemctl enable docker
$ systemctl restart docker
2
3
4
5
# 2.3.2 配置Docker的GPU环境
$ cat ./gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
$ echo -e "deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/deb/\$(ARCH) /" > /etc/apt/sources.list.d/nvidia-container-toolkit.list
$ apt install nvidia-container-toolkit -y
2
3
# 2.3.3 配置Docker国内镜像源
$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.imgdb.de",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com",
"https://docker.1ms.run",
"https://func.ink",
"https://lispy.org",
"https://docker.xiaogenban1993.com"
]
}
EOF
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.3.4 重启Docker使配置生效
$ sudo systemctl daemon-reload && sudo systemctl restart docker
# 2.4 搭建NFS文件系统
NFS(network file system)网络文件系统工具,通过网络使不同机器或者操作系统之间分享部分文件,用于宿主机和目标机之间的文件共享。使用该方式需要管理员权限,服务端配置好后,客户端不需要认证登录就可以挂载。
文件服务器(被挂载机):172.19.32.65 // 实际存储文件的地方
操作服务器(挂载机):172.19.32.66 // 使用文件的地方(实际不存储在这里)
2
# 2.4.1 安装NFS环境
安装 NFS(两台机器都需要安装)并设置开机自启
$ sudo apt-get install nfs-kernel-server -y // 安装 NFS 服务
$ systemctl status nfs-kernel-server.service // 查看NFS服务是否启动
$ systemctl enable nfs-kernel-server.service // 设置NFS主程序开机启动
2
3
# 2.4.2 在被挂载机上配置
Step2:在文件服务器(被挂载机)上新建目录,配置权限,配置挂载
$ mkdir -p /deepseek && chmod 777 -R /deepseek
$ vim /etc/exports
2
编辑需要共享的目录和允许访问的服务器(*
为不限制IP,不建议这么做,但如果不想限制IP就把如下配置的192.168.1.200换成*
即可)及权限,内容如下:
/deepseek *(rw,sync,no_root_squash)
注:如果服务器的端口大于1024,则还需要加上insecure,如果未加 insecure,下一步挂载时会报错mount.nfs: access denied by server while mounting
。
/deepseek *(insecure,rw,sync,no_root_squash)
重启文件服务器(被挂载机)NFS服务。
$ sudo /etc/init.d/nfs-kernel-server restart
另注:如果挂载后创建文件出现mount.nfs: Read-only file system
的错误,是/etc/exports
的配置有问题(例如IP与权限的那个括号之间应该没有空格,请查看是不是加了空格导致的)。
# 2.4.3 在挂载机上配置
操作服务器(挂载机)新建目录,配置挂载
$ mkdir /deepseek
$ sudo mount 172.19.32.65:/deepseek /deepseek
$ mount // 显示当前系统已经挂载的设备及挂载点
$ cd /deepseek && touch test.txt // 创建测试⽂件,去⽂件服务器(被挂载机)查看⽂件是否存在
$ cd /deepseek && rm -f test.txt // 删除测试⽂件
2
3
4
5
使用 umount 卸载挂载
$ sudo umount 172.19.32.65:/deepseek /deepseek
注意:如果出现 umount.nfs: XXX: device is busy
错误,可使用以下方式强制卸载挂载
$ sudo fuser –m –v /storage
$ kill -9 [pid]
$ sudo umount –lf 172.19.32.65:/deepseek /deepseek
2
3
# 2.4.4 设置开机自动挂载
$ vim /etc/rc.local // 写入如下配置
sudo mount 172.19.32.65:/deepseek /deepseek
2
# 3. 推理服务部署
# 3.1 将两台机器连接上Ray集群
# 3.1.1 拉取vLLM的镜像
两台机器拉取vLLM最新的Docker镜像,此时最新的vLLM是v0.7.2。
$ docker pull vllm/vllm-openai // 官方源
$ docker pull docker.1ms.run/vllm/vllm-openai // 国内受限的话,可以用这个镜像源
2
# 3.1.2 编写集群启动脚本
分别给两个机器编写集群启动脚本,CUDA_VISIBLE_DEVICES按照当前机器的空余显卡来写。
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Usage: $0 head_node_address --head|--worker [additional_args...]"
exit 1
fi
HEAD_NODE_ADDRESS="$1"
NODE_TYPE="$2"
shift 2
ADDITIONAL_ARGS=("$@")
if [ "${NODE_TYPE}" != "--head" ] && [ "${NODE_TYPE}" != "--worker" ]; then
echo "Error: Node type must be --head or --worker"
exit 1
fi
cleanup() {
if [ -e /var/lib/docker/containers/vllm ]; then
docker stop vllm
docker rm vllm
fi
}
trap cleanup EXIT
RAY_START_CMD="ray start --block"
if [ "${NODE_TYPE}" == "--head" ]; then
RAY_START_CMD+=" --head --port=6379"
else
RAY_START_CMD+=" --address=${HEAD_NODE_ADDRESS}:6379"
fi
docker run -itd \
--privileged \
--entrypoint /bin/bash \
--network host \
--name vllm \
--shm-size 10000000g \
--gpus all \
-v /deepseek/DeepSeek-R1-Distill-Qwen-32B/:/mnt \
"${ADDITIONAL_ARGS[@]}" \
-e CUDA_VISIBLE_DEVICES=0,1,2,3 \
docker.1ms.run/vllm/vllm-openai:latest \
-c "${RAY_START_CMD}
--restart=always\"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
关键参数解释:
-v /DeepSeek-R1-Distill-Qwen-32B/:/mnt # 将DeepSeek-R1-Distill-Qwen-32B挂载到/mnt目录
-e CUDA_VISIBLE_DEVICES=0,1,2,3 # 指定显卡
2
# 3.1.3 启动Ray集群节点
随便选一台服务器作为head节点,另一台作为worker节点。
head节点容器启动
$ bash run_cluster_head.sh 172.19.32.65 --head
worker节点容器启动
$ bash run_cluster_worker.sh 172.19.32.65 --worker
从任意服务器进入容器内,检查是否连接上了Ray集群。
$ docker exec -it vllm /bin/bash
$ ray status
2
发现两个节点都在,证明Ray启动脚本没问题,停止删除两个Docker容器。
# 3.2 LLaMA-Factory部署API服务
# 3.2.1 修改源码的初始化参数
下载 LLaMA-Factory 项目的源码。
$ cd /deepseek
$ git clone https://github.com/hiyouga/LLaMA-Factory.git
2
需要对 vllm_engine.py (opens new window) 里AsyncLLMEngine的初始化参数做一下更改。
原来是这样:
engine_args = {
"model": model_args.model_name_or_path,
"trust_remote_code": model_args.trust_remote_code,
"download_dir": model_args.cache_dir,
"dtype": model_args.infer_dtype,
"max_model_len": model_args.vllm_maxlen,
"tensor_parallel_size": get_device_count() or 1,
"gpu_memory_utilization": model_args.vllm_gpu_util,
"disable_log_stats": True,
"disable_log_requests": True,
"enforce_eager": model_args.vllm_enforce_eager,
"enable_lora": model_args.adapter_name_or_path is not None,
"max_lora_rank": model_args.vllm_max_lora_rank,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
需要把tensor_parallel_size手动改为多机使用的卡数。
engine_args = {
"model": model_args.model_name_or_path,
"trust_remote_code": model_args.trust_remote_code,
"download_dir": model_args.cache_dir,
"dtype": model_args.infer_dtype,
"max_model_len": model_args.vllm_maxlen,
"tensor_parallel_size": 8, # 改了这里
"gpu_memory_utilization": model_args.vllm_gpu_util,
"disable_log_stats": True,
"disable_log_requests": True,
"enforce_eager": model_args.vllm_enforce_eager,
"enable_lora": model_args.adapter_name_or_path is not None,
"max_lora_rank": model_args.vllm_max_lora_rank,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.2.2 修改集群启动脚本
需要将LLaMA-Factory项目挂载进容器,并安装相关依赖。
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Usage: $0 head_node_address --head|--worker [additional_args...]"
exit 1
fi
HEAD_NODE_ADDRESS="$1"
NODE_TYPE="$2"
shift 2
ADDITIONAL_ARGS=("$@")
if [ "${NODE_TYPE}" != "--head" ] && [ "${NODE_TYPE}" != "--worker" ]; then
echo "Error: Node type must be --head or --worker"
exit 1
fi
cleanup() {
if [ -e /var/lib/docker/containers/vllm ]; then
docker stop vllm
docker rm vllm
fi
}
trap cleanup EXIT
RAY_START_CMD="ray start --block"
if [ "${NODE_TYPE}" == "--head" ]; then
RAY_START_CMD+=" --head --port=6379"
else
RAY_START_CMD+=" --address=${HEAD_NODE_ADDRESS}:6379"
fi
FULL_CMD+="pip install datasets peft trl sse_starlette -i https://pypi.tuna.tsinghua.edu.cn/simple && ${RAY_START_CMD}"
docker run -itd \
--privileged \
--entrypoint /bin/bash \
--network host \
--name vllm \
--shm-size 10000000g \
--gpus all \
-v /deepseek/DeepSeek-R1-Distill-Qwen-32B/:/mnt/ \
-v /deepseek/LLaMA-Factory/:/app \
"${ADDITIONAL_ARGS[@]}" \
-e CUDA_VISIBLE_DEVICES=0,1,2,3 \
docker.1ms.run/vllm/vllm-openai:latest \
-c "${FULL_CMD}"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 3.2.3 启动大模型推理服务
head节点容器启动
$ bash run_cluster_head.sh 172.19.32.65 --head
worker节点容器启动
$ screen -S deepseek
$ bash run_cluster_worker.sh 172.19.32.65 --worker
$ VLLM_WORKER_MULTIPROC_METHOD=spawn \
CUDA_VISIBLE_DEVICES=0,1,2,3 \
DISABLE_VERSION_CHECK=1 \
python3 /app/src/api.py \
--model_name_or_path /mnt/ \
--template deepseek3 \
--infer_backend vllm \
--vllm_enforce_eager True \
--vllm_gpu_util 0.9 \
--vllm_maxlen 60000 \
--max_new_tokens 32768
2
3
4
5
6
7
8
9
10
11
12
13
# 3.2.4 验证推理服务是否正常
使用如下命令进行验证,可以得到符合预期的输出,部署成功。
$ curl --location --request POST 'http://172.19.32.66:8000/v1/chat/completions' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "DeepSeek-R1-Distill-Qwen-32B",
"messages": [
{
"role": "user",
"content": "树上有四只鸟,开枪打死一只,还剩几只?"
}
],
"temperature": 0.6,
"stream": true
}'
2
3
4
5
6
7
8
9
10
11
12
13
# 4. 参考资料
[1] deepseek r1满血版本部署 from 微信公众号 (opens new window)
[2] 分布式推理和服务 from vLLM官方文档 (opens new window)
[3] 尝试基于vLLM+Ray多机部署满血DeepSeek-R1 from 知乎 (opens new window)
[4] Ray+vLLM+LLaMA-Factory多机部署大模型 from 知乎 (opens new window)