每次上傳新的 Docker Image 到 Google Cloud Run 時,都要另外打 gcloud
指令實在是有點繁瑣,本篇會與你分享筆者怎麼使用 GitHub Action,設定 Docker 自動容器話與 Cloud Run 的自動部署,不用再打部署指令,簡化開發流程!
本文同時發佈於我的個人部落格
這是筆者第一篇程式的技術學習筆記,所以在解釋跟教學步驟上會略顯繁瑣、或是有需改善的地方,還請大佬或是讀者不吝指教。
而筆者也將本文章的難度設定成入門門檻,所以會含括一些前置步驟的教學,如果你已經設定過可以直接略過!
GitHub Action 是 Github 的 CI 功能,簡而言之就是把 commit 後的 Build、Test、Deploy 的流程全都自動化,不用手動另外執行( 就是做 Jenkins 的工作 )
這位前輩的文章有更完整的解釋:GitHub Actions 基本介紹 - 開始自動化 workflow 的第一步 - iT 邦幫忙
那麽 GitHub Action 對於要部署到 Cloud Run 的專案有什麼好處呢?透過設定 GitHub Action,你可以將這些過程全都自動化:
而且是在每次新的 commit 後就會自動完成,你只需專注做程式碼的開發即可,是不是超方便的?
不過補充一下,GitHub Actions 是有額度限制的,超過額度後要付費才能繼續用,以下是 GitHub Action 的免費使用額度,收費標準以執行時間為單位:
但在進到教學正文之前,會需要你先做以下三件事:
如果做好前置作業,就照著下文設定你的 GitHub Action 吧!整個過程大約花費 10 分鐘。
本篇文章會教學用 Google 官方的 YAML,而針對 Auth 部分,會需要用到專案的 Workload Identity Federation 來進行 GitHub Action 的 OIDC 驗證,因此,這段會先教學如何建立 GCP 專案的 Identity federation。
下文會用 gcloud
指令進行操作,如果你的電腦還沒有裝 Google Cloud SDK,或之前都是用 GUI 網頁來部署的話,可以照著這篇文章的教學安裝 SDK 並完成設定:
如何安裝 Google Cloud SDK 命令行工具?macOS 就是那麼簡單 - Python 編程.圖表
// 雖然上篇文章是 MacOS 版本的,但安裝過程跟 Windows 類似~
安裝好 SDK 並登入管理 GCP 的 Google 帳號後,打開 Terminal 先設定一個環境變數,省去重複打編號的過程:
export PROJECT_ID="你的專案 ID"
接著創建一個服務帳戶,你可以自訂第一個引號的帳戶 ID:
( 如果你已經有一個 GCP 專案服務帳戶,可以略過這步,並記下你現有專案服務帳戶的 email 位置 )
gcloud iam service-accounts create "github-service-account" \
--project "${PROJECT_ID}"
// 如果你的 Cloud Run 專案會需要使用其他 Google Cloud 的資源( 像是 Cloud Storage、Cloud SQL )記得為服務帳戶新增相對應的權限,你可以用 gcloud 指令或是到 GCP 網頁版→ IAM 與管理內新增權限。
再來新增一個 Workload Identity 集區( Workload Identity Pool )你可以自訂 “github-pool” 跟 display-name 的名稱:
gcloud iam workload-identity-pools create "github-pool"
--project="${PROJECT_ID}" \
--location="global" \
--display-name="GitHub Deployment Poll"
接著輸入這段指令取得集區的編號:
gcloud iam workload-identity-pools describe "github-pool"
--project="${PROJECT_ID}" \
--location="global" \
--format="value(name)"
輸出會像這樣 projects/111111111/locations/global/workloadIdentityPools/my-pool
,將這組集區編號設定成環境變數,方便等等重複使用:
export WORKLOAD_IDENTITY_POOL_ID="..."
接著為集區新增一個 Provider:
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="github-pool" \
--display-name="Github Provider" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--issuer-uri="https://token.actions.githubusercontent.com"
p.s. 如果你要建立全部 repo 權限的 Provider,attribute-mapping 要改成這個:
--attribute-mapping="google.subject=assertion.sub,attribute.repository_owner=assertion.repository_owner"
再來為服務帳號綁定工作集區的使用者 IAM 權限,先設定一個環境變數,設定成你的 GitHub Repo 名稱:
export REPO="github_username/repo_name"
再打這段指令:
gcloud iam service-accounts add-iam-policy-binding "github-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
--project="${PROJECT_ID}" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"
如果你要套用於全部 repo 的 GitHub Action,先設定一個 OWNER 環境變數:
export OWNER="username"
再修改前兩個的指令的 member 參數內容:
--member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository_owner/${OWNER}"
最後輸入以下指令,拿到集區 Provider 的資源名稱並記下來:
gcloud iam workload-identity-pools providers describe "my-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="my-pool" \
--format="value(name)"
你應該會得到類似以下的名稱,稍後新增 repo secret 時會用到:
projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider
由於上文設定的 Google Cloud 資源名稱跟服務帳戶都是機密資訊,無論 repo 是否為 public 還是 private,都不建議直接寫在 GitHub Action 的 YAML 檔上面。
而針對不想公開在網路上,但又需要用在 GitHub Action 內的敏感資訊( 像是 GCP 集區名稱、密鑰、資料庫網址 )可以設定成 repo 的 secret,讓 GitHub Action 可以用類似環境變數的方式存取,同時讓敏感資訊不會直接暴露在 YAML 上。
所以接下來要新增 Cloud Run 自動部署所需的 secret。先打開你的 GitHub Repository 頁面,進入 Setting,點選左側選單 Secrets and variables → Action:
點選 New repository secret,新增兩個 secret:
WIF_PROVIDER
: 步驟一最後取得的資源名稱WIF_SERVICE_ACCOUNT
: 步驟一設定的服務帳戶( 包含 @ 之後的網域 )最後,我們就能沿用 Google 官方寫好的 Cloud Run Deploy YAML 檔到 repo 內,回到你的 repo 頁面 → Actions:
搜尋 Cloud Run,並點選 “Build and Deploy to Cloud Run” :
接著,修改 51 ~ 55 行的環境變數,根據註解自訂成你的專案編號、Cloud Run 服務名稱跟地區,地區可以使用 asia-east1
也就是台灣的機房:
另外記得要稍微改一下 109 行的 Docker image 網址,改成:
image: ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}/${{ env.SERVICE }}:${{ github.sha }}
// p.s. 筆者用官方的 YAML 部署時,就遇到了 image 網址少了一個 image name 參數的錯誤,上面的解法是參考這篇的討論:
Docker push "Missing image name"-error when pushing to GCP Artifact Registry from Github Actions
完成所有修改後,按右上方的 Commit change、新增 GitHub Action 的 YAML 檔就大功告成:
之後每次 commit 到 repo 的 main 分支就會自動執行 GutHub Action,將程式打包成 Docker image 並部署到 Cloud Run上了:
以上就是設定 Cloud Run 自動部署的 GitHub Action 操作教學了,再重新概述一下三個步驟:
透過以上三步,就能設定 Repo 的 Action 了,你也可以另外加入測試等其他步驟,完善你的 CI/CD 流程,不過使用時要注意 GitHub Action 的額度限制喔。
筆者會有寫這篇教學的靈感,是因為趁暑假自學 Web 開發的技術時,剛好碰到 Serverless 的部署,我希望能自動化 Cloud Run 部署的工作,也趁機學一下 GitHub Action 的原理跟實作,只是網路上的文章都是舊版的部署方法,便記錄新版 Google 官方的 Cloud Run Action 怎麼設定。
當然,筆者在這篇是直接用 Google 官方寫的 YAML 檔,也沒有加入 Unit test 等項目,所以沒有發揮用 Actions 做 CI/CD 的功能,未來若有機會進一步學到這塊的話,會再撰寫文章跟大家分享我的淺見所學。
希望這篇文章有幫到你的開發!
本文同時發佈於我的個人部落格
本篇教學主要是受到下文的啟發,感謝 Robby 前輩寫的筆記文:
GCP - 使用 Github Actions 部署 React 到 Cloud Run | Robby - 全端的 Front-End Engineer - 點部落
GitHub - google-github-actions/auth: A GitHub Action for authenticating to Google Cloud.