2026 年 Mac Mesh 共有ビルドプールのディスク水位管理
DerivedData クリーンアップと 3 層キャッシュ Runbook

ディスク水位 · DerivedData / CocoaPods / Gradle · 3 層成果物 · 6 ステップ 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 成果物の 3 層水位線と 6 ステップ Runbook で、清掃を火消しから監査可能な定例へ移します。構成は5 つの隠れコスト、清掃戦略対照表、水位スクリプト項目、6 ステップ実装、3 つのハードしきい値、FAQです。シートとリースは 並行シートとミューテックス、イメージドリフトは ゴールデンイメージ一覧、成果物は rsync とオブジェクトストレージ、プール容量は 3 プール SLO マトリックス、多ブランチは Git worktree 分離を参照してください。

01

共有ビルドプールがディスク満杯になる前に見られる 5 つの「隠れコスト」

2026 年の Mac Mesh チケットでは、ディスク問題は「100GB 足りない」だけではありません。テナントローテーション、キャッシュ局所性、成果物ライフサイクルの間に統一契約がなく、APFS 上は空きがあるのに Xcode の一時書き込みが失敗するケースが多いです。

  1. 01

    DerivedData の無境界共有:複数リポジトリが ~/Library/Developer/Xcode/DerivedData を共有し、インデックスと ModuleCache がブランチで交錯。clean 1 回で隣接テナントの ModuleCache を誤削除し、ディスク満杯ではなくランダムな link 失敗として現れます。

  2. 02

    CocoaPods / Gradle グローバルキャッシュに TTL なし:~/Library/Caches/CocoaPods~/.gradle/caches が増え続ける。Pods 更新後も旧 tarball が数 GB 残り、worktree 多ブランチと並行すると争用が拡大します。

  3. 03

    「アップロード済みだがローカル残留」:オブジェクトストレージ側は成功したのに $CI_ARTIFACTS_DIR に保持ポリシーがなく、rsync 完了フック未連携で IPA/dSYM がディスクを消費します。

  4. 04

    APFS スナップショットと「空き」の錯覚:ローカルスナップショットで df は余裕に見えるが、コンパイルピークで実書き込みが破綻。ボリューム・層別の waterline_used_pct が欠けます。

  5. 05

    清掃とシートロックの競合:リース未解放でディレクトリを掃引、または シートロック TTL と衝突し、「ディスクは空いたがビルドは赤」の二次障害になります。

成果物は 3 層ディレクトリ辞書、warn/hard 二重水位、リース終了時 LRU、ゴールデンイメージ週次ドリフト検査との分離です。いずれか欠ければ共有プールで「任意 monorepo 並行」を約束すべきではありません。次節は 3 つの清掃哲学を対照し、「毎週金曜に全員 ssh で rm -rf」を避けます。

02

対照表:手動清掃、水位ガード、ゴールデンイメージリセットの選び方

ディスク運用は「強ければよい」わけではなく、ビルドヒット率、清掃の監査可能性、テナント分離のバランスです。変更レビューに下表を貼り、各層(L1/L2/L3)でデフォルト戦略は 1 つだけにしてください。

戦略L1 DerivedDataL2 Pods/GradleL3 成果物向くケース主なリスク
手動 cron週末にグローバル rmたまの pod cache prune日数ベース find 削除極小チーム・低並行隣接誤削除・監査不可
水位ガードworkspace ハッシュ LRU容量閾値で evictrsync 成功後 48h共有プール既定指標とロック契約が必要
イメージリセットスナップショット巻き戻しイメージ更新に追随ボリューム置換ドリフト失控・コンプライアンスコールドスタート遅延

選定の原則:共有プールの既定は「水位ガード」。イメージリセットは ゴールデンイメージドリフト一覧 と組み合わせた四半期フォールバックのみで、日常 LRU の代替にはなりません。

Dedicated 専有プール と Shared ローテーションが共存する場合、L1 キャッシュキーにプール種別タグが必要です。ないと専有ノードの局所性が共有プール清掃で損なわれます。

3 層ディレクトリ案(Runbook 添付に記載)

L1/var/mesh/cache/deriveddata/{workspace_hash}、Xcode DERIVED_DATA_DIR にバインド。L2/var/mesh/cache/cocoapods/var/mesh/cache/gradle。ユーザーホームのグローバルキャッシュへの書き戻し禁止。L3/var/mesh/artifacts/{job_id}。アップロード成功後は検証用サイドカーのみ保持。監視は layer_*_bytes を層別に報告し、「/ パーティション 85%」だけに依存しません。

03

6 ステップ Runbook:水位スクリプトから 3 層自動回収へ

以下 6 ステップは Runner が Mac Mesh ラベルに接続済みで、Job 前にシート acquire、後に release することを前提とします。順序を飛ばさないでください。指標のない水位線は盲削除です。

  1. 01

    3 層辞書とパスを固定:L1/L2/L3 ルート、warn(82%)/ hard(92%)を mesh-disk-policy.yaml に書き、イメージ一覧 にデフォルトマウントを登録します。

  2. 02

    disk-waterline プローブを配置:60 秒ごとにボリューム使用率と各層バイト数を収集し Prometheus/OpenTelemetry へ送信。hard 到達時は Runner を drain し新規 Job を fail-fast します。

  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 パネルの先頭行に置き、OS アラートのみに依存しないでください。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

3 つのハードしきい値と引用可能な運用パラメータ

以下の数値は 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 システムボリュームで mesh に約 60% を割く現場では、L2 合計 80GB(CocoaPods/Gradle 各 40GB ソフト上限)、L3 単一 Job 12GB(dSYM 含む)を推奨します。「週末 cron のみ」や「全員 ssh で手削除」を恒久策にすると監査項目とシート契約が欠け、隣接誤削除・コールドスタート急増・半書き込み成果物がリリース週に集中します。iOS/Android CI とディスク SLO を契約可能なクラウド Mac Mini に載せるチームには、VpsMesh Mac Mini クラウドレンタルが通常最適です。プランは 価格ページ、導入と水位スクリプト例は ヘルプセンター注文ページ をご覧ください。

よくある質問

読者からの質問トップ 3

既定は workspace ハッシュバケット とシートリースのバインドで、リース終了時にそのバケット LRU。多ブランチは worktree 分離記事。グローバル ~/Library/Developer/Xcode/DerivedData の無制限共有は避けてください。

Runner は fail-fast し disk_waterline_hard_stop を報告し、半書き込み成果物を防ぎます。スケジューラは空きノードへルーティングするか Burst を起動します。シート意味論は 並行シート記事 を参照してください。

必要です。ディスク清掃はランタイムゴミの回収のみで、スナップショットドリフト一覧の代替にはなりません。導入は ヘルプセンター、プラン比較は 価格ページ をご覧ください。