本文聚焦在 「程式碼推上 GitHub → 自動 build → 自動部署到 Cloud Run」 這條 CD 管線的設定。
⚠️ 安全提醒:文中所有專案 ID、專案編號、Service Account email、WIF 路徑等敏感資訊,都以佔位符(
<...>)取代。實際操作時請替換成自己的值,切勿把明碼寫進公開文件。
整體流程
整條 CD 管線只要一個 git push 就會自動跑完:
flowchart TD
A([git push origin main]) --> B[GitHub Actions 觸發]
B --> C["① 透過 WIF 認證 GCP
(免金鑰)"]
C --> D["② docker build 映像檔"]
D --> E["③ docker push 到
Artifact Registry"]
E --> F["④ gcloud run deploy
部署到 Cloud Run"]
F --> G(["瀏覽器開 Cloud Run URL
看到網站 🎉"])
💡 核心觀念:用 Workload Identity Federation(WIF) 建立 GitHub 與 GCP 的信任關係,GitHub Actions 不需要持有任何金鑰即可取得部署權限。
前置準備
1. 啟用必要的 GCP API
於 GCP Console 啟用以下 API:
- Cloud Run Admin API
- Artifact Registry API
- Cloud Build API
- Service Networking API
- Secret Manager API
2. 建立 Artifact Registry(存放 Docker 映像檔)
| 設定 | 值 |
|---|---|
| Format | Docker |
| Region | asia-east1 |
| Mode | Standard |
完整路徑格式:
1 | asia-east1-docker.pkg.dev/<PROJECT_ID>/<REPOSITORY> |
3. 建立 Service Account 並授予角色
建立一個專供 GitHub 推送/部署使用的 Service Account,逐一加上以下 3 個角色:
| 角色 | 用途 |
|---|---|
| Artifact Registry 寫入者(Writer) | 推送映像檔(⚠️ 不是「服務代理」) |
| Cloud Run 管理員 | 部署服務 |
| 服務帳戶使用者 | 部署時模擬執行身分 |
設定 Workload Identity Federation(免金鑰認證)
建立 Workload Identity Pool
- Pool ID:
github-pool
新增 OIDC Provider
| 設定 | 值 |
|---|---|
| Provider type | OpenID Connect (OIDC) |
| Provider Name | github-provider |
| Issuer URL | https://token.actions.githubusercontent.com |
屬性對應(Attribute Mapping)
| OIDC | |
|---|---|
google.subject |
assertion.sub |
attribute.repository |
assertion.repository |
attribute.repository_owner |
assertion.repository_owner |
屬性條件(關鍵安全設定)
限制只有自己的 GitHub 帳號/組織能使用此 Provider:
1 | assertion.repository_owner == '<GITHUB_OWNER>' |
綁定 Service Account 與 WIF
到 Service Account 的 「具備存取權的主體(Principals with access)」 分頁,點 「授予存取權」,新增主體:
1 | principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/github-pool/attribute.repository/<GITHUB_OWNER>/<REPO_NAME> |
角色:Workload Identity 使用者
📌 容易搞混的地方:「這個 SA 能做什麼」要在 IAM 頁編輯;「誰能用這個 SA」要在 SA 的「具備存取權的主體」頁編輯。
GitHub Secrets 設定
到 GitHub repo 的 Settings → Secrets and variables → Actions,新增 3 個 Secrets(實際值請填自己的,勿外流):
| Name | 內容說明 |
|---|---|
GCP_PROJECT_ID |
你的 GCP 專案 ID |
GCP_WIF_PROVIDER |
projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/github-pool/providers/github-provider |
GCP_SA_EMAIL |
部署用 Service Account 的 email |
GitHub Actions Workflow
於 .github/workflows/push-image.yml:
1 | name: Build, Push and Deploy to Cloud Run |
觸發部署
1 | git add . |
推送後,到 GitHub repo 的 Actions 分頁看執行狀況;跑完後開 Cloud Run 配發的 URL 即可看到部署結果。
踩過的坑(CD 相關)
🕳️ 坑 1:組織政策禁止建立 SA 金鑰
錯誤訊息
1 | 服務帳戶金鑰建立功能已停用 |
解法:改用 Workload Identity Federation,完全不用金鑰 —— 這其實是更安全的業界最佳實踐。
🕳️ 坑 2:Artifact Registry 角色加錯
錯誤訊息
1 | denied: Permission 'artifactregistry.repositories.uploadArtifacts' denied |
| 錯誤的角色 | 正確的角色 |
|---|---|
| Artifact Registry 服務代理(Service Agent) | Artifact Registry 寫入者(Writer) |
🕳️ 坑 3:授予存取權的入口位置
要在 SA 詳情頁分頁列最右邊的「具備存取權的主體 / Principals with access」,才會看到正確的「+ 授予存取權」按鈕,而不是「權限」分頁。
🕳️ 坑 4:Cloud Run 要求容器必須監聽 HTTP port
只「跑完就結束」的容器會一直重啟。Cloud Run 是「無狀態 HTTP 服務」,容器必須監聽 port(預設 8080)。
安全提醒
- 🔒 切勿把專案 ID、專案編號、SA email、WIF 完整路徑等寫進公開文件;統一以 Secrets 管理。
- 🔒 WIF 的屬性條件(
repository_owner)務必設定,避免其他人的 repo 冒用你的 Provider。 - 🔒
permissions: id-token: write是 WIF 運作的必要條件,別漏掉。
留言