執行器
如何更換 GitHub Actions 執行器供應商:標籤、快取、機密、計費與備援
要切換供應商,請先串接供應商(通常透過 GitHub App),將 runs-on 改為其標籤,然後執行作業。接著確認標籤變更無法處理的六件事:執行器映像檔、快取、網路身分、OIDC 信任、備援機制與計費。請先在一個儲存庫上試行,並使用只需一項變更就能復原的切換方式。
更新日期
本指南不偏向任何廠商。它說明更換 GitHub Actions 執行器供應商時會移動哪些東西、最常出問題的地方,以及如何退回。 CRACI 是我們打造的產品,也是供應商之一;它會出現在有文件佐證之事實適用的地方,並在文末有專屬章節。若要先選擇供應商,請參閱 GitHub Actions 執行器供應商比較與 GitHub 託管執行器替代方案。
切換時哪些會改變、哪些維持不變
GitHub Actions 分為兩半。GitHub 是控制平面:它儲存儲存庫與工作流程檔案、觸發事件、儲存機密、指派作業、 顯示紀錄與檢查結果、保存建置產物並簽發 OIDC 權杖。 CI 執行器則是作業實際執行的地方:一台具備映像檔、CPU、磁碟、連往網際網路的網路路徑, 通常還有本機快取的機器。GitHub 將作業指派給執行器,在作業開始時傳送作業的機密,執行器再將紀錄串流回傳。
執行器供應商只取代後半部。
| 項目 | 留在 GitHub | 移至供應商 |
|---|---|---|
| 儲存庫、工作流程檔案、觸發條件 | 是 | 否 |
| 機密儲存 | 是 | 機密會在作業開始時傳送到供應商的機器 |
| 作業指派、紀錄、檢查介面 | 是 | 執行器將紀錄串流回傳 |
來自 actions/upload-artifact 的建置產物 | 是 | 否 |
| OIDC 權杖簽發者 | 是 | 否,但權杖會標示該執行器為自架 |
| 機器、映像檔、CPU、記憶體、磁碟 | 否 | 是 |
| 對外網路路徑與 IP 位址 | 否 | 是 |
| 快取儲存空間 | 取決於供應商 | 取決於供應商 |
| 移轉作業的按分鐘計費 | 否 | 是 |
第三方執行器是以自架執行器的身分向 GitHub 註冊。這就是為什麼 GitHub 對自架執行器的規則也適用於它: 標籤如何分派作業、執行器群組如何限制存取、OIDC 權杖如何描述它,以及 GitHub 如何對它計費。
runs-on 變更與標籤
GitHub 會尋找符合作業 runs-on 標籤與群組的執行器。若沒有符合的執行器上線,
作業會留在佇列中,直到有執行器上線;若被指派的執行器在 60 秒內沒有接手作業,作業會重新排入佇列;
而在佇列中停留超過 24 小時的作業會失敗
(GitHub
自架執行器參考文件)。標籤打錯字,或儲存庫未安裝供應商的應用程式,都會表現為一個永遠不會開始的作業。
供應商以下列兩種方式之一指定機器:
-
寫在標籤中。Ubicloud 使用
ubicloud-standard-2之類的標籤,Blacksmith 使用blacksmith-2vcpu-ubuntu-2404,Avrea 使用avrea-ubuntu-latest-2-vcpu,ARM 機器則在標籤中加上arm。變更規格就代表變更標籤。 -
寫在設定步驟中。CRACI 只使用一個標籤
runs-on: craci,再由cracicorp/setup@v1步驟選擇規格(1 至 32 個運算單位,每單位 1 vCPU 與 3 GB,預設為 2)、 映像檔、網路政策,或以 slug 指定組織的執行器範本。若 CRACI 無法解析某個輸入,它會執行預設環境, 並在作業紀錄中寫入警告;未知的映像檔或範本則會遭到拒絕。
讓切換只需一個變數
請將標籤放在儲存庫或組織變數中,而不是寫死在程式碼裡。如此一來,切換過去或切換回來都只是設定變更, 而不需要在每個儲存庫發 pull request。
jobs:
build:
# Falls back to GitHub-hosted when the variable is not set
runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v7
- run: make build
deploy:
needs: build
# Stays on GitHub-hosted until you decide to move it
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
選擇是以作業為單位,因此建置與測試作業可以移轉,部署作業則維持不變。變數可在組織層級設定, 並在個別儲存庫覆寫,因此一項設定就能移轉一整組儲存庫,個別儲存庫也能選擇不參與。
可重複使用的工作流程
如果相同的管線被複製到許多儲存庫,請將它移入可重複使用的工作流程(reusable workflow),並從輸入或變數讀取執行器。
在那裡變更 runs-on,就會變更所有呼叫它的儲存庫。規則集(ruleset)可以要求組織的儲存庫執行某個工作流程,
讓共用版本持續被使用。
執行器映像檔:相容性與版本固定
GitHub 的託管映像檔內含大量預先安裝的工具與託管工具快取。供應商提供的映像檔,要不是與 GitHub 相容,就是較為精簡。 作業經常依賴一些從未宣告的東西:
- 預先安裝的程式語言版本與命令列工具;
- 免密碼的
sudo,以及systemd(供以systemctl啟動的服務使用); - 執行中的 Docker 常駐程式,以及 Buildx 與 Compose;
setup-*actions 在下載前會讀取的託管工具快取;- 大型建置所需的可用磁碟空間。
判斷原則:先使用供應商與 GitHub 相容的映像檔。等作業順利通過後,再將它移到精簡映像檔,
並為它原本隱含使用的所有項目加上明確的 setup-* 步驟。
版本固定:ubuntu-latest 會依 GitHub 的時程移至新版本,而
ubuntu-24.04 只固定作業系統版本,不固定其上的套件版本。請在作業內固定重要的項目:
以明確版本指定 setup actions,並以摘要值指定容器映像檔。請詢問各供應商允許您固定哪些項目。
執行器應用程式本身則必須持續更新,才能與 GitHub 通訊。
在 CRACI 上,映像檔包括 x86-64 與 ARM64 上的 CRACI Slim(Ubuntu 24.04,不含 systemd),以及與 GitHub Actions
完全相容的 Ubuntu 24.04 映像檔;後者以 ubuntu-24.04 或 ubuntu-latest 選用,
跟隨 GitHub 的 Ubuntu 24.04 執行器映像檔,並包含託管工具快取。所有映像檔都內含 Docker Engine、Buildx 與
Compose v2。
快取:哪些會延續、哪些從零開始
在新供應商上的最初幾次執行往往較慢,常見原因是快取還是空的,而不是機器較慢。
actions/cache 的運作方式決定了您會看到什麼
(actions/cache README):
- 項目是依其鍵值與版本找到的,版本是快取路徑與壓縮工具的雜湊值。
- 項目以分支為範圍;預設分支的項目可供其他分支使用。
- 預設情況下,一個儲存庫最多可保存 10 GB 的快取,超過後會淘汰最舊的項目。儲存庫管理員以及組織或企業擁有者可以提高上限;超過 10 GB 的用量會向帳戶收費(GitHub 相依套件快取)。
-
在 Windows 上儲存的快取不會在其他作業系統上還原,反之亦然,除非設定了
enableCrossOsArchive;使用不同的壓縮工具也會產生不同的版本。
供應商以下列兩種方式之一提供快取:
| 模式 | 最初幾次執行 | 取捨 |
|---|---|---|
| 執行器使用 GitHub 的快取服務,與 GitHub 託管執行器相同 | 既有項目可以還原 | 快取流量需經由網際網路在供應商與 GitHub 之間傳輸 |
| 供應商從其執行器旁的儲存空間提供快取 API | 通常是空的,直到最初幾次執行將它填滿,除非供應商會匯入或回退讀取 GitHub 的項目 | 還原更快;寫入其中的項目通常對 GitHub 託管執行器不可見 |
第二點對混合機群與復原很重要:如果您將作業切換回來,它在 GitHub 上也可能從空快取開始。 請詢問供應商採用哪種模式,以及項目存放在哪裡。
分辨空快取與緩慢的執行器。以一個快取大型
node_modules 目錄的 Node 建置為例。在新供應商上第一次執行時,actions/cache 會回報未命中,
安裝步驟會下載所有內容,後置步驟則會儲存快取。從同一分支的下一次執行起,該步驟會回報命中,安裝步驟所需時間也隨之縮短。
請等快取暖機後再比較執行結果:讀取
cache-hit 輸出,並將還原步驟與安裝步驟的時間和建置本身分開計算。
關於鍵值、範圍與快取下毒,請參閱 GitHub Actions 快取的運作方式。
在 CRACI 上,actions/cache 的運作方式與現在相同,而建置紀錄會以套件為單位標示它是從 CI 快取還原,還是實際擷取的。
Docker 層快取
| 機制 | 層存放位置 | 須知事項 |
|---|---|---|
BuildKit type=gha |
GitHub Actions 快取 | 範圍與大小規則同上;需要支援它的建置器 |
BuildKit type=registry |
您登錄庫中的另一個映像檔 | 可在任何執行器上運作,更換供應商後依然保留;您需支付登錄庫的儲存與傳輸費用 |
| 供應商本機的層快取或永久磁碟 | 位於供應商的執行器旁 | 通常最快;若您離開該供應商,它會留在原處 |
登錄庫快取是可攜的選項(Docker 快取後端):
- uses: docker/build-push-action@v7
with:
push: true
tags: ghcr.io/acme/app:latest
cache-from: type=registry,ref=ghcr.io/acme/app:buildcache
cache-to: type=registry,ref=ghcr.io/acme/app:buildcache,mode=max
兩個同時開始的作業會還原同一份快取,並且都會建置快取中缺少的層。這在任何 CI 上都會發生, 因此請不要將它視為供應商的問題。
CRACI 提供容器層快取,包括本機層快取、遠端層快取與 bind mount 快取。
機密、OIDC 與雲端憑證
GitHub 儲存您的機密,並將它們傳送給執行作業的執行器。將作業移至供應商,就代表把該作業的機密託付給該供應商。 請詢問:
- 每個作業擁有自己的虛擬機器,還是共用主機上的容器?
- 機器是否會在作業結束後銷毀?是否有任何資料被保留?
- 供應商會保留哪些紀錄?GitHub 會在作業紀錄中遮蔽已註冊的機密,但表示對經過轉換的值不保證能自動遮蔽; 也請詢問供應商自身的系統紀錄。
OIDC 仍可運作,但有一個需要注意的地方。OIDC 權杖是由 GitHub 而非執行器簽發,因此
permissions: id-token: write 在任何執行器上都能運作。但權杖的 runner_environment
宣告為 github-hosted 或 self-hosted
(GitHub OIDC 參考文件),
而在第三方執行器上,它會是 self-hosted。要求
github-hosted 的雲端信任政策會拒絕該作業。例如,具有下列屬性條件的 Google Cloud 工作負載身分集區:
# Before: only GitHub-hosted runners in the acme organization
assertion.repository_owner == 'acme' && assertion.runner_environment == 'github-hosted'
# After: drop the runner check, and narrow by repository and branch instead
assertion.repository == 'acme/app' && assertion.ref == 'refs/heads/main'
移除執行器檢查會擴大可取得憑證的對象,因此請同時收緊另一項條件。在切換之前,
請搜尋每一項雲端信任政策與工作負載身分設定中的 runner_environment。
推送映像檔:GITHUB_TOKEN 只要具備 packages: write,就能從任何執行器推送到 GitHub
Container Registry,使用已儲存機密的登錄庫登入方式也維持不變。
在 CRACI 上,GitHub App 會讀取您的程式碼與 Actions 執行紀錄,並管理它為您的組織註冊的執行器。 每個作業都在各自隔離的虛擬機器中執行,CRACI 不會儲存您的原始碼。
網路身分:IP 允許清單與對外連線
新的執行器會從新的 IP 位址連出。請列出所有依來源位址進行篩選的項目:
- 資料庫與建置產物儲存庫的允許清單;
- 設有 IP 限制的 SaaS API;
- 合作夥伴的 SFTP 伺服器,以及位於防火牆後方的內部服務。
可行的選項是供應商的固定或穩定對外 IP 位址,或是由您掌控的代理伺服器。這也是決定作業究竟可以連線到哪裡的時機: 執行器上的對外連線(egress)政策 可以阻止遭入侵的相依套件將機密傳送到建置根本不需要的主機。請參閱 GitHub Actions 對外連線政策。
CRACI 提供穩定的對外 IP 範圍,以及可設為預設拒絕或允許的對外連線政策,政策會在作業開始前驗證,
並採失效即封鎖(fail closed)。若未設定 network 輸入,預設範本會允許其他對外連線,
因此對外連線控管需要由您自行設定。
混合機群:移轉 Linux,讓 macOS 與 iOS 留在原處
執行器是以作業為單位選擇,因此一個工作流程可以在供應商上執行其 Linux 作業,在
GitHub 託管執行器上執行其 macOS 作業。以 actions/upload-artifact 上傳的建置產物由 GitHub 儲存,
因此一個執行器上的作業可以將檔案交給另一個執行器上的作業。
jobs:
backend:
runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v7
- run: ./gradlew test
android:
runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v7
- run: ./gradlew assembleRelease
- uses: actions/upload-artifact@v7
with:
name: android
path: app/build/outputs/apk/release/
ios:
# Signing and the iOS build stay on GitHub-hosted macOS
runs-on: macos-latest
needs: backend
steps:
- uses: actions/checkout@v7
- run: xcodebuild -scheme App -configuration Release archive
留在 GitHub 上的作業仍會使用您方案的內含額度,超出部分由 GitHub 收費。CRACI 目前在 x86-64 與 ARM64 上執行 Linux,Windows 與 macOS 已列入產品藍圖,因此搭配 CRACI 的混合機群,代表 Linux 使用 CRACI, 其餘則使用 GitHub 託管執行器。
供應商停擺時的備援
GitHub 沒有內建執行器標籤之間的備援機制。如果該標籤沒有任何執行器上線,作業就會等待, 並在 24 小時後失敗。請事先規劃:
- 上述的變數切換:將它改回
ubuntu-latest,新的執行就會送往 GitHub 託管執行器。 -
手動覆寫,用於緊急執行:一個
workflow_dispatch輸入,讀取方式為runs-on: ${{ inputs.runner || vars.LINUX_RUNNER || 'ubuntu-latest' }}。 - 為作業設定
timeout-minutes,避免停滯的作業將部署卡住好幾個小時。 - 監控佇列等候時間,以便在作業等待時間比平常更長時察覺。
請詢問各供應商是否提供自動備援,以及觸發條件為何。也請為另一個方向做好規劃: GitHub 負責排入佇列並指派每個作業,因此 GitHub Actions 發生服務中斷時,所有執行器供應商上的作業也都會停止。
計費:GitHub 還會收費嗎?
GitHub 不對自架執行器按分鐘收費,而第三方執行器是以自架執行器身分註冊,因此您移轉出去的分鐘數 將不再出現在 GitHub 帳單上 (GitHub Actions 計費說明)。GitHub 仍會收取:
- 您方案中的席次費用;
- 超出內含額度、由其保存的建置產物與快取儲存空間;
- 留在 GitHub 託管執行器上、超出您方案內含用量的作業,且內含額度不會退還。
試行期間,您會收到兩張帳單。各供應商計算建置分鐘數的方式不同: GitHub 將每個作業無條件進位到整分鐘,有些供應商則按秒計量。要估算切換前後的用量,請使用 GitHub Actions 成本計算器。CRACI 只對 建置分鐘數收費:每 vCPU 分鐘 $0.002(預設 2 vCPU 執行器為 $0.004),按秒計量,無月費。
資安隔離:應向任何供應商詢問的問題
| 問題 | 為何重要 |
|---|---|
| 每個作業一台虛擬機器,還是共用主機上的容器? | 共用主機會讓遭入侵的作業能觸及其相鄰作業 |
| 機器是否會在作業結束後銷毀? | 持續存在的機器會將檔案、憑證與處理程序帶入下一個作業 |
| 硬體位於何處,由誰維運? | 資料所在地、司法管轄權,以及您與客戶的合約 |
| 供應商會儲存哪些資料,保存多久? | 紀錄、快取與網路資料可能包含敏感內容 |
| 它持有哪些認證? | 您的廠商審查會問到 |
| 您能控管對外連線嗎? | 阻止機密透過惡意套件外洩 |
| 它的 GitHub App 可以讀取與變更什麼? | 應用程式的權限適用於您安裝它的每個儲存庫 |
GitHub 表示,公開儲存庫幾乎永遠不應使用自架執行器,因為任何人都能開啟 pull request 並入侵該環境;而即時(just-in-time)執行器在移除前最多只執行一個作業 (GitHub 安全使用 參考文件)。每個作業使用全新虛擬機器,就能解決大部分這類疑慮。
CRACI 的回答:每個作業都在歐洲裸機基礎架構上、各自隔離的虛擬機器中執行。CRACI Corporation Oy 針對 CRACI 平台開發與維運的資訊安全管理系統, 已取得 Into Certification 核發的 ISO/IEC 27001 認證,詳情請見 Trust Center。CRACI 會儲存建置中繼資料、套件資料、網路追蹤、SBOM、 來源證明、快取與稽核紀錄,但絕不儲存您的原始碼。請參閱 CRACI 可以存取哪些內容 與資安。
先在一個儲存庫上試用
- 挑選一個具代表性、經常執行 Linux 工作流程的儲存庫,而不是版本發布管線。
- 在 GitHub 託管執行器上記錄基準:最近 30 次執行的執行時間與佇列等候時間中位數,以及計費分鐘數。
- 只在該儲存庫上安裝供應商的 GitHub App。
- 在分支上透過儲存庫變數切換一個作業。
- 至少執行十次,並將前三次視為快取暖機而捨棄。
- 比較執行時間、佇列等候時間、快取命中率、失敗次數與成本;檢查紀錄、OIDC 與對外呼叫。
- 變更變數以復原,並確認作業回到 GitHub 託管執行器。
| 指標 | GitHub 託管基準 | 供應商 | 通過門檻 |
|---|---|---|---|
| 作業執行時間中位數 | 您的目標,例如縮短 30% | ||
| 佇列等候時間中位數 | 不比基準差 | ||
| 暖機後的快取命中率 | 與基準相同 | ||
| 非程式碼造成的失敗執行 | 無 | ||
| 每次執行成本 | 低於基準 | ||
| OIDC、允許清單與對外呼叫 | 全部正常運作 |
請用您自己的工作流程衡量速度。每家供應商都會公布自己的數據,而唯一能決定您情況的數字, 是來自您自己管線的那一個。
CRACI 的定位
CRACI 是 GitHub Actions 執行器。它取代的是執行器,而不是 GitHub Actions:作業以
runs-on: craci 移轉,規格與映像檔透過 cracicorp/setup@v1 或組織執行器範本設定,
執行紀錄仍會顯示在 GitHub 中。憑藉更快的硬體、更短的佇列等候時間與快取,CRACI 的建置速度約為 GitHub 託管執行器的兩倍。
選擇它而非其他供應商的理由,在於每個作業留下的東西:一份記錄建置所擷取內容的 SBOM,附有 完整性狀態,並在採失效即封鎖的對外連線政策下記錄。docs.craci.com 也提供一段給程式碼代理(coding agent)使用的提示詞, 可為您的工作流程提出以作業為單位的移轉計畫。請參閱 CI/CD 整合。
CRACI 不適用的情況
- 您需要 macOS 或 Windows 執行器:它們已列入 CRACI 的產品藍圖。
- 您使用 GitHub Enterprise Server,而 CRACI 不支援它。
- 您的 CI 是 GitLab CI 或 Jenkins:兩者都已列入產品藍圖。
- 執行器必須位於您自己的雲端帳戶中:客戶自行託管執行器已列入產品藍圖。RunsOn 與 WarpBuild 的 自帶雲端選項目前就能做到;請參閱 CRACI 與 RunsOn 比較與 CRACI 與 WarpBuild 比較。
- 您的主要目標是 CI 可觀測性與除錯;請參閱 CRACI 與 Avrea 比較。若要 自行維運執行器,請參閱代管與自架執行器比較。
更換執行器供應商:常見問題
要改用其他 GitHub Actions 執行器供應商,需要變更哪些地方?
安裝供應商的 GitHub App,再將作業的 runs-on 標籤改為供應商的標籤。工作流程、觸發條件、機密與 GitHub 介面都維持不變。在移轉重要作業之前,請先確認執行器映像檔、快取、對外 IP 位址、使用 OIDC 的雲端信任政策、備援機制與計費方式。
我的 GitHub Actions 快取會延續到新的執行器供應商嗎?
取決於供應商從哪裡提供快取。如果其執行器使用 GitHub 的快取服務,既有項目就能還原。如果它從執行器旁的儲存空間提供快取 API,快取通常會從空的開始,並在最初幾次執行時逐步填滿。請詢問供應商採用哪種模式,以及在其執行器上寫入的項目是否對 GitHub 託管執行器可見。
Docker 層快取在第三方執行器上能運作嗎?
可以,有三種機制可選:使用 Actions 快取的 BuildKit type=gha 後端;可在任何執行器上運作、採用 type=registry 的登錄庫快取;或由供應商保存在其執行器旁的層快取或永久磁碟。
Linux 作業移轉後,可以把 macOS 與 iOS 建置留在 GitHub 上嗎?
可以。執行器是以作業為單位選擇,因此在同一個工作流程中,Linux 作業可以在供應商上執行,macOS 作業則留在 GitHub 託管執行器上。以 needs: 串連它們,並透過由 GitHub 儲存的 actions/upload-artifact 與 actions/download-artifact 傳遞檔案。
如果第三方執行器停擺,作業會怎樣?有備援機制嗎?
GitHub 沒有內建執行器標籤之間的備援機制。若沒有任何上線中的執行器符合作業的標籤,作業會一直留在佇列中,並在 24 小時後失敗。請將標籤放在儲存庫或組織變數中,讓切換回來只需一項變更;設定 timeout-minutes;並詢問各供應商是否提供自己的備援機制。
機密與 OIDC 在第三方執行器上還能運作嗎?
可以。機密由 GitHub 儲存,並在作業開始時傳送到執行器;OIDC 權杖也是由 GitHub 簽發,因此 id-token: write 在任何執行器上都能運作。需要注意的是:在第三方執行器上,權杖的 runner_environment 宣告為 self-hosted,因此要求 github-hosted 的雲端信任政策會拒絕該作業。
改用其他執行器供應商後,GitHub 還會向我收取分鐘數費用嗎?
移轉出去的作業不會。第三方執行器是以自架執行器的身分向 GitHub 註冊,而 GitHub 表示自架執行器不按分鐘收費。GitHub 仍會收取席次費用、超出內含額度的儲存空間費用,以及留在 GitHub 託管執行器上之作業的費用。供應商則會另外收取自己的分鐘數費用。
如何固定執行器映像檔,避免它在我不知情時變動?
ubuntu-latest 會依 GitHub 的時程更新,而 ubuntu-24.04 只固定作業系統版本,不固定其上的套件版本。請在作業內固定重要的項目:以明確版本指定 setup actions,並以摘要值(digest)指定容器映像檔。請詢問各供應商允許您固定哪些項目;執行器應用程式本身則必須持續更新,才能與 GitHub 正常運作。
在第三方執行器上,作業之間如何隔離?
各供應商不同。請詢問每個作業是否擁有自己的虛擬機器,還是共用主機上的容器;機器是否會在作業結束後銷毀;以及供應商事後會保留哪些資料。每個作業使用全新虛擬機器是常見模式中最強的一種,因為上一個作業不會留下任何東西給下一個作業。
如何先在一個儲存庫上測試執行器供應商?
在一個儲存庫上安裝供應商的 GitHub App,在分支上透過儲存庫變數切換一個經常執行的 Linux 作業,至少執行十次,並與 GitHub 託管的基準比較執行時間、佇列等候時間、快取命中、失敗次數與成本。只要變更變數即可復原。