本地AI实验室从零到精通:IT大叔的多节点分布式AI架构完全手册

本地AI实验室从零到精通:IT大叔的多节点分…

本地AI实验室从零到精通:IT大叔的多节点分布式AI架构完全手册

教程看了、Ollama装了、ComfyUI跑了,结果显存爆了、内存炸了、模型加载慢到怀疑人生——不是你不行,是架构没想清楚。这篇把一台服务器到多节点集群的完整思路和实操全给你。


一、先泼冷水:一台机器扛所有AI服务,大概率翻车

写这个标题之前,我已经踩过不止一次坑。

最初的想法很简单——一台主力机,插两块显卡,Docker Compose 一把梭,Ollama、ComfyUI、RAG 知识库、Whisper 语音识别全塞进去。结果呢?

  • 显存争夺:ComfyUI 生图吃到 12GB 显存,Ollama 推理立刻开始 swap
  • PCIe 瓶颈:两块显卡抢 PCIe 通道,带宽砍半
  • 内存溢出:Embedding 模型 + 向量数据库 + ComfyUI 节点缓存,32GB 内存直接干满
  • 磁盘 IO 打架:模型加载、ComfyUI 缓存、数据库写入抢同一块 SSD

解决方案不是「再买一台」,而是 把服务拆开,分散到不同节点。下面是我跑了三个月验证过的架构。


二、硬件选型:别拿游戏机当服务器

很多人的误区是拿自己打游戏的主机跑 AI 服务。不是不行,但性能损失大、稳定性差。

核心原则

  • 显存是第一生产力:推理/生图都吃显存,显存不够一切免谈
  • PCIe 通道数决定多卡效率:消费级主板插两张卡,第二张大概率 x4/x8 而非 x16
  • 内存容量决定并发上限:除了推理,还有 embedding、缓存、系统开销

我的推荐配置

角色 CPU GPU 内存 存储 场景 推理节点 4核+ 1×24GB+ 32GB 512GB NVMe Ollama / vLLM 生图节点 6核+ 1×16GB+ 32GB 256GB NVMe ComfyUI 服务节点 2核 无所谓 16GB 256GB SSD RAG、数据库、反向代理 存储节点 2核 无所谓 8GB 大容量 HDD/阵列 NAS 级存储

如果只有一台机器:至少 64GB 内存 + 1×24GB 显存,用 Docker 限制每个服务的最大资源,务必给每个容器设置 –memory 和 –cpus


三、操作系统与虚拟化:PVE 是最好选择

用裸机 Linux 跑也行,但一旦要加机器、迁移服务、备份整机,Proxmox VE (PVE) 的好处就出来了。

为什么选 PVE

  • 快照回滚:装 ComfyUI 插件前打个快照,炸了秒回
  • 迁移无忧:服务从一台搬到另一台,在线热迁移
  • 资源超分:AI 服务不是 24×7 满载,可以超分 CPU/内存
  • 嵌套 Docker:PVE 里开 LXC 或 VM 跑 Docker,隔离性好,爆了不影响宿主机

我的 PVE 规划

PVE Cluster

├── 推理节点 VM (4核/32GB/512GB) → Ollama + Open WebUI

├── 生图节点 VM (6核/32GB/256GB) → ComfyUI + Stable Diffusion

├── 服务节点 LXC (2核/16GB/200GB) → Caddy + PostgreSQL + Redis

└── NAS 容器 → TrueNAS Scale 或 直接 NFS 共享

关键操作:给 AI 推理的 VM 开启 PCIe Passthrough,把显卡直通给 VM,避免虚拟化层损耗。

# 查看显卡 IOMMU 分组

lspci -vnn | grep -i nvidia

# 在 PVE 的 /etc/default/grub 开启 IOMMU

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

# 更新 grub 后重启

update-grub && pve reboot


四、Docker 编排:别再一个 docker-compose.yml 管所有

每类服务应该有自己的 compose 文件,通过网络相互通信。

标准的目录结构

/opt/docker/

├── ollama/

│ ├── docker-compose.yml

│ └── volumes/

├── comfyui/

│ ├── docker-compose.yml

│ └── volumes/

├── caddy/

│ ├── docker-compose.yml

│ ├── Caddyfile

│ └── data/

├── postgres/

│ ├── docker-compose.yml

│ └── data/

└── vllm/

├── docker-compose.yml

└── models/

Ollama 节点的 docker-compose.yml

version: '3.8'

services:

ollama:

image: ollama/ollama:latest

container_name: ollama

restart: unless-stopped

ports:

  • "11434:11434"

volumes:

  • ./volumes/ollama:/root/.ollama

deploy:

resources:

reservations:

devices:

  • driver: nvidia

capabilities: [gpu]

count: 1

environment:

  • OLLAMA_NUM_PARALLEL=2
  • OLLAMA_MAX_LOADED_MODELS=1

open-webui:

image: ghcr.io/open-webui/open-webui:main

container_name: open-webui

restart: unless-stopped

ports:

  • "3000:8080"

volumes:

  • ./volumes/open-webui:/app/backend/data

environment:

  • OLLAMA_BASE_URL=http://ollama:11434

关键优化

  • OLLAMA_NUM_PARALLEL=2:限制并行请求数,避免显存炸裂
  • OLLAMA_MAX_LOADED_MODELS=1:一次只加载一个模型,切换模型自动卸载
  • 给 ComfyUI 也加上类似限制,--max-memory 不要超过显存的 85%

五、网络互连:跨节点服务怎么通信

多节点之间用 Docker overlay 网络Tailscale/WireGuard 打通内网。

方案一:Tailscale(最省心)

# 每个节点安装 Tailscale

curl -fsSL https://tailscale.com/install.sh | sh

tailscale up

# 所有节点加入同一个 Tailnet,自动分配 100.x.x.x 地址

# 容器里通过 100.x.x.x:端口 直接访问其他节点

方案二:WireGuard(全内网场景)

在 PVE 宿主机上配置 WireGuard,每个 VM 通过宿主机转发。

# 服务节点配置 Caddy 反向代理

cat > /opt/docker/caddy/Caddyfile << 'EOF'

ai.internal.lab {

reverse_proxy 100.64.0.2:11434 # 推理节点

}

draw.internal.lab {

reverse_proxy 100.64.0.3:8188 # 生图节点

}

EOF

方案三:K3s / Nomad(进阶用户)

如果节点超过 3 台,直接上 K3s 轻量 Kubernetes,用 Service 发现和 Ingress 统一入口。


六、模型管理:别一口气下一堆模型

这是最常见的坑——看到 HuggingFace 上有人说这个模型好就下,那个也不放过。结果 500GB 硬盘一周就满了。

我的模型选择策略

场景 推荐模型 显存需求 模型大小 日常对话/代码 Qwen2.5-7B-Q4 ~6GB 4.5GB 文档分析/长上下文 Qwen2.5-14B-Q4 ~10GB 8GB 编程/逻辑推理 DeepSeek-Coder-V2-Lite-Q4 ~8GB 6GB 轻量快速回复 Qwen2.5-3B-Q4 或 Llama-3.2-3B-Q4 ~3GB 2GB

不要超过手里的显存上限去跑大模型。14B 模型如果只有 8GB 显存,强行加载会切到 CPU 推理,速度慢 10 倍以上。

模型热切换技巧

在 Open WebUI 里配置多个模型,让用户根据场景手动选择。后台用 ollama run 时,Ollama 会自动卸载闲置模型。

# 查看当前已加载模型

curl http://localhost:11434/api/tags

# 手动卸载模型释放显存

ollama stop qwen2.5:7b


七、ComfyUI 工作流优化:生图更快、不爆显存

ComfyUI 是显存大户,尤其是用了 ControlNet、IP-Adapter、Tiled VAE 这些节点后。

必装节点

  • ComfyUI-Manager:装插件、更新、管理一键搞定
  • Tiled VAE:高分辨率生图时,把 VAE 解码分块处理,显存占用从 12GB 降到 3GB
  • Efficient Loader:一键切换模型和 VAE,避免手动改配置

启动参数优化

# ComfyUI 容器启动命令

python main.py --listen 0.0.0.0 --port 8188 \

--highvram # 如果你有 24GB+ 显存

# --lowvram # 如果显存 <= 8GB,用低速模式

# --novram # 只有 4GB 显存时,全部用系统内存(极慢)

工作流设计原则

1. 先低分辨率出图,再用 Tiled Upscale:直接出 1024×1024 比先出 512×512 再放大,显存占用高 3 倍

2. ControlNet 只开必要的:一个 ControlNet 大约吃掉 2-3GB 额外显存

3. Batch Size 别贪:batch=1 最稳,batch=2 显存翻倍,收益不大


八、性能监控:知道瓶颈在哪才能优化

没有监控就像闭着眼睛开车。部署完成后,第一时间搭建监控。

最简单的方案:netdata + cAdvisor

# netdata 一键监控系统资源

bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# cAdvisor 监控容器资源

docker run -d --name cadvisor \

-p 9110:8080 \

-v /var/run/docker.sock:/var/run/docker.sock:ro \

-v /sys:/sys:ro \

-v /var/lib/docker/:/var/lib/docker/:ro \

gcr.io/cadvisor/cadvisor:latest

需要重点关注的指标

指标 阈值 超标时的影响 GPU 显存使用率 < 85% 超了会 OOM 或切 CPU GPU 温度 < 80°C 超过会降频,推理速度暴跌 系统 Swap 0 一旦开始 swap,响应时间从秒变分钟 磁盘 IO Wait < 5% 模型加载和写入卡顿

九、数据备份:别等炸了才想起

AI 服务的数据远比系统本身珍贵——模型配置、工作流、数据库里的对话记录、RAG 知识库。

我的备份策略

# 每天凌晨 3 点,自动备份关键数据到 NAS

0 3 * * * /opt/scripts/backup-ai-data.sh

备份脚本核心逻辑:

#!/bin/bash

BACKUP_DIR="/mnt/nas/backups/ai-$(date +%Y%m%d)"

mkdir -p $BACKUP_DIR

# Ollama 模型列表和配置

ollama list > $BACKUP_DIR/models.txt

# ComfyUI 工作流和自定义节点

tar czf $BACKUP_DIR/comfyui-workflows.tar.gz /opt/docker/comfyui/volumes/

# 数据库

docker exec postgres pg_dump -U user -d ragdb > $BACKUP_DIR/ragdb.sql

# 保留最近 7 天,删除更早的

find /mnt/nas/backups/ -name "ai-*" -mtime +7 -exec rm -rf {} \;


十、避坑清单:我交过的学费都列在这里

1. 不要用消费级 SSD 当系统盘+模型盘 — 模型反复加载会快速磨损 TLC 颗粒,建议系统用 Optane 或企业级 U.2

2. Docker 日志不限制 — 默认日志驱动不限制大小,跑一个月日志文件能吃掉几十 GB。加 --log-opt max-size=10m --log-opt max-file=3

3. Ollama 默认不加 CORS — 跨节点调用时必须配置 OLLAMA_ORIGINS=*

4. ComfyUI 不设置 –listen — 默认只监听 localhost,跨节点访问需要手动改

5. PVE 不配置 IOMMU 就装 GPU Passthrough — 装好发现透传不了,又要重启重配

6. 不做 Swap 限制 — 系统认为可以用 swap,实际 AI 推理 swap 后慢到不可用

# 关闭所有 swap

swapoff -a

# 或者设置 vm.swappiness=1

echo "vm.swappiness=1" >> /etc/sysctl.conf


十一、常见问题排雷(实战 FAQ)

Q1:Ollama 响应特别慢,有时候十几秒才回复

排查顺序:先查显存,再看模型大小,最后看是否在 swap。

# 第一步:看显存是不是爆了

nvidia-smi --query-gpu=memory.used,memory.total --format=csv

# 第二步:看是否在用 swap

free -h

# 第三步:看加载的模型是否太大

curl http://localhost:11434/api/tags

大概率是显存不足导致切 CPU 推理。解决方案:换 Q4 量化的小模型(如 Qwen2.5-7B-Q4),或者加一块显卡做负载分担。

Q2:ComfyUI 生图到一半报 CUDA Out of Memory

最直接的原因:显存碎片化。连续生图多次后,显存里的缓存没有被彻底清理。

# ComfyUI 重启前先清理显存缓存

sudo fuser -v /dev/nvidia0

nvidia-smi --gpu-reset # 慎用,会杀掉所有 GPU 进程

# 更温和的方式:在 ComfyUI 节点里加一个定时清理脚本

更根本的解决方案:换 Tiled VAE 分块处理,或者降分辨率到 768×768 先用,再看效果决定是否放大。

Q3:Open WebUI 连不上 Ollama

三步定位法:

# 1. 容器内部能通吗?

docker exec open-webui curl http://ollama:11434/api/tags

# 2. 宿主机能通吗?

curl http://localhost:11434/api/tags

# 3. 跨节点能通吗?(替换为实际 IP)

curl http://100.64.0.2:11434/api/tags

哪一步不通,问题就在哪一层。最常见原因:Docker 网络没配置对,或者 OLLAMA_HOST 没设置成 0.0.0.0

Q4:PVE 里 GPU 透传后 VM 启动报错

# 检查 IOMMU 是否开启

dmesg | grep -i iommu

# 检查显卡是否在独立的 IOMMU 组

find /sys/kernel/iommu_groups/ -type l | grep 0000:0

# 如果跟其他设备绑在一个组里,需要 ACS 补丁或调整 PCIe 槽位

Q5:docker-compose up 报 port already allocated

90% 的情况是之前退出没清理干净:

# 看谁占了端口

ss -tlnp | grep 11434

# 停掉旧容器

docker stop ollama && docker rm ollama

# 或者换端口映射


十二、写在最后

这套架构我跑了三个月,从一台服务器到三台节点,从裸机 Linux 到 PVE 集群,从一个人本地玩到能稳定服务全家。

最大的感受是:AI 能力的瓶颈从来不是模型本身,而是你愿不愿意花时间把基础设施搭扎实。

如果刚开始,只做两件事:

1. 一台机器先跑 Ollama + Open WebUI

2. 加一台机器(或二手工作站)跑 ComfyUI

两个节点之间用 Tailscale 打通,比堆在一台机器上好十倍。等觉得管理起来麻烦了,再上 PVE + Docker 编排。


*如果你正在搭建本地 AI 环境,有踩坑经历或者好方案,欢迎在评论区分享。大叔会挑有价值的问答整理成后续文章。*

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注