共计 3746 个字符,预计需要花费 10 分钟才能阅读完成。
最近大模型本地化部署非常火热,不少折腾 NAS 的极客顺理成章地打起了私有化部署的主意——把 Intel 12/13 代带核显的 NAS 节点或者塞了一张半高亮机卡(如 RTX 3050 6G / Tesla P4)的自建全闪 / 混闪小主机,改造成 24 小时待命的私人大模型推理与 RAG 知识库节点。但真上手跑起来,多数人遇到的不是体验 AI 的快感,而是一连串崩溃:并发向量化时机械硬盘咯咯作响无法休眠、Docker 容器悄无声息被 Linux OOM Killer 干掉,甚至核显驱动压根没透传成功,全靠 CPU 软跑把功耗拉满风扇起飞。
一、架构分层:别让向量库毁了你的机械阵列
在动手写 docker-compose.yml 之前,必须在物理存储与内存规划上划清界限。很多朋友直接在机械硬盘的共享目录下建了个 docker_data 卷,接着把 Ollama、Qdrant/Milvus 和 Open WebUI 全塞进去。这是严重的架构硬伤。
本地 RAG 系统在切片写入(Ingestion)和语义检索阶段,向量数据库(如 Qdrant)会产生海量微小的高频随机读写(WAL 机制与 HNSW 索引更新)。如果这个目录落在 ZFS 或 Btrfs 的机械硬盘池里,阵列磁头会处于持续寻道状态,NAS 硬盘休眠机制彻底失效,功耗飙升且极易缩短盘片寿命。
黄金挂载原则:
- 模型权重(Large Blobs): 可存放在 SATA SSD 或单挂的读取盘上,模型只在加载进显存 / 内存时发生顺序大文件读取。
- 向量数据库与 SQLite(Hot Data): 必须强制绑定在 NVMe SSD 存储池(系统盘或独立高速卷),绝不给 HDD 阵列带来寻道压力。
- 原始文档(Cold Data):PDF、Markdown、电子书归档存放在 NAS 机械大容量存储池中,按需按块读取。
二、生产级 Docker 编排:Ollama + Qdrant + Open WebUI
这里给出一套经过实测的生产级编排文件,集成了硬件加速设备挂载、健康检查以及最核心的 deploy.resources 资源边界。以集成 Intel 核显(第 10-14 代常见核显 UHD 730/770)的 Linux/Debian/TrueNAS 环境为例:
version: '3.8'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama-service
restart: unless-stopped
devices:
- /dev/dri:/dev/dri # 透传 Intel 核显,启用 i915 硬件加速
volumes:
- /mnt/nvme-pool/docker/ollama:/root/.ollama
environment:
- OLLAMA_KEEP_ALIVE=10m # 10 分钟无请求自动释放显存 / 内存
- OLLAMA_NUM_PARALLEL=2 # 限制并发分支,防止显存与内存打架
- OLLAMA_FLASH_ATTENTION=1 # 开启 Flash Attention 降低显存占用
networks:
- ai-internal
deploy:
resources:
limits:
memory: 14G # 严格限制内存边界,留足系统安全边际
qdrant:
image: qdrant/qdrant:v1.8.4
container_name: qdrant-vector
restart: unless-stopped
volumes:
- /mnt/nvme-pool/docker/qdrant/storage:/qdrant/storage:z
networks:
- ai-internal
deploy:
resources:
limits:
memory: 4G # 防止索引暴走吃满内存
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
ports:
- "3000:8080"
volumes:
- /mnt/nvme-pool/docker/open-webui:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- VECTOR_DB=qdrant
- QDRANT_URL=http://qdrant:6333
- RAG_EMBEDDING_ENGINE=ollama
- RAG_EMBEDDING_MODEL=bge-m3:latest
- CHUNK_SIZE=1000
- CHUNK_OVERLAP=100
networks:
- ai-internal
depends_on:
- ollama
- qdrant
networks:
ai-internal:
driver: bridge
如果你给 NAS 插了 NVIDIA 独显(例如低功耗的 T400、GTX 1650 或半高 RTX 3050),需要将 devices 替换为标准的 deploy.resources.reservations.devices GPU 驱动透传块,并确保底层已经安装 nvidia-container-toolkit。
三、核心调优:核显 / 显卡驱动透传与验证
许多人在挂载 /dev/dri 后,自以为万事大吉,实测发现推理依旧是全核 CPU 飙到 100%。Ollama 对 Intel 核显的利用在 Linux 下依赖于 OneAPI/Level Zero 运行时或者 Vulkan 后端。在容器启动后,务必直接通过命令验证驱动与设备分配情况:
# 查看 NAS 宿主机核显权限
ls -la /dev/dri
# 正常应输出 card0, renderD128。若 renderD128 权限受限,执行:sudo chmod 666 /dev/dri/renderD128
# 进入 Ollama 容器内部查看加载情况
docker exec -it ollama-service /bin/sh -c "ls -l /dev/dri"
# 实时监测 Intel GPU 负载(宿主机需安装 intel-gpu-tools)sudo intel_gpu_top
运行 intel_gpu_top 时,随便拉一个 qwen2.5:7b-instruct-q4_K_M 模型执行一条生成命令。如果在 Render/3D 或 Compute 栏位看到了明显的利用率(如 40%~85%),说明硬加速成功起效;若依旧空空如也,则代表当前 Ollama 版本对该型号架构调用了纯 CPU 线程进行推演。
四、防爆内存:降服 Linux OOM Killer 与虚拟内存策略
在普通服务器上跑爆内存顶多容器重启,但在集成 NAS 系统(如 TrueNAS、Unraid 或跑了软路由的一体机)上,内存用尽引发的内核级 OOM Killer 可能会无差别杀掉你的 ZFS ARC 监控、Samba 服务乃至 Docker Daemon,导致存储挂载断开、网络掉线。
1. 锁死 Linux OOM 优先级,保护宿主机服务
我们绝对不能让核心服务被干掉。可以通过调整 Docker 进程或模型的 OOM 优先级,让 Linux 在被迫开枪时优先干掉大模型推理容器,保全 NAS 的基础存储生命线:
# 查看当前 ollama 容器的主 PID
CONTAINER_PID=$(docker inspect --format '{{ .State.Pid}}' ollama-service)
# 提高该容器被杀的倾向(取值 -1000 到 1000,越大越容易被当成牺牲品)# 将其调为 800,确保宿主机系统组件(如 smbd、sshd)安全
echo 800 | sudo tee /proc/$CONTAINER_PID/oom_score_adj
2. Swappiness 与 ZFS ARC 的协调
如果你的 NAS 运行着 ZFS,ZFS ARC 缓存默认可能会吃掉 50% 甚至更多内存。而 Ollama 进行矩阵计算时需要大块连续物理内存。当两方冲突时,如果系统启用了过大的 Swap 换页,整个系统会直接卡死进 I/O 阻塞态。
建议将内核 Swappiness 压低,并在 SSD 上设置小额应急 Swap:
# 修改宿主机 sysctl 配置
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
五、选型与性能实测建议
在消费级 NAS 上运行本地大模型与 RAG 知识库,模型参数选型必须“量体裁衣”:
- Embedding 模型优先选小型量化版: 千万不要无脑上
bge-large。推荐实测表现极为均衡的bge-m3:latest或nomic-embed-text。前者多语言能力极强且向量维度适配绝大多数切片场景,在纯 CPU 上的嵌入延迟也可以控制在毫秒级。 - RAG 召回阶段控制 Context 上下文:Open WebUI 默认的上下文窗口往往很大,在
OLLAMA_NUM_CTX设置为 8192 或更大时,KV Cache 对内存的消耗呈阶梯级上升。在 NAS 资源受限(32G 内存以下)场景中,建议在 Open WebUI 模型设置中将Context Length压在 4096,此时每轮问答的内存抖动会从 8GB 断崖式下跌至 2.5GB 左右。 - 模型量化尺寸选择: 对于 Intel 8 核 CPU 或单卡 6G/8G 显存,主力模型死守 Q4_K_M 量化标准的 7B/8B 模型(如
qwen2.5:7b或llama