iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
IT Operation

地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理系列 第 9

Day 9|容量規劃:用模型與硬體搭配矩陣決定地端節點與儲存規格

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260923/20141816BVr4fj9R9Q.png

前言:第二段從「買之前要算什麼」開始

本系列前幾天講的是開源服務怎麼封裝到容器中,給伺服器或 NAS 跑,至於這些服務要跑在什麼機器上、機器夠不夠、儲存要多大,則是接下來的題目。我在前一個系列的 Day 16 回答的是「要選哪個模型」,選型的五個問題後來做成了 open-model-selector 這個工具。今天把同一個工具反過來用,模型清單是輸入,節點數、記憶體、儲存容量、網路頻寬是輸出。

維運的容量規劃跟選型有一個根本差別。選型可以一次選一個,容量規劃要算的是「同時」。哪幾個模型要同時常駐、幾個人同時用、每個人開多長的 context、模型庫一年會長到多大、新模型從 NAS 載進節點要多久。這些數字決定買幾台、買多大,也決定 Day 11 的守護要盯哪些邊界、Day 13 的儲存實測要量什麼、Day 30 的電費怎麼算。

文章依 open-model-selector 的 commit 03f126f 撰寫。這個 commit 把 data.js 的每個數字都補上來源,權重檔大小取自 Hugging Face 上的量化檔,KV cache 的每 token 成本改為依模型的 config.json 推導(BF16、只計全注意力層),查不到的欄位設為空值。前一版的 KV 值普遍低估好幾倍,今天的表如果用舊版算,結論會整個相反,這件事在本文後面的第二節會講。場域的設備清單見索引 repo 的 lab/inventory.md

一、容量規劃面面觀

問題 這個場域的答案 決定了什麼
有哪些工作負載 內部對話與 Agent 迴圈、長文與程式庫的 RAG、ComfyUI 圖像與影片生成、封裝測試 模型的形狀,MoE 或 Dense
尖峰時同時常駐幾個模型 一個對話用 MoE 加一個長文用 Dense,ComfyUI 另外一台 節點數與每台的記憶體
同時幾個 session、多長 context 五人團隊,尖峰 8 個 session,Agent 迴圈開 32k KV cache 的預算
模型庫多大、一年長多少 目前約 600 GB,每月新增兩到三個模型 NAS 容量與 Day 12 的清理規則
冷啟動可以等多久 對話服務 2 分鐘內,批次工作不限 節點與 NAS 之間的網路,以及哪些模型要放本機 SSD
電費與散熱的上限 一間有冷氣的辦公室,一個 20A 迴路或二個 15A 迴路 Day 11 的熱守護、Day 30 的一年成本

第一列的答案來自前一個系列,第三、四列是依團隊規模推的估計值,其他部分的計算請往下看囉。

二、一個節點裝得下什麼 ?

open-model-selector 的「能跑嗎」用的公式是這一行。

需要的記憶體 = 權重檔大小 + KV cache 每 token 成本 × context 長度 + 2 GB 執行期預留
完美暢跑     = 需要的記憶體 ≤ 0.85 × (可用記憶體 − 共存保留)

0.85 是給碎片與峰值的餘裕,2 GB 是 CUDA 或 Metal 執行期的固定開銷,兩個係數都是工具的預設值。KV cache 每 token 的成本依注意力架構差很多,同樣是 30B 上下的模型,傳統 GQA 的 Qwen2.5-Coder-32B 是 256 KB,混合注意力的 Qwen3.8-27B 只有 64 KB,DeepSeek-V4-Flash 的 MLA 只有 5.4 KB。

工具一次算一個模型一個 session。容量規劃要的是多 session 與多模型,把公式展開就是把 KV 項乘上 session 數、把多個模型的權重與預留加總。以下是 DGX Spark 128 GB 統一記憶體、不保留給其他程式、32k context 的結果,單機預算是 0.85 × 128 = 108.8 GB,兩台合計 217.6 GB。

模型與量化 權重 KV 每 session 1 session 合計 8 session 合計 單機 108.8 GB 內
gpt-oss-120b MXFP4 63.4 1.13 66.5 74.4
Llama-3.3-70B Q8_0 75.0 10.00 87.0 157.0 只到 3 session
Llama-3.3-70B Q5_K_M 49.9 10.00 61.9 131.9 只到 5 session
Ornith 1.5 35B-A3B Q8_0 37.8 0.63 40.4 44.8
Qwen2.5-Coder-32B Q8_0 34.8 8.00 44.8 100.8 是,餘 8 GB
Qwen3.8-27B Q8_0 29.0 2.00 33.0 47.0
DeepSeek-V4-Flash UD-Q4_K_XL 155.1 0.17 157.3 158.4 否,兩台合計內
DeepSeek-R1 UD-Q2_K_XL 226.6 2.14 230.7 245.8 否,兩台合計也超過

單位 GB,context 32,768 tokens,KV 以 BF16 計。

第一,KV cache 會不會成為瓶頸,看的是注意力架構,不是參數量。Llama-3.3-70B 每個 32k 的 session 要 10 GB,8 個 session 光 KV 就 80 GB,比 Q5 的權重還大,Qwen2.5-Coder-32B 的 8 個 session 要 64 GB。反過來,MoE 的 gpt-oss-120b 與 Ornith,以及混合注意力的 Qwen3.8-27B,8 個 session 只多 5 到 16 GB。選 Dense 模型做多人服務時,要先查它是不是傳統 GQA,是的話 session 數就是記憶體的主項。Ollama 的 OLLAMA_KV_CACHE_TYPE=q8_0 可以把 KV 減半,代價是另一個要驗的品質變數,今天的表不算它。

第二,工具前一版把這幾個模型的 KV 記成實際值的四分之一到十六分之一,用舊值算會得到「8 個 session 的 KV 在 Dense 上也只有幾 GB,不是瓶頸」的結論。這是用工具做容量規劃需要留意的,公式對不代表輸入對,每一個輸入要能追到來源。

第三,DeepSeek-V4-Flash 的總參數是 284B,4-bit 級就要 155 GB,單機放不下,兩台合計的 217.6 GB 預算內放得下,這正是前一個系列 Day 27 雙機合體的實驗平台。671B 的 DeepSeek-R1 連 Q2 都要 230 GB,超過兩台合計,不是這兩台機器的選項。雙機跨機執行的代價前一個系列 Day 27 實測過,它留給實驗,不進生產。

繁體中文有一條前一個系列量出來的限制,4-bit 量化在繁中的劣化是英文的 1.67 到 2.00 倍,所以對話與 Agent 用途從 8-bit 起跳,這也是上表多數列用 Q8_0 的原因。

兩個模型同時常駐

尖峰時要一個對話用的 MoE 加一個長文用的 Dense 同時在記憶體裡。先看它們能不能擠在同一台。

組合 每模型 session 數 合計 單機餘裕
gpt-oss-120b MXFP4 加 Qwen3.8-27B Q8_0 1 99.5 9.3
gpt-oss-120b MXFP4 加 Qwen3.8-27B Q8_0 2 102.7 6.1
gpt-oss-120b MXFP4 加 Qwen3.8-27B Q8_0 4 108.9 不足 0.1
gpt-oss-120b MXFP4 加 Ornith 1.5 Q8_0 1 107.0 1.8
gpt-oss-120b MXFP4 加 Qwen2.5-Coder-32B Q8_0 1 111.3 不足 2.5
gpt-oss-120b MXFP4 加 Llama-3.3-70B Q5_K_M 1 128.4 不足 19.6

單位 GB,32k context。

能擠的只有 gpt-oss 加 Qwen3.8,而且每個模型 2 個 session 就只剩 6 GB。這在工具上會亮綠燈,在維運上不能當平時的組態,Day 11 的記憶體守護門檻會比 6 GB 更早觸發。第二節的節點規則從這裡來。

Ollama 的 OLLAMA_MAX_LOADED_MODELSOLLAMA_NUM_PARALLEL 決定了同時載入幾個模型與每個模型幾個 session,這兩個值是 Day 8 設定檔裡的兩個鍵,容量規劃算出來的數字要寫回去。要注意 OLLAMA_NUM_PARALLEL 會讓 Ollama 依 context 長度乘上平行數配置 KV,設 4 就是一次保留 4 份 32k 的 KV,不是用到才長。

節點數的規則

節點數由「尖峰時要同時常駐的模型組合」決定,不由模型總數或總參數量決定。這個場域的常駐組合是兩個 LLM 加 ComfyUI,ComfyUI 在 Intel 工作站上,兩個 LLM 分在兩台 DGX Spark 上各一個,而非擠在一台。理由有三個,上表顯示擠在一台時每個模型只能給 2 個 session,一台掛掉另一台還在,Day 11 的熱守護降載時不會兩個模型一起變慢。

所以每台節點的設定是 OLLAMA_MAX_LOADED_MODELS=1OLLAMA_NUM_PARALLEL=4,兩台合計 8 個 session,符合第一節的尖峰。gpt-oss 那台 4 個 session 是 69.9 GB,Qwen3.8 那台是 39.0 GB,兩台都有 40 GB 以上的餘裕。

另外寫下降級組態。一台故障時把兩個模型擠到剩下那台,改成 OLLAMA_MAX_LOADED_MODELS=2OLLAMA_NUM_PARALLEL=2,總 session 從 8 降到 4,餘裕 6.1 GB。這是故障期間的暫時組態,要寫進 Day 26 的變更紀錄,修好後改回來。兩台的 100GbE 直連留給實驗與模型同步,不是生產路徑。

三、儲存:模型庫的大小與它會長多快

模型庫的容量不是「選定的模型加總」,有四個乘數。

項目 估算 說明
選定模型的量化檔 約 290 GB 上表前六列,gpt-oss、Llama 兩種、Ornith、Coder-32B、Qwen3.8
同一模型的第二種量化 約 100 GB 8-bit 給對話、4-bit 給共存型工作站
Ollama 的 blob 副本 約 165 GB Day 8 講過,Ollama 匯入 GGUF 會複製一份進自己的 blob 目錄,以生產的四個模型計
ComfyUI 的 checkpoint、VAE、LoRA 約 100 GB Day 7 的 <Public>/models
小計 約 655 GB 與第一節「目前約 600 GB」相近
雙機實驗用的 DeepSeek-V4-Flash 155 GB 一個實驗模型就是模型庫的四分之一

最後一列單獨列出,是因為它說明了模型庫會怎麼長。生產用的模型幾十 GB 一個,實驗用的大型 MoE 一個就上百 GB,模型庫的成長主要由實驗決定,不由生產決定。每月新增兩到三個模型,每個 20 到 150 GB,一年約 1 到 2 TB。Day 12 的清理規則會退掉被取代的版本,版本要保留幾代、退掉之前要留多久是那天要決定的事,今天先用「保留兩代」來估算,一年後的模型庫約 2 TB。

TS-464 是 4 bay 機種,在這系列,容量不是 NAS 的瓶頸,要看的是讀取速度,也就是往下會說明的部分。

什麼放 NAS,什麼放本機 SSD

前一個系列測試過一條規則,也就是這系列文章中使用工具的儲存決策頁內容。如果地端 AI 模型的檔案大小能夠塞進統一記憶體,那權重放 NAS 的代價只是冷啟動多十幾秒的一次性成本。放不進記憶體的模型則絕對不放 NAS,因為每一次分頁回收再讀取都走網路,最慘的案例總載入時間將慢 3.8 倍。第二條規則呢,是 loader 的磁碟依賴度,GGUF 走 mmap 的磁碟依賴達 73%,vLLM 載入後幾乎不再碰磁碟。

套用到這個場域。DGX Spark 上生產用的模型都放得進記憶體,全部從 NFS 載入,本機的 NVMe 只放 Ollama 的 blob 目錄與 KV cache 的溢出。Intel 工作站的 RTX 5060 Ti 只有 16 GB,跑 Qwen2.5-Coder-32B Q4_K_M 的 19.9 GB 會部分卸載到 CPU,這台的模型要放本機 SSD。AMD 工作站的 RTX 3060 12 GB 同理。

四、網路:冷啟動的時間由最慢的一段決定

模型從 NAS 載入節點的時間是檔案大小除以有效頻寬。以線速的 85% 估有效頻寬。

鏈路 有效頻寬 63.4 GB(gpt-oss-120b) 34.8 GB(Coder-32B Q8)
2.5GbE 0.27 GB/s 239 秒 131 秒
10GbE 1.06 GB/s 60 秒 33 秒
100GbE 10.6 GB/s 6 秒 3 秒

第一節說對話服務的冷啟動要在 2 分鐘內。TS-464 的內建網路是兩個 2.5GbE 埠,走它載入 gpt-oss 要 4 分鐘,不合格。這個場域的 TS-464 已在 PCIe 插槽裝了 QNAP 的 QXG-10G1T,單埠 RJ45 的 10GbE 網卡,接上 10GbE 交換器之後估算是 60 秒,合格。兩台 DGX Spark 各自接 10GbE 交換器,節點端不是瓶頸。100GbE 只在兩台 DGX Spark 之間,NAS 不在那條線上,所以第三列對載入時間沒有幫助。

換成 10GbE 之後,網路不再是上限,瓶頸往後移了兩段。一是 TS-464 的碟組能不能持續餵出 1 GB/s 的循序讀,四顆硬碟的 RAID 5 速度是夠的。其二是 NFS 的單一連線,沒有開 nconnect 時單一 TCP 連線不一定跑得滿 10GbE。這台機器採用的網路卡 QXG-10G1T 是五速網卡,10、5、2.5、1GbE 都能協商,線材或交換器埠不對時它會安靜地降到 5GbE 或 2.5GbE,連線照樣通,只是載入時間回到上表的第一列附近,所以要看實際協商的速度,不能只看燈號。

這一節的數字是估算,Day 13 會在同一批設備上實測 SSD、NFS、iSCSI 三條路徑的載入時間,估算與實測的差距會回寫到這裡。

五、電力與熱

DGX Spark 的規格頁寫電源供應器 240 W,GB10 的 TDP 140 W,兩在規格上最大合計 480 W,實際上用不到這麼多電。我在前一個鐵人賽系列文中有寫過,在兩台的牆插上接了電力計,雙機 tensor parallel 滿載時兩台合計 327.77 W,常駐閒置 108.63 W,實測滿載約是銘牌的七成。

TS-464 的規格頁寫的是裝滿硬碟時典型運作 40.5 W、硬碟待機 21.6 W,電源變壓器 90 W。三台 Proxmox VE 節點是 Intel 處理器加 DDR4 記憶體,權衡以 200 W 估算。Intel 搭配 Nvidia 顯示卡的 AI 算力工作站含 RTX 5060 Ti 約 300 W、網路設備約 50 W,同樣是估值。DGX Spark 與 TS-464 取規格上限、其餘取估值,全部約 1,120 W,DGX Spark 改用實測、TS-464 改用典型值,約 920 W。一個 15A 的 110V 迴路是 1,650 W,這個環境設置了雙迴路用電,以及備用的迴路一個,整體夠用,但空調要另算。

電費以外,熱是另一條邊界。前一個系列遇過 GB10 在熱浸透之後跑滿載整台斷電,不留核心日誌,降功耗也避不開,這是 Day 11 熱守護要處理的事。Day 11 的取樣器會記 DGX Spark 的實際功耗與溫度,Day 30 用實際數字算一年電費。

六、把它寫成文件

容量規劃的產出是一份文件,這份文件在 Day 26 談變更管理時是變更單的附件,任何新增模型、調整 OLLAMA_MAX_LOADED_MODELS、換 NAS 網卡的變更,均能去對照它。放在索引 repo 的 lab/capacity-plan.md,欄位如下。

欄位 內容
版本與日期 每次變更遞增
資料來源 open-model-selector 的 commit,換版本就要重算
工作負載清單 第一節的表
常駐模型組合 每台節點的模型、量化、OLLAMA_MAX_LOADED_MODELSOLLAMA_NUM_PARALLEL,以及降級組態
記憶體預算 第二節的表,含 0.85 與 2 GB 兩個係數
儲存預算 第三節的表,含一年成長估計與保留代數
網路預算 第四節的表,含冷啟動的目標時間
電力預算 第五節的銘牌值與實測值,Day 30 全部換成實測值
已知的未實測項 NAS 碟組與 NFS 的實際載入速度、NAS 網卡的實際協商速度、Proxmox VE 節點與工作站的實際功耗、團隊的實際 session 數

「資料來源」與「已知的未實測項」是這份文件最重要的兩列。今天的第二節就是例子,工具換一個 commit,同一個公式算出相反的結論。每一個估算值旁邊寫清楚它是估的還是量的、依據哪個版本、量的寫在哪一天量的。Day 13 與 Day 30 會各回來填一次。

怎麼跑

用工具重算第二節的任何一列。

git clone https://github.com/ivanusto/open-model-selector && cd open-model-selector
git checkout 03f126f
python3 serve.py

在瀏覽器裡到「能跑嗎?」分頁,硬體選 NVIDIA GB10,context 設 32k,模型與量化逐一選,讀所需記憶體。多 session 與多模型的合計工具還沒有,用下面這段算,公式與工具相同,數字取自 data.jssizeGBkvPerTokKB

python3 - <<'EOF'
# (權重 GB, KV KB/token) 取自 data.js @ 03f126f
models = {"gpt-oss-120b MXFP4": (63.4, 36), "Qwen3.8-27B Q8_0": (29.0, 64)}
ctx, sessions, budget = 32768, 2, 128 * 0.85
total = sum(w + kv * ctx / 1048576 * sessions + 2 for w, kv in models.values())
print(f"total {total:.1f} GB, budget {budget:.1f} GB, headroom {budget - total:.1f} GB")
EOF
# total 102.7 GB, budget 108.8 GB, headroom 6.1 GB

在 NAS 上看目前模型庫的大小與網卡。

du -sh /share/Public/models /share/CACHEDEV1_DATA/OpenWebUIOllama/ollama
for i in /sys/class/net/eth*; do echo "$(basename $i) $(cat $i/speed 2>/dev/null) Mb/s"; done

下指令後第二行會看到一個 10000 Mb/s 的介面,那是 QXG-10G1T。若顯示 5000 或 2500,就是協商降速了,這樣的話,你會需要查線材與交換器埠。而本環境中,AI 算力節點的 NFS 掛載要指向這個介面的位址。

明天

Day 10 先插一個這兩台機器上的真實案例,節點基線移到 Day 11。今天算出來每台節點要常駐什麼、開幾個 session,明天從 DGX OS 的初始設定、帳號與 SSH 加固開始,把兩台機器整成一樣的狀態,之後本系列文章後據的守護與指標收集才有一致的對象可以測試。


系列文章與程式碼索引:onprem-ops-30days

本日程式碼:open-model-selector @ 03f126f

參考資料


上一篇
Day 8|案例實戰:Open WebUI + Ollama 重構記,把專案回到通用框架會省下什麼呢?
下一篇
Day 10|上游引擎一改版,地端 AI 環境用的配方壞了怎麼辦 ? patch 移植實戰紀錄
系列文
地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言