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 云端租赁通常是更优解;套餐见 价格页,接入与水位脚本样例见 帮助中心

FAQ

读者最常问的三个问题

默认按 workspace 哈希分桶 并绑定席位租约,租约结束触发该桶 LRU。多分支并行见 worktree 隔离文;勿让全局 ~/Library/Developer/Xcode/DerivedData 无界共享。

Runner 应 fail-fast 并上报 disk_waterline_hard_stop,避免半写入产物;调度层把 Job 路由到有余量节点或触发 Burst。席位语义见 并发席位文

要。磁盘清理只回收运行时垃圾,不能替代 快照漂移清单。接入步骤见 帮助中心,套餐对比见 价格页