GPUStack 安装与多节点配置教程:用 Docker 管理多台 NVIDIA GPU 主机
本文记录一次实际的 GPUStack 多节点部署过程,适合希望把多台电脑上的 NVIDIA GPU 统一管理、统一部署模型,并通过 OpenAI 兼容 API 对外提供服务的用户。
本文实测环境为 GPUStack v2.2.3。GPUStack 更新较快,安装 Worker 时应优先复制当前管理界面生成的命令,本文命令用于解释各项配置和排查思路。
一、GPUStack 是什么
GPUStack 可以把多台机器上的 GPU 组织成一个统一管理的集群。它负责管理 Worker、模型、推理后端、模型实例、资源调度和 API,而上层应用只需要连接 GPUStack 提供的统一接口。
一个典型结构如下:
AI 应用 / Open WebUI / Agent
│
OpenAI 兼容 API(/v1)
│
GPUStack Server
192.168.5.25
│
┌───────────────┴───────────────┐
│ │
Worker 1 Worker 2
RTX 5070 Ti 12GB RTX 3060 Ti 8GB
192.168.5.25 192.168.5.13需要先澄清一个常见误区:两台电脑各有一张显卡,不等于把两张显卡的显存自动合成一张更大的显卡。GPUStack 最适合做统一管理和任务调度,例如让 5070 Ti 运行主模型,让 3060 Ti 运行 Embedding、Reranker 或小模型。
新版 GPUStack 在 vLLM、SGLang、MindIE 等特定后端下支持分布式推理,但这需要后端、模型和网络环境共同满足要求。普通家庭千兆局域网更适合“不同 GPU 运行不同任务”,不建议一开始就跨两台电脑拆分同一个大模型。
二、本文使用的环境
本文用下面这组地址演示:
| 角色 | 地址 | GPU | 用途 |
|---|---|---|---|
| Server + Worker | 192.168.5.25 | RTX 5070 Ti Laptop 12GB | GPUStack 管理端、主力模型 |
| Worker | 192.168.5.13 | RTX 3060 Ti 8GB | Embedding、Reranker、小模型 |
软件环境:
- Linux,或 Windows 上的 WSL2 Linux
- Docker Engine
- NVIDIA 显卡驱动
- NVIDIA Container Toolkit
- GPUStack v2.2.3
- 两台主机处于可以互相访问的局域网
GPUStack 官方目前建议使用 Docker 镜像安装,不建议再通过 PyPI 直接安装。多节点之间还应启用 NTP 时间同步,避免节点状态不同步。
三、安装前检查
以下检查需要在每一台 NVIDIA GPU 主机上执行。
1. 确认系统能够识别显卡
nvidia-smi能够显示显卡型号、驱动版本和显存状态,才说明宿主机驱动正常。
2. 确认 Docker 正常
sudo docker version
sudo docker ps如果不使用 sudo 时出现:
permission denied while trying to connect to the Docker API这不是 GPUStack 故障,而是当前用户没有 Docker Socket 权限。可以暂时在 Docker 命令前加 sudo。如果希望长期免 sudo,可将当前用户加入 Docker 组,然后退出终端并重新登录:
sudo usermod -aG docker $USER3. 确认容器可以访问 GPU
先检查 Docker 是否配置了 NVIDIA Runtime:
sudo docker info 2>/dev/null | grep -i nvidia也可以直接运行一个 CUDA 容器测试:
sudo docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi如果宿主机的 nvidia-smi 正常,而容器内失败,通常是 NVIDIA Container Toolkit 尚未安装或没有正确配置。此时应先修复容器 GPU 环境,再安装 GPUStack。
四、安装 GPUStack Server
GPUStack Server 负责管理界面、调度、API 和数据库。Server 容器默认内置 PostgreSQL,个人或小型局域网部署通常无需另外安装数据库。
在准备作为 Server 的主机上运行:
sudo docker run -d --name gpustack \
--restart=unless-stopped \
--privileged \
--network=host \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume gpustack-data:/var/lib/gpustack \
--runtime nvidia \
gpustack/gpustack:v2.2.3 \
--advertise-address 192.168.5.25如果使用官方镜像的其他仓库地址,也可以把最后的镜像名替换成安装页面给出的地址,例如 quay.io/gpustack/gpustack:v2.2.3。一个集群内的 Server 和 Worker 应使用相同版本。
检查容器状态:
sudo docker ps | grep gpustack
sudo docker logs --tail 100 gpustackGPUStack 默认 API 端口是 30080。在浏览器访问:
http://192.168.5.25:30080如果你的部署方式在前面配置了网关、反向代理或映射到 80 端口,则按实际地址访问。
初始管理员密码通常保存在数据目录中,可以尝试执行:
sudo docker exec -it gpustack cat /var/lib/gpustack/initial_admin_password登录后请立即修改管理员密码。
五、添加第二台 Worker
推荐的做法不是手写 Token,而是进入 GPUStack 管理界面:
Clusters → 选择集群 → Add Worker复制页面生成的 docker run 命令,在 Worker 主机上执行。这样能确保 Token、镜像版本和当前版本所需参数一致。
下面是本文环境中使用过的命令结构。请把 Token 替换成管理界面生成的真实值,绝对不要把真实 Token 发布到博客或截图中。
sudo docker run -d --name gpustack-worker \
-e "GPUSTACK_RUNTIME_DEPLOY_MIRRORED_NAME=gpustack-worker" \
-e "GPUSTACK_TOKEN=<WORKER_TOKEN>" \
--restart=unless-stopped \
--privileged \
--network=host \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume gpustack-data:/var/lib/gpustack \
--runtime nvidia \
quay.io/gpustack/gpustack:v2.2.3 \
--server-url http://192.168.5.25:30080 \
--worker-ip 192.168.5.13如果管理界面生成的命令使用 --token 或 --advertise-address,应保留管理界面给出的写法,不要为了与本文完全一致而擅自改参数。GPUStack 的命令行参数必须写在镜像名后面;镜像名前面的是 Docker 参数。
另一个很容易忽略的细节是:Bash 的续行符 \ 后面不能再有空格,否则下一行不会被当作同一条命令。
启动后检查:
sudo docker ps | grep gpustack
sudo docker logs --tail 100 gpustack-worker日志中应能看到类似内容:
Version check passed
Registering worker
Worker registered
GPUStack worker startup completed然后回到管理界面的 Workers 页面,确认第二台机器和它的 GPU 已经出现。
六、为什么 Worker 已注册,却只显示 Server 的 GPU
这是我在实际部署中遇到的主要问题。Worker 日志里虽然显示注册成功,但配置却是:
"server_url": "http://192.168.5.25",
"worker_ip": "127.0.0.1"Worker 把自己的地址上报成了 127.0.0.1。Server 即使知道有这台 Worker,也无法通过回环地址访问另一台电脑上的 Worker 服务。
解决方式是重建 Worker,并明确指定局域网地址:
sudo docker rm -f gpustack-worker然后在新的启动命令末尾加入正确地址:
--worker-ip 192.168.5.13新版或管理界面生成的命令也可能使用:
--advertise-address 192.168.5.13重建后再次检查日志,确认 worker_ip 不再是 127.0.0.1。
七、多节点网络和端口
只验证“Worker 能访问 Server”还不够。GPUStack 多节点需要至少满足:
- Worker 能访问 Server,用于注册、心跳和状态同步;
- Server 能访问 Worker,用于转发推理请求;
- 分布式推理场景下,Worker 之间还需要互通。
官方默认端口包括:
| 端口 | 用途 |
|---|---|
TCP 30080 | GPUStack Server API |
TCP 10150 | Worker API |
TCP 10151 | Worker Metrics |
TCP 40000-40063 | 推理服务端口范围 |
TCP 41000-41999 | Ray 分布式服务端口范围 |
在 Server 主机上测试 Worker:
curl http://192.168.5.13:10150/如果返回:
{"detail":"Not Found"}这通常反而说明端口已经连通,只是根路径 / 没有对应接口。真正有问题的是超时、拒绝连接或路由不可达。
在 Worker 主机上也要测试 Server:
curl http://192.168.5.25:30080/如果使用了系统防火墙、路由器访客网络、VLAN、WSL2、虚拟机 NAT 或 VPN,需要确保上面的地址和端口在正确方向上可以访问。
八、部署第一个模型
Worker 正常后,进入:
Models → Deployments → Deploy ModelGPUStack 支持从 Hugging Face、ModelScope 和本地路径部署模型。一般流程如下:
- 选择模型来源并搜索模型;
- 设置部署名称;
- 选择集群和推理后端;
- 设置副本数量;
- 根据显存调整上下文长度、量化和性能参数;
- 使用 Worker Selector 指定运行模型的 Worker;
- 提交部署并观察实例日志。
对于本文的两张显卡,更合理的分工是:
RTX 5070 Ti 12GB
└── 主聊天模型 / Coding 模型 / Agent 模型
RTX 3060 Ti 8GB
├── Embedding
├── Reranker
├── Whisper
└── 小型 LLMGPUStack 会根据模型元数据估算资源需求,然后把模型实例调度到满足条件的 Worker。不要只看模型文件大小,KV Cache、上下文长度、后端和并发设置也会占用显存。
九、理解 No suitable workers
假设部署时出现:
No suitable workers.
Details:
- Matched 2 workers by cluster selector.
- The model requires approximately 17.34 GiB VRAM.
- The largest available worker provides 11.94 GiB VRAM.这段日志说明两台 Worker 已经匹配成功,问题不是节点丢失,而是没有任何一台 Worker 能独立满足模型的显存需求:
模型需要:17.34 GiB
最大单卡:11.94 GiB两台电脑上的 12GB + 8GB 不会在普通部署模式下自动变成一张 20GB 显卡。
可选的解决方式包括:
- 换用参数量更小的模型;
- 换用更低量化版本;
- 降低上下文长度和 KV Cache 占用;
- 减小并发、Batch Size 或副本数量;
- 在支持的自定义后端中启用 CPU Offload;
- 在 vLLM、SGLang 或 MindIE 支持的环境中配置分布式推理;
- 把两个不同任务分别部署到两台 Worker,提高整体吞吐量。
对于一台 12GB 显卡和一台 8GB 显卡的普通局域网,最后一种通常最稳定,也最能发挥 GPUStack 的管理优势。
十、通过 OpenAI 兼容 API 调用模型
模型部署成功后,在 GPUStack 中创建 API Key,然后使用 /v1 接口调用。
export GPUSTACK_API_KEY="<YOUR_API_KEY>"
curl http://192.168.5.25:30080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${GPUSTACK_API_KEY}" \
-d '{
"model": "your-model-name",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你好,请介绍一下你自己。"}
],
"stream": false
}'连接其他兼容 OpenAI API 的客户端时,通常填写:
Base URL: http://192.168.5.25:30080/v1
API Key: 在 GPUStack 中创建的 API Key
Model: GPUStack 中的模型部署名称不要把 Worker 注册 Token 当成 API Key。前者用于 Worker 加入集群,后者用于应用调用模型,两者用途不同。
十一、常用维护命令
查看容器:
sudo docker ps | grep gpustack查看 Server 日志:
sudo docker logs -f gpustack查看 Worker 日志:
sudo docker logs -f gpustack-worker重启容器:
sudo docker restart gpustack
sudo docker restart gpustack-worker查看数据卷:
sudo docker volume ls
sudo docker volume inspect gpustack-data删除并重建 Worker,但保留数据卷:
sudo docker rm -f gpustack-worker不要在没有备份的情况下删除 Server 的 gpustack-data 数据卷。它可能包含数据库、配置、日志和模型缓存等数据。
十二、升级时的注意事项
升级前先备份数据,并记录原来的完整启动参数。升级顺序应为:
- 先升级 Server;
- 再升级各个 Worker;
- 保证 Server 和 Worker 版本一致;
- 到
Clusters → Add Worker重新获取当前版本的 Worker 命令; - 重新检查 Worker IP、GPU 识别和双向网络。
生产环境不建议长期使用浮动的 latest 标签。固定到明确版本更容易回滚和排查,例如:
gpustack/gpustack:v2.2.3十三、排错顺序总结
遇到节点或模型部署异常时,可以按下面的顺序排查:
宿主机 nvidia-smi 是否正常?
↓
Docker 容器能否看到 GPU?
↓
Worker 容器是否正在运行?
↓
Server 与 Worker 版本是否一致?
↓
Worker 是否成功注册?
↓
Worker 上报的 IP 是否为真实局域网 IP?
↓
Server 与 Worker 是否双向连通?
↓
管理界面是否能看到 Worker 和 GPU?
↓
单个 Worker 的资源是否满足模型需求?这个顺序比一上来反复重装更有效。尤其当日志已经出现 Worker registered 时,应继续检查上报 IP、心跳、端口和 GPU Runtime,而不是把问题简单归结为“GPUStack 没有识别节点”。
结语
GPUStack 的价值不是把不同电脑上的显存无条件相加,而是把分散的 GPU 资源统一管理,并为上层应用提供一致的模型服务接口。
对于“12GB 主力卡 + 8GB 辅助卡”这样的家庭或个人工作站环境,最实用的方案是:主力显卡运行聊天、Coding 或 Agent 模型,辅助显卡运行 Embedding、Reranker 和小模型。这样两张显卡可以同时工作,部署也比跨节点拆分单个大模型稳定得多。