固定 Mac Runner、臨時 Runner,還是兩者並用?負載穩定、倉庫較少且工具鏈啟動成本高,先保留固定節點;發布峰值明顯、多倉庫共享或隔離要求高,則採用 ephemeral runner。 對多數團隊而言,最穩妥的做法是固定基線承接日常工作,再用彈性池吸收可預測的突發排隊,而不是一次過重做整套 CI 基礎設施。
最後更新於 2026-09-05;功能狀態核實自 GitHub 自託管 Runner 參考文件、Runner Scale Set Client 官方儲存庫 及 Runner 權限與安全文件。
本週建議動作: 先從工作流程記錄整理日常排隊時間、節點佔用、失敗原因與工具鏈初始化時間,再把發布工作流單獨標記。若固定節點在日常已足夠,只有發布時排隊,就先做「固定基線+突發池」試跑,不要直接永久增加常駐 Mac。
誰適合採用哪一種 Mac Runner
這篇適合三類讀者:
- 移動開發團隊負責人: 要處理發布高峰排隊,但不想全年閒置多台 Mac。
- DevOps 與平台工程師: 要設計 Runner 註冊、任務路由、倉庫隔離與節點回收流程。
- 安全或發布負責人: 要判斷簽名資產能否放入臨時節點,以及如何限制工作流程來源。
GitHub Actions Mac Runner 的彈性擴容,並不是單純把 Runner 數量調高。真正要決定的是:哪些工作需要長期保留狀態,哪些工作可以在一次任務後銷毀,以及 Mac 主機供應速度能否追上佇列變化。
| 方案 | 適合的工作負載 | 主要優點 | 主要代價 | 本文評分 |
|---|---|---|---|---|
| 固定 Runner | 日常構建穩定、工具鏈和快取需要保留 | 啟動路徑短,故障排查直接 | 閒置時仍要維護,工作區與憑證可能殘留 | 本文評分:4/5 |
| 臨時 Runner | 發布峰值、多倉庫隔離、任務來源不固定 | 任務後可註銷,隔離邊界較清楚 | 仍須自行供應、清理和回收 Mac 主機 | 本文評分:4/5 |
| 固定基線+突發池 | 平日穩定、發布時突然升高 | 在可用性與成本間取平衡 | 控制面、供應和降級流程較複雜 | 本文評分:5/5 |
以上評分是按啟動穩定性、隔離難度、維護成本和峰值吸收能力作出的架構判斷,不是 GitHub 的官方評級。
先按工作場景分流,而不是按開發者人數加節點
日常構建穩定:固定節點通常更簡單
如果任務來源可控、倉庫數量有限,而且 Xcode、套件、模擬器或自訂工具鏈需要長期保留,固定 Runner 通常較合適。這裡的「固定」不是任意放一台 Mac 就完成,而是要維持明確的倉庫存取範圍、標籤路由、維護窗口和故障備援。
判斷依據應來自工作流程記錄,而不是團隊有多少位開發者。至少要觀察:
- 工作流在佇列中等待多久,等待是否集中在發布時段;
- Runner 實際執行任務的時間,以及大量閒置的時段;
- 失敗是來自 Xcode、簽名、依賴下載、主機重啟,還是 Runner 本身;
- 固定節點上的快取和工具鏈是否真的縮短了任務準備時間。
固定 Runner 的隱性問題是狀態會累積。工作區、暫存檔、登入狀態、鑰匙串和環境變數都可能跨任務保留。若倉庫信任邊界不同,固定節點不能只靠一個共用標籤解決。
發布峰值集中:不要為短暫排隊永久買滿節點
版本發布或大型合併形成的高峰,應先與日常基線分開。短時間排隊不一定代表全年都需要更多常駐 Runner;關鍵是比較三件事:
- 峰值主要是哪一類任務,例如測試、Archive、簽名或上傳;
- 佇列長度多久會超過團隊可接受的等待時間;
- 一個臨時 Mac 從供應到完成 Runner 註冊,需要多久。
如果峰值可預測,可以預熱臨時 Runner;如果峰值由佇列信號觸發,則要驗證節點供應速度能否在等待惡化前完成。若主機啟動時間不穩定,彈性池可能只是把「Runner 排隊」換成「等待 Mac 上線」。
| 峰值特徵 | 優先方案 | 成立條件 | 不適合的反例 |
|---|---|---|---|
| 每日任務數和佇列變化小 | 固定 Runner | 快取有效、工具鏈狀態需要保留 | 倉庫來源不受控,或需要強隔離 |
| 發布時集中排隊 | 預熱臨時 Runner | 發布窗口可預測,Mac 供應時間可驗證 | 峰值不可預測,節點供應經常失敗 |
| 佇列信號觸發突發工作 | 按信號擴容 | 有供應、註冊、註銷和異常回收鏈 | 只會建立 Runner,不能清理主機 |
| 平日低負載、發布高負載 | 固定基線+突發池 | 關鍵發布不依賴單一彈性控制面 | 沒有固定備援,控制面故障即全線停擺 |
在「Xcode 發布高峰應增加常駐節點還是臨時租用 Mac」這個選擇上,我們會先看峰值是否反覆出現,以及發布任務是否需要長期保留狀態。只有當高峰已成為穩定的日常基線,增加常駐節點才有充分理由;否則,臨時租用 Mac 或建立突發池更容易控制閒置成本。
多倉庫共享時,隔離設計比擴容速度更重要
多倉庫共用 Mac 算力時,不能把所有工作流送進同一個 Runner Group。至少要按以下條件劃分:
- 倉庫信任級別:內部、合作方和公開來源不應使用同一條高權限路徑;
- Xcode 版本與 SDK 需求:需要不同工具鏈的工作流應使用不同標籤;
- 任務類型:普通測試、構建、簽名發布和上傳任務應分流;
- 網路權限:可接觸內部套件源的節點,不應讓所有倉庫任意使用。
GitHub 的 Runner Group 權限說明指出,Runner Group 可用來限制哪些組織或倉庫能使用特定 Runner;而標籤管理文件則說明以標籤把工作流導向相符節點。這些設定是路由和權限邊界,不等於已完成主機清理。
Mac Runner 擴容後如何避免倉庫互相污染
若採用長期 Runner,任務結束後應清除工作區、暫存資料、登入狀態和不再需要的憑證;若採用臨時 Runner,則要驗收主機本身是否真的被重設或回收。
「ephemeral runner 已註銷」與「Mac 主機已清理」是兩件事。前者代表該 Runner 不再接收任務;後者還要確認本機檔案、鑰匙串、快取、系統登入狀態和網路權限沒有被下一個租戶或工作流繼承。
注意: 不要把一次性註冊、Runner 離線或工作流完成,當成主機已安全銷毀的證據。平台應保留外部工作流日誌、主機供應記錄和回收結果,否則污染問題發生後很難重建時間線。
Runner Scale Set Client 能做什麼,不能做什麼
Runner Scale Set Client 是否能支援 macOS 節點
截至 2026-09-05,官方資料已確認 Runner Scale Set Client 可用於建立包含 macOS 在內的自訂彈性 Runner 方案,但官方儲存庫仍標示為 Public Preview。它可以對接 Runner Scale Set API,產生臨時設定,並協助把擴縮容信號傳給團隊自己的基礎設施;它不是完整的 Mac 主機供應服務。
換句話說,客戶端不會自動替團隊購買、啟動、重裝、清理或回收實體 Mac。Mac 主機生命週期仍由團隊自己的供應層負責。這也是它與 Actions Runner Controller 官方概念不同的地方:ARC 的核心概念圍繞 Kubernetes Runner Pod,不能直接把容器化的擴容流程照搬到真實 macOS 主機。
| 控制層 | 負責事項 | 不應假設它會負責的事項 | 驗收證據 |
|---|---|---|---|
| 工作流佇列 | 發出任務需求與路由條件 | 不保證 Mac 已可用 | 佇列、標籤和工作流日誌 |
| Runner Scale Set Client | 對接 API、產生臨時設定 | 不供應或清理 Mac 主機 | API 事件與註冊記錄 |
| Mac 供應基礎設施 | 建立、啟動、配置和回收主機 | 不自動理解倉庫信任 | 主機生命週期記錄 |
| Runner | 接收並執行單一或指定任務 | 不等於主機已清空 | 註冊、任務完成、註銷狀態 |
| 外部日誌系統 | 留存工作流與控制面證據 | 不會替代主機清理 | 可按任務追溯的日誌 |
最小驗證鏈應包含:
- 佇列信號能否觸發供應流程;
- Mac 節點是否在預期狀態下上線;
- Runner 能否以正確的群組和標籤註冊;
- 單一測試任務能否完成並回傳日誌;
- 任務結束後 Runner 是否註銷;
- 主機是否完成清理、重設或回收;
- 供應失敗時是否能留下外部記錄並進入降級路徑。
官方 自託管 Runner 監控與故障排查文件可作為控制面檢查依據,但主機清理仍須由平台團隊自行定義驗收條件。
簽名發布要獨立設計,不要讓所有任務共用高權限節點
包含鑰匙串、憑證、內部依賴源或專用網路的工作流,不應直接與普通測試共用同一批 Runner。固定節點在這類場景有一項實際優勢:複雜狀態可以長期維護,故障時也較容易由熟悉環境的工程師處理。
但固定節點必須嚴格限制任務來源。若公開分支、未審核的拉取請求或低信任倉庫能觸發簽名節點,長期保存的鑰匙串便會成為高價值攻擊面。GitHub 的自託管 Runner 安全使用指南也提醒,自託管 Runner 的環境和權限需要由使用者自行承擔與管理。
臨時節點則要求憑證注入、撤銷和回收可以重複執行。不能只把憑證檔案複製到 Mac,任務結束後再依賴人工刪除。較穩妥的分流方式是:
- 普通編譯和測試:使用低權限、可回收的 Runner;
- 需要內部套件源:使用獨立網路和專用 Runner Group;
- 簽名與發布:使用受限來源、獨立標籤及明確的憑證生命週期;
- 發布完成:撤銷短期憑證,確認鑰匙串和工作區已清理,再回收主機。
若目前無法自動化簽名資產注入和撤銷,先維持一台受控固定節點,通常比把未驗證的憑證流程硬塞進彈性池安全。
固定還是彈性:用條件分支作出決定
以下條件列表可直接用於架構評審;每個判斷都要能由工作流記錄、權限設定或主機生命週期記錄驗證。
- 若日常佇列穩定、倉庫較少,而且 Xcode 工具鏈或快取需要長期保留,則選固定 Runner;否則回到下一項。
- 若發布峰值可預測,且臨時 Mac 能在可接受的等待窗口內完成供應與註冊,則選預熱臨時 Runner;若供應時間不穩定,保留固定基線。
- 若多倉庫需要不同信任級別、Xcode 版本或網路權限,則選分組的臨時 Runner 或隔離節點池;不要用一個共用標籤掩蓋邊界。
- 若簽名資產仍依賴人工登入、固定鑰匙串或不可重複的內部狀態,則把發布任務留在受控固定節點;普通測試再交給彈性池。
- 若Runner Scale Set Client 只能完成註冊信號,卻沒有主機建立、清理和回收能力,則先補齊供應層;不要把客戶端當成 Mac 自動化服務。
- 若彈性控制面不可用、Mac 啟動失敗、Runner 更新異常或外部日誌缺失,則暫停擴容並回退到固定基線;關鍵發布不應只依賴突發池。
這套分支也回答了「GitHub Actions 自託管 Mac Runner 能否自動擴容」:可以建立具備擴縮容信號的自訂方案,但「自動擴容」必須同時包含佇列判斷、Mac 供應、Runner 註冊、任務後清理和異常回收,不能只看 API 是否成功回應。
故障降級要在正式切換前演練
彈性方案最容易被忽略的是失效時的回退。至少要模擬以下情況:
- 控制面無法收到佇列信號;
- Mac 主機已供應,但 Runner 沒有完成註冊;
- Runner 更新失敗或節點長時間離線;
- 任務完成後註銷成功,但主機回收失敗;
- 外部日誌沒有保存,無法確認簽名資料是否清除。
每一種故障都要有最大等待時間、停止擴容條件和人工接管方式。固定基線節點應保留關鍵發布能力;彈性任務則要能被取消、重新排程或轉回固定節點。GitHub 的新增自託管 Runner 文件可用來核對註冊流程,但不會替團隊定義供應失敗時的業務降級規則。
我們建議先用一條非正式發布工作流做完整試跑:從佇列產生開始,追蹤 Mac 供應、Runner 上線、測試任務、註銷、主機清理和日誌保存;只有每個環節都有可追溯證據,才把彈性池接入真正的簽名發布。
結論:先保留基線,再用真實峰值驗證彈性池
對 Xcode CI 而言,固定 Runner 和臨時 Runner 沒有脫離場景的絕對優劣。穩定單倉庫工作負載重視工具鏈狀態和可預測性,固定節點較簡單;發布峰值、多倉庫共享和強隔離場景則更適合臨時 Runner。多數平台團隊應先採用固定基線加突發池,並以真實工作流驗證供應時間、排隊改善、註銷和主機清理,而不是先追求全面自動化。
如果目前方案是自購 Mac mini 或長期維持閒置節點,常見缺點是資金先被硬體鎖定、發布高峰仍要預留容量,而且主機維護與遠端可用性由團隊自行承擔;如果改用一般雲端 Linux 主機,又無法直接承接 Xcode、macOS 工具鏈和 Apple Silicon 相容性要求。當需求只是發布週期、版本驗證或短期 CI 節點,透過 JexMac 租用真實 Mac,先按遠端 Mac 租賃週期與方案取得可用環境,再按CI 節點驗收與工作流試跑驗證固定基線和突發節點是否能協同,通常比全年持有全部峰值容量更容易控制風險。
若團隊已在使用 Xcode,亦可先參考遠端 Mac 上的 Xcode 開發方案,再把場景矩陣中的日常基線、發布峰值和簽名邊界帶入一次實際工作流測試。
以 JexMac 彈性部署 GitHub Actions Mac Runner
JexMac 提供遠端 Mac 租用服務,協助團隊按專案需求配置穩定的 Xcode 建置與測試環境。