本文の要点
- Mac クラスタ拡張 = 課金・注文層 + BFF API + Provisioner 開通層 + Runner 編成層の 4 層を分離すること。
- ノード動的追加の中核 API:
cart/add_item(config[region]付き)→checkout→order-server/infoで SSH 取得。 - 商品 ID と構成(16GB/24GB、日/週/月レンタル、ストレージ addon)は BFF で決定的にエンコードされ、スクリプト注文に向く。
- リリース週の「弾力性」= 月額ベースライン + API 日額 burst ノード。キュー深度で拡張し、3 台を通年オンラインにしない。
- Runner クラスタは labels ルーティング(build / test / sign)。新ノードは cloud-init 後に同一 org へ自動登録。
- GitHub Actions ホスト macOS Runner と比べ、API クラスタは DerivedData パスと独占メモリを制御でき、壁時計時間が安定しやすい。
- 7 ステップ導入:単一ノード API PoC → デュアル Runner → キュー監視拡張 → リージョン failover 演習。
先行結論:拡張するのは状態機械であり、VM テンプレートではない
Mac クラスタ自動拡張の分水嶺は「Pod を秒単位で起動できるか」ではなく、決済成功から SSH 利用可能まで、API で読めるサービス状態と冪等な開通パイプラインがあるかにある。
多くのチームが初めて「Mac 算力ノード自動拡張」を語るとき、頭に浮かぶのは AWS Auto Scaling Group や Kubernetes HPA だ——メトリクス上昇 → 新インスタンス → 30 秒でトラフィック受け入れ。しかし Apple Silicon ベアメタル Mac mini は独占在庫商品であり、同一台を 2 つの「月額独占」顧客に同時販売できない。開通には鍵注入、リージョン DNS、SSH ポート割り当てが必要だ。現実的なモデルはこうなる:API によるクラスタ動的構成 = キュー深度に応じて BFF へ注文し、order-server/info をポーリングし、資格情報取得後に Runner プールへ登録する。
kvmboot の本番パスは FOSSBilling 自動化算力レンタルプラットフォーム と同源だ。FOSSBilling が注文と更新を管理し、api.kvmboot.com の BFF が安定した OpenAPI 契約を公開、データセンター Provisioner が割り当てと接続情報の書き戻しを行う。開発者が書くべきはその上のクラスタコントローラ——macOS が Linux コンテナのように無限複製できると期待するのではない。
1. なぜ API 駆動の Mac クラスタが必要か(Why)
従来、「もう 1 台 Mac が欲しい」が次の 3 点で止まりがちだった。
- 手動レンタル:運用コンソールで選択し、メールで SSH を送る。拡張上限は人数。リリース週の深夜追加は自動化不能。
- 固定 Runner 単機:16GB Mac 1 台で archive + XCTest + シミュレータを同時実行すると swap が壁時計を破壊する——Xcode ビルド最適化とデュアルノード並列 を参照。
- GitHub Actions ホスト macOS:分単位課金でキュー変動が大きく、コールドスタートのたびに DerivedData が消える。大規模リポジトリのリリース週請求は予測不能。
- Mac を K8s に無理やり載せる:macOS ライセンスと仮想化の境界から、通常の Worker Node には不向き。編成は注文と Runner 層で行い、クラスタ内で macOS Pod を回すのではない。
「Windows 開発 + iOS 納品」「リリース週 3× 並列ビルド」「Agent 7×24 常駐」が重なるチームに必要なのは、プログラム可能な算力契約だ。API で「アジア太平洋 16GB 日額ノードを 1 台追加」と言えば、5 分後に SSH が CMDB に現れ、GitHub Actions workflow の runs-on: [self-hosted, mac-build, burst] が即座にスケジュールできる。これが 2026 年における Mac 算力ノード自動拡張 の現実的な定義である。
2. Mac 算力ノードクラスタの 3 層モデル(What)
「クラスタ」を 3 層に分けると、API の責務が混ざらない。
2.1 リソース層(ベアメタルプール)
物理次元:リージョン(アジア太平洋 sg/jp、米東など)、メモリ(16GB / 24GB)、期間(日 / 週 / 月)、オプションのストレージ addon。在庫は有限で、API 注文前に商品一覧を確認すべき(GET /guest/product/get_list)。SKU と product_id は BFF で決定的にマッピングされる(基本プランは ID 200 から構成ビットでエンコード)。
2.2 制御層(BFF + 注文状態機械)
外部契約は https://api.kvmboot.com に集約。全リクエストに x-client-ssaid(匿名セッション識別子)。ログイン後は x-client-token を追加。注文は pending_setup → active(ほか suspended 等)を経由し、active かつ Provisioner が書き戻した後にのみ GET /order-server/info/{order_id} が hostname、username、password、ssh_port、vnc_port 等を返す——詳細は プロジェクト API ドキュメント の order-server-info を参照。
2.3 編成層(Runner / Agent クラスタ)
SSH 取得後、自動化(Ansible、cloud-init shell、または GitHub セルフホスト Runner インストールスクリプト)が ci ユーザー作成、DerivedData 永続パスマウント、Xcode コマンドラインツール、Runner 登録と labels 付与を担当する。クラスタの「スケジューリング」は CI プラットフォーム(label で job ルーティング)で起こり、ハイパーバイザ内の別スケジューラではない。マルチノード実践は Flutter + GitHub Actions + Mac mini セルフホスト Runner 実戦アーキテクチャ を参照。
3. BFF API で 1 ノードを動的開通する(How)
以下は最小再現パス(疑似コードレベル、フィールドは本番 BFF と一致)。
# 0. 共通ヘッダ
HEADERS = {
"Content-Type": "application/json",
"x-client-ssaid": "<ブラウザと同じ長いランダム文字列>",
"x-client-token": "<POST /password-login または /email-login の戻り値>"
}
BASE = "https://api.kvmboot.com"
# 1. ログイン(OpenAPI で確定したエンドポイント。guest/login は使わない)
POST {BASE}/password-login {"email":"...","password":"...","role":"client"}
# 2. SKU 確認 → product_id、period、region を選択
GET {BASE}/guest/product/get_list?show_hidden=false
# 3. カートを空にして商品追加(region がノードの配置先を決定)
GET {BASE}/guest/cart/reset
GET {BASE}/guest/cart/add_item?id=200&period=1D&config[region]=sg
# 4. 決済 + 支払い(テスト環境は Stripe テストモード可)
GET {BASE}/client/cart/checkout?gateway_id=<stripe_id>
POST {BASE}/pay-invoice {"hash":"<invoice_hash>","gateway_id":...,"return_url":"..."}
# 5. active まで注文をポーリング
GET {BASE}/client/order/get_list?per_page=100
# 6. SSH 資格情報を取得(Provisioner 書き戻し後)
GET {BASE}/order-server/info/{order_id}
ステップ 5–6 をスケールアウトコントローラに包む:キュー深度 > 閾値 → 3–6 を実行 → 新ノードを Runner 登録 → 内部 CMDB に書き戻し。スケールインは:該当 label への job 配信停止 → drain 待ち → 期限切れで更新しない、またはシャットダウン工単(client/support/ticket_create、content 形式 order_id + operate: off)。
リージョンとメモリ選定はクラスタ RTT と swap リスクに直結する。リモート Mac M4 アジア太平洋/米東と 16GB/24GB ガイド を参照。初回 API 開通は Mac レンタル開通・受入チェックリスト で日額 PoC を行い、その後自動化を書く。
4. 比較:手動 vs API 編成 vs GHA vs「K8s 思考」
五軸表頭は記事全体で統一し、レビュー会議でそのまま使える。
| 方案 | 入口 | 実行力 | コンテキスト | コスト | 権限境界 | 向く人 |
|---|---|---|---|---|---|---|
| 手動コンソールレンタル | Web コンソール | 人手で SSH 送付 | API 状態機械なし | 開発コスト低 | 運用承認 | 固定ノード ≤3 台 |
| BFF API 動的クラスタ | スクリプト / CI コントローラ | 注文・ポーリング・Runner 登録 | 注文 ID が CMDB を貫通 | 日額 burst + 月額ベース | Token + ssaid 認証 | リリース弾力・マルチリージョン |
| GitHub ホスト macOS | workflow YAML | xcodebuild(コールド環境) | job ごとにクリーン | 分単位、ピーク高額 | GitHub サンドボックス | 小規模 OSS |
| 自社 Mac ファーム | データセンター / オフィス | 完全自律 | DerivedData 常駐 | CapEx + 運用 | 物理セキュリティ自律 | 7×24 フル稼働 >18 ヶ月 |
| K8s 式の幻想 | kubectl / HPA | macOS 非適用 | ライセンス・仮想化制限 | エンジニアリングの罠 | コンプライアンスリスク | Mac 主経路として非推奨 |
非対称な結論:iOS / Flutter 納品チームにとって、API 編成のベアメタル Mac クラスタ はしばしば「壁時計 × コスト」で純 GHA に勝つ——機械が速いからではなく、実行コンテキスト(DerivedData、Keychain、Runner label)が保持・予測可能だからだ。
5. シナリオ選定マトリクス
| シナリオ | 日次ビルド回数 | ピーク特性 | 推奨クラスタ形態 | API 戦略 |
|---|---|---|---|---|
| 個人 Side Project | <5 | 突発なし | 単一ノード月額 | 自動拡張不要 |
| Flutter 小チーム | 5–15 | リリース週 ×2 | 月額 1 + 日額 burst 1 | キュー >4 で API 日額追加 |
| アウトソース複数 Team ID | ピーク 30+ | 並列 archive | ビルド / 署名デュアルプール | 異なる label + リージョンで分離 |
| AI Agent 7×24 | 継続 | メモリ敏感 | 24GB ベース + 任意 burst | 月額 API 更新、job 単位ではない |
| クロスリージョン DR | 任意 | 単一リージョン障害 | アジア太平洋 + 米東各 1 ベース | DNS / workflow で region パラメータ failover |
6. 推奨スタック(Stack)
スタック A:単一ノード API PoC(1 週間)
日額 SKU → API 注文 → order-server/info で SSH 受入
→ 手動 Runner インストール(labels: mac-build)
→ xcodebuild archive を 1 本実行しローカル壁時計と比較
スタック B:デュアルプール CI クラスタ(本番スイートスポット)
月額ノード A:labels mac-build, deriveddata-persist
月額/日額ノード B:labels mac-test, simulator
キュー監視 → API 日額ノード C(labels mac-build, burst)リリース週のみ
スタック C:プラットフォーム再販(上級)
自社ポータル → FOSSBilling 課金 → 自前 Cluster Controller が kvmboot BFF を呼ぶ
→ テナント分離:顧客ごとに独立 Runner org + 注文 ID クォータ
(アーキテクチャは FOSSBilling 算力レンタル記事を参照)
7. 5 つのよくある誤解
- 誤解 1:「決済リダイレクト成功 = ノード準備完了」 — Webhook + 注文
active+order-server/infoの三者で判断。リダイレクトは失われることがある。 - 誤解 2:「自動拡張 = 無限在庫」 — ベアメタル過剰販売は SLA を直撃。コントローラに在庫上限とサーキットブレーカを入れる。
- 誤解 3:「新ノードに label なしでもクラスタになる」 — すべての burst ノードに明示的 labels が必要。ないと job が誤ったマシンに落ち DerivedData を汚染する。
- 誤解 4:「16GB 単機で archive + テスト + Agent」 — API で第 2 ノードを追加するか 24GB に上げる。swap に賭けない。
- 誤解 5:「開通ロジックをフロントエンド JS に書く」 — クラスタコントローラはサーバー側(または CI Secret 環境)で動かし、Token をブラウザリポジトリに漏らさない。
8. 7 ステップ導入チェックリスト
- 日額 PoC:コンソールまたは Postman で login → add_item → checkout → pay →
order-server/infoを通し、開通受入チェックリスト と照合。 - スクリプト化:上記を
provision_mac_node(region, plan, period)に封じ SSH 構造体を返す。冪等キーは内部request_idでログ。 - Runner インストール:cloud-init で GitHub Actions Runner または GitLab Runner。固定
ciユーザーと DerivedData パス。 - labels 付与:最低
mac-build/mac-testを分離。burst ノードはburstを追加しリリース後に下線しやすくする。 - キューシグナル接続:GitHub Actions queue API、内部 Redis、Jenkins キュー深度で拡張トリガー。クールダウンでチャタリング防止。
- スケールインと drain:配信停止 → running job 完了待ち → シャットダウン工単または日額注文を更新しない。
- failover 演習:
order-server/infoタイムアウトとリージョン不可用を模擬し、workflow がconfig[region]を切り替えられるか検証。
9. FAQ
Mac 算力ノードは K8s のように秒単位で自動拡張できる?
できない。ベアメタル開通は分単位。在庫を意識した注文編成と理解し、Pod の秒単位起動と混同しない。
クラスタ動的構成に最低限必要な API は?
ログイン、product/get_list、cart/add_item、cart/checkout、pay-invoice、order/get_list、order-server/info。電源操作は工単 API。
GitHub Actions とどう連携する?
各ノードをセルフホスト Runner として登録し labels を付与。workflow の runs-on でプールにルーティング。拡張 = 新 API 注文 + 自動登録。
リリース週の一時ノード追加の課金は?
日額 SKU を選び、そのウィンドウのみ課金。ベースは月額。総コストは純 GHA macOS 分課金より低いことが多い。
API 開通失敗の切り分けは?
注文が active か、order-server/info が 404 か、region と product_id の一致、在庫枯渇を確認。
10. まとめ
Mac 算力ノード自動拡張 の 2026 年の正解は、API による動的構成で「契約層の注文」と「実行層の Runner クラスタ」を接続することだ。キューが深ければベアメタルを注文し、空けば drain 後に日額ノードを解放する。macOS に K8s の神話を無理に当てはめない。order-server/info の SSH をクラスタ join token と見なせば、プログラム可能な Mac ビルドファームを手に入れられる。
推奨パス:日額 API PoC → デュアル label プール → キュー駆動 burst → 月額ベースライン確定。プラットフォーム能力とプランは トップ Cloud Mac 比較 を参照。
API で Mac 算力ノードを CI クラスタに組み込む
リリース週に一時的にビルド力を足し、平常時は月額ベース 1 台——それが API 動的クラスタ構成 が解く問題だ。kvmboot は api.kvmboot.com BFF で注文・開通ポーリング・SSH/VNC 取得の全链路をプログラム可能にする。独占 M4 ベアメタル、アジア太平洋/米東ノード、日額で受入可能。空回りの YAML より、実在庫に接続したスケールアウトコントローラの方が説得力がある。