2026 Mac Mesh 共享建置池磁碟水位治理
DerivedData 清理與三層快取 Runbook

磁碟水位 · DerivedData / CocoaPods / Gradle · 產物三層 · 六步 Runbook · 硬閾值

2026 Mac Mesh 共享建置池磁碟水位與 DerivedData 治理

維運、行動端基礎建設與要為共享 Mac 建置池簽磁碟 SLO 的 Tech Lead常在週五晚上收到同一類告警:Runner 線上但 Job 因「No space left」失敗,DerivedData 佔滿系統磁碟區,CocoaPods 與 Gradle 全域快取無人認領,產物目錄在 rsync 成功後仍堆在本機。本文先界定誰遇到什麼問題:Mac Mesh 多租戶輪換下,磁碟不是「滿了再手工 rm」,而是缺可觀測水位 + 分層回收契約;再給出結論:用 L1 DerivedData / L2 依賴快取 / L3 CI 產物 三層水位線與六步 Runbook,把清理從救火變成可稽核例行;結構上交付五條隱性稅、清理策略對照表、水位腳本欄位、六步落地、三條硬閾值與 FAQ。席位與租約見 並發席位與互斥;映像漂移見 黃金映像清單;產物外送見 rsync 與物件儲存;池型容量見 三池 SLO 矩陣;多分支隔離見 Git worktree 隔離

01

共享建置池磁碟爆滿前最常見的五條「隱性稅」

2026 年 Mac Mesh 工單裡,磁碟問題很少是「少買了 100GB」這麼簡單。更多是在輪換租戶、快取局部性與產物生命週期之間缺統一契約,導致 APFS 看起來還有空間,Xcode 卻已經在寫暫存檔時失敗。

  1. 01

    DerivedData 無界共享:多儲存庫共用 ~/Library/Developer/Xcode/DerivedData,索引與模組快取按分支交錯,一次 clean 誤刪鄰居正在用的 ModuleCache,表現為隨機 link 失敗而非磁碟滿。

  2. 02

    CocoaPods / Gradle 全域快取無 TTL:~/Library/Caches/CocoaPods~/.gradle/caches 只增不減;Pods 版本升級後舊 tarball 仍佔數 GB,且與 worktree 多分支 並行時放大爭用。

  3. 03

    產物「已上傳仍留本機」:Job 在物件儲存側已成功,但 $CI_ARTIFACTS_DIR 未掛保留策略,與 rsync 完成鉤子 未綁定,磁碟被 IPA/dSYM 慢慢吃光。

  4. 04

    APFS 快照與「可用」誤導:本機快照讓 df 顯示餘量充足,真實可寫空間在編譯峰值時擊穿;缺少按磁碟區、按層的 waterline_used_pct 指標。

  5. 05

    清理與席位鎖競態:租約未釋放就掃目錄,或與 席位鎖 TTL 衝突,造成「磁碟清了、建置卻紅」的二次事故。

交付物應是:三層目錄字典、warn/hard 雙水位、按租約結束的 LRU、與黃金映像漂移週檢解耦。缺任一,就不應在共享池上承諾「任意 monorepo 可並行」。下一節用對照表比較三種常見清理哲學,避免「每週五全員 ssh 上去 rm -rf」。

02

對照表:手工清掃、水位守護與黃金映像重置怎麼選

磁碟治理不是越狠越好,而是要在建置命中率、清理可稽核性與租戶隔離之間取平衡。請把下表貼在變更評審頁:每一層(L1/L2/L3)只允許勾選一種預設策略。

策略L1 DerivedDataL2 Pods/GradleL3 產物適合主要風險
手工 cron週末 rm 全域目錄偶發 pod cache prune按天數 find 刪除極小團隊、低並行誤刪鄰居、不可稽核
水位守護行程按 workspace 雜湊 LRU容量觸線 evictrsync 成功後 48h共享池預設需指標與鎖契約
映像重置快照回滾清空隨映像刷新磁碟區級替換漂移失控、合規快照冷啟動編譯變慢

選型底線:共享池預設應選「水位守護」;映像重置只配合 黃金映像漂移清單 做季度兜底,不能取代日常 LRU。

Dedicated 獨占池 與 Shared 輪換並存時,L1 快取鍵必須帶池型標籤,否則獨占機的局部性收益會被共享池清掃腳本誤傷。

三層目錄建議(寫入 Runbook 附件)

L1/var/mesh/cache/deriveddata/{workspace_hash},綁定 Xcode DERIVED_DATA_DIRL2/var/mesh/cache/cocoapods/var/mesh/cache/gradle,禁止寫回使用者主目錄全域快取。L3/var/mesh/artifacts/{job_id},上傳成功後僅保留校驗旁路檔案。這樣監控可以按層回報 layer_*_bytes,而不是只有一個模糊的「/ 分割區 85%」。

03

六步 Runbook:從水位腳本到三層自動回收

以下六步假設 Runner 已接入 Mac Mesh 標籤,且席位在 Job 開始前 acquire、結束後 release。順序不要跳:沒有指標的水位線等於盲刪。

  1. 01

    凍結三層字典與路徑:把 L1/L2/L3 根目錄、warn(82%)/ hard(92%)閾值寫入儲存庫 mesh-disk-policy.yaml,並在 映像清單 中登記預設掛載點。

  2. 02

    部署 disk-waterline 探針:每 60s 採集磁碟區使用率與各層位元組數,上報 Prometheus/OpenTelemetry;hard 觸線時 Runner 進入 drain 並 fail-fast 新 Job。

  3. 03

    隔離 DerivedData:CI 注入 DERIVED_DATA_DIR 指向 workspace 雜湊桶;租約結束觸發該桶 LRU,禁止掃全域 DerivedData。

  4. 04

    L2 依賴快取 evict:CocoaPods 用 pod cache clean 封裝為「按容量」而非「按時間」;Gradle 啟用 GRADLE_USER_HOME 指向 mesh 目錄並限制 max-cache-size

  5. 05

    產物與 rsync 鉤子:物件儲存 multipart 完成事件回呼刪除本機 L3;失敗重試保留至 7 天,欄位與 產物 Runbook 對齊。

  6. 06

    週檢與演練:對照黃金映像 checksum、模擬 90% 水位下 Job 拒絕、記錄清理稽核日誌;與 Burst 溢出 聯動時先清 L3 再接納可中斷 Job。

disk-waterline 探針最小欄位
hostname
pool_type
volume_mount
waterline_used_pct
waterline_warn_threshold
waterline_hard_threshold
layer_l1_deriveddata_bytes
layer_l2_cocoapods_bytes
layer_l2_gradle_bytes
layer_l3_artifacts_bytes
seat_lease_id
last_cleanup_ts_unix
cleanup_evicted_bytes_1h
disk_waterline_hard_stop

提示:探針輸出應作為 Grafana 面板的第一行,而不是僅依賴系統告警。把 cleanup_evicted_bytes_1h 與成功建置數同圖,可區分「真清理」與「建置變少所以磁碟看似下降」。

04

症狀矩陣:磁碟告警時先判層還是先判池

磁碟告警與 佇列 SLO 症狀常重疊。先用下表定位是容量、快取鍵還是產物堆積,再決定清掃範圍。

症狀layer_* 主導可能根因優先動作
僅 Xcode 步驟失敗L1 高DerivedData 串味或索引損壞按 workspace 雜湊清桶
Android/iOS 混合池慢L2 高Pods/Gradle 無 evict收緊 L2 容量上限
上傳成功仍滿L3 高rsync 鉤子未綁補物件儲存回呼
df 正常但寫入失敗快照APFS 本機快照減快照保留 + 探針

注意:不要在持有 席位鎖 時執行磁碟區級 rm -rf。清理腳本必須檢查 seat_lease_id 為空或租約已過期,否則會把正在編譯的 ModuleCache 一併刪掉。

若 L1 在清桶後 24 小時內再次頂滿,優先審查是否缺少 worktree 隔離 導致同一節點並行多份全量 DerivedData,而不是繼續加碟。

05

三條硬閾值與可引用維運參數

下列數值來自多個 16GB/24GB 共享池現場的折衷,寫入變更單後可作為對外 SLO 的附件;獨占池可把 warn 下調 5 個百分點以換取更穩定的索引熱快取。

  • 雙水位:waterline_warn_threshold=82 觸發 L3→L2→L1 順序 evict;waterline_hard_threshold=92 拒絕新 Job 並打 disk_waterline_hard_stop=1
  • L1 最大駐留:共享池單 workspace 桶 14 天32GB 先到先刪;Dedicated 可放寬至 28 天但需獨占標籤。
  • L3 本機保留:rsync/上傳成功後 48 小時 內刪除;失敗佇列保留 7 天,超過則告警並人工覆核物件儲存側物件是否存在。

在 512GB 系統磁碟區、約 60% 預留給 mesh 的現場,L2 合計建議封頂 80GB(CocoaPods 與 Gradle 各 40GB 軟上限),L3 單 Job 目錄軟上限 12GB(含 dSYM)。把「僅 cron 週末清掃」或「全員 ssh 手工刪快取」當作長期方案時,往往缺少稽核欄位與席位契約,誤刪鄰居、編譯冷啟動激增、產物半寫入會在發布週集中爆發。對於要把 iOS/Android CI 與磁碟 SLO 落在可合約化雲端 Mac Mini 的團隊,VpsMesh 的 Mac Mini 雲端租用通常是更優解;方案見 定價頁面,接入與水位腳本樣例見 說明中心,訂購見 訂購頁面

常見問題

讀者最常問的三個問題

預設按 workspace 雜湊分桶 並綁定席位租約,租約結束觸發該桶 LRU。多分支並行見 worktree 隔離文;勿讓全域 ~/Library/Developer/Xcode/DerivedData 無界共享。

Runner 應 fail-fast 並上報 disk_waterline_hard_stop,避免半寫入產物;排程層把 Job 路由到有餘量的節點或觸發 Burst。席位語意見 並發席位文

要。磁碟清理只回收執行階段垃圾,不能取代 快照漂移清單。接入步驟見 說明中心,方案對比見 定價頁面