GitHub Actions 自動部署(CD)到 GCP Cloud Run 完整教學
本文聚焦在
本文聚焦在「「程式碼推上 GitHub → 自動 build → 自動部署到 Cloud Run」 這條 CD 管線的設定。
為了安全,所有專案⚠️ 安全提醒:文中所有專案 ID、專案編號、Service Account email、WIF路徑等敏感資訊都以佔位符(路徑等敏感資訊,都以佔位符(<...>)取代,取代。實際操作時請替換成自己的值,切勿把明碼寫進公開文件。切勿把明碼寫進公開文件。
整體流程
整條 CD 管線只要一個
git push就會自動跑完:
git push origin main
|│
v▼
GitHub Actions 觸發
|│
+-├─ ① 透過 Workload Identity FederationWIF 認證 GCP(免金鑰)
+-├─ ② docker build 映像檔
+-├─ ③ docker push 到 Artifact Registry
+-└─ ④ gcloud run deploy 部署到 Cloud Run
|│
v▼
瀏覽器開 Cloud Run URL 看到網站 ```
💡 核心觀念:用
**Workload Identity Federation(WIF)**建立 GitHub 與 GCP 的信任關係,GitHub Actions 不需要持有任何金鑰即可取得部署權限。---
前置準備
1. 啟用必要的 GCP API
於 GCP Console 啟用:啟用以下 -API:
2. 建立 Artifact Registry(存放 Docker 映像檔)
asia-east1`east1
完整路徑格式:
asia-east1-docker.pkg.dev/<PROJECT_ID>/<REPOSITORY>
```
3. 建立 Service Account 並授予角色
建立一個專供 GitHub 推送/部署使用的 Service Account,逐一加上以下 3 個角色:個角色:
設定 Workload Identity Federation(免金鑰認證)
建立 Workload Identity Pool
- Pool
ID:`ID:github-pool`pool
新增 OIDC Provider
github-provider`provider
https://token.actions.githubusercontent.com`com
屬性對應(Attribute Mapping)
google.subject`subject
assertion.sub
attribute.repository
assertion.sub`repository
attribute.repository`repository_owner
assertion.repository_owner
屬性條件(關鍵安全設定)
限制只有自己的 GitHub 帳號/組織能使用此 Provider:
assertion.repository_owner == '<GITHUB_OWNER>'
```
綁定 Service Account 與 WIF
到 Service Account 的「**的 「具備存取權的主體(Principals with access)**」 分頁,點「**授予存取權**」點 「授予存取權」,新增主體:
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 ,新增 3 個 ->→ Secrets and variables ->→ Actions`ActionsSecrets(Secrets(實際值請填自己的,勿外流):
GCP_PROJECT_ID
GCP_WIF_PROVIDER
projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/github-pool/providers/github-provider`provider
GCP_SA_EMAIL
GitHub Actions Workflow
於 `.github/workflows/push-image.:yml`yml
name: Build, Push and Deploy to Cloud Run
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
id-token: write # WIF 取得 OIDC token 必須
env:
REGION: asia-east1
REPOSITORY: <REPOSITORY>
IMAGE_NAME: <IMAGE_NAME>
SERVICE_NAME: <SERVICE_NAME>
jobs:
build-push-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Authenticate to GCP
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_SA_EMAIL }}
- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v2
- name: Configure Docker auth
run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet
- name: Build Docker image
run: |
docker build -t ${{ env.REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .
- name: Push to Artifact Registry
run: |
docker push ${{ env.REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy ${{ env.SERVICE_NAME }} \
--image=${{ env.REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
--region=${{ env.REGION }} \
--platform=managed \
--allow-unauthenticated \
--port=8080 \
--memory=256Mi \
--cpu=1 \
--min-instances=0 \
--max-instances=2
- name: Show service URL
run: |
URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} --region=${{ env.REGION }} --format='value(status.url)')
echo "Service URL: $URL"
```
觸發部署
git add .
git commit -m "feat: setup CI/CD pipeline"
git push origin main
```
推送後,到 GitHub repo 的 **Actions**Actions 分頁看執行狀況,分頁看執行狀況;跑完後開 Cloud Run 配發的 URL 即可看到部署結果。
踩過的坑(CD 相關)
🕳️ 坑 1:組織政策禁止建立 SA 金鑰
錯誤訊息
服務帳戶金鑰建立功能已停用
組織政策:iam.disableServiceAccountKeyCreation`)。disableServiceAccountKeyCreation
解法:
解法:改用 Workload Identity Federation,完全不用金鑰 —— 這其實是更安全的業界最佳實踐。
🕳️ 坑 2:Artifact Registry 角色加錯
錯誤訊息
denied: Permission 'artifactregistry.repositories.uploadArtifacts' denied`。denied
|
🕳️ 坑 3:授予存取權的入口位置
要在 SA 詳情頁分頁列最右邊的「**詳情頁分頁列最右邊的「具備存取權的主體 / Principals with access**」access」,才會看到正確的「+ 授予存取權」按鈕,而不是「權限」分頁。
🕳️ 坑 4:Cloud Run 要求容器必須監聽 HTTP port
只「跑完就結束」的容器會一直重啟。Cloud Run 是「無狀態 HTTP 服務」,容器必須監聽容器必須監聽 port(port(預設 `8080`8080)。
安全提醒
repository_owner)務必設定,避免其他人的 repo 冒用你的 Provider。
permissions: id-token: write`write 是 WIF 運作的必要條件,