跳至主要內容
GCP 核心服務 — 第 4/10 篇

Cloud Run 入門:部署、擴縮、權限與 VPC 怎麼設定

內文字級

Cloud Run 入門:部署、擴縮、權限與 VPC 怎麼設定
更新:2026-10-07

手上已經有一個能接 HTTP 請求的容器,卻不想為它維護 VM 或 Kubernetes 叢集時,Cloud Run 往往是最快能上線的選擇。

它會處理 HTTPS 端點、負載分配和執行個體擴縮,但「無伺服器」不等於不用做維運。容器啟動速度、並發數、IAM、最小實例、VPC 路徑和下游連線,仍然會影響延遲、穩定性與帳單。這篇會沿著一次部署的完整流程,把這些設定串起來。

Cloud Run 交付與擴縮流程:Source 經 Build 產生 Container image,部署成 Cloud Run Service 下的 Revision A 與 Revision B;穩定服務網址可切分流量,各 Revision 依請求並發啟動多個 Instance,閒置時縮到零,也可用 Min instances 換取較低冷啟動;Secret Manager 與 VPC egress 提供受控依賴

每次部署都會產生不可變的 Revision,Service URL 再把流量導向指定版本,所以 Canary 和回滾不必更換網址。執行個體會依請求和並發量擴縮,沒有流量時預設能縮到零;若保留 minimum instances 來減少冷啟動,就要支付閒置期間的費用。Secret 和私有網路連線則在執行階段注入,不必放進映像。

一、先分清楚 Service、Job 和 Worker pool

Cloud Run 可以直接執行符合 container runtime contract 的映像,也能從原始碼協助建置。依工作是否需要 HTTP 端點,以及何時算完成,可以分成三種資源:

資源執行方式常見用途
Services透過負載平衡端點接收 HTTP/gRPC 請求API、網站、Webhook、推送式事件
Jobs啟動一批 tasks,全部完成後結束資料轉換、報表、排程與一次性作業
Worker pools持續執行、沒有負載平衡 HTTP 端點Kafka、Pub/Sub 等 pull-based worker

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

Service 和 Job 會涵蓋大多數入門情境。Worker pool 需要設定實例數,若要依 queue backlog 等外部指標調整,還得另外配置 autoscaling,因此不會是單純 HTTP API 的第一選擇。

二、第一代還是第二代執行環境?

Cloud Run Service 有第一代和第二代執行環境。若沒有指定,平台會依使用的功能選擇;Job 和 Worker pool 則固定使用第二代。兩代價格相同,差別主要在啟動特性和 Linux 相容性:

特性Gen1Gen2
基礎技術gVisor 沙盒(Google 自家的輕量隔離層)MicroVM(迷你虛擬機,完整 Linux 核心)
系統呼叫受限(不支援全部 syscall)完整支援
冷啟動速度較快(Bursty 流量佳)較慢
CPU 效能標準更高(適合計算密集)
記憶體下限128 MiB512 MiB
網路吞吐量標準更高
NFS 支援不支援支援

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

如果需要完整 syscall、NFS、cgroup、較高 CPU 或網路效能,選第二代。第一代則適合流量零散、經常從零擴展,而且實測後確定它的啟動時間較短的 Service。若應用記憶體低於 512 MiB,也只能使用第一代。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  subgraph CHOOSE["選擇執行環境"]
    direction TB
    START["盤點容器的系統呼叫、<br/>效能與啟動特性"] --> REQUIRED{"需要完整 Linux syscall、<br/>NFS、較高 CPU<br/>或網路效能?"}
    REQUIRED -->|"是"| GEN2["選第二代<br/>完整 Linux 相容性"]
    REQUIRED -->|"否"| BURST{"是否為短暫、<br/>bursty 工作負載,<br/>且極度在意冷啟動?"}
    BURST -->|"是"| GEN1["評估 Gen1<br/>較輕量但 syscall<br/>與功能受限"]
    BURST -->|"否或不確定"| AUTO["使用預設自動選擇<br/>讓 Cloud Run<br/>依功能需求判斷"]
  end
  subgraph TEST["用實際容器驗證"]
    direction TB
    VERIFY["量測啟動時間、系統相容性<br/>與尖峰負載"] --> CONFLICT{"出現 syscall、記憶體<br/>或效能瓶頸?"}
    CONFLICT -->|"是"| ADJUST["切換 Gen2 或調整資源<br/>再重新測試"]
    CONFLICT -->|"否"| DONE["保留選擇並記錄基準數據"]
  end
  GEN1 --> VERIFY
  GEN2 --> VERIFY
  AUTO --> VERIFY

第二代適合需要完整 Linux 功能或持續效能的服務;第一代則可能在部分 scale-from-zero 情境啟動得更快。沒有一個選項適合所有容器,應以實際映像量測啟動時間、系統相容性和尖峰負載。

三、資源上限先知道,但不要直接照上限配置

項目限制
最大 vCPU8 個(每實例)
最大記憶體32 GiB(每實例)
最大請求逾時60 分鐘
最大啟動逾時4 分鐘
每實例最大並發請求1,000(主控台預設 80;gcloud/Terraform 新建服務時是 80 × vCPU 數)
最大環境變數1,000 個
HTTP/1 請求大小32 MiB

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

請求逾時和啟動逾時是兩件事。前者預設 5 分鐘,最長可設 60 分鐘,而且包含為該請求啟動容器所花的時間;後者要求執行個體在啟動後 4 分鐘內開始監聽。若初始化需要載入大型模型或建立很多連線,可以先改善映像和啟動流程,再評估 startup CPU boost。

32 MiB 限制適用於 HTTP/1 請求;使用 HTTP/2 server 時沒有這項請求大小上限。HTTP/1 回應若採 streaming 或 chunked transfer,也不能只用表格中的數字判斷。

Cloud Run 建立服務表單「容器」設定的「資源」區塊,記憶體下拉選單展開,可見選項由 128 MiB、256 MiB、512 MiB(已選)、1 GiB、2 GiB、4 GiB、8 GiB 到 16 GiB,清單可再往下捲;右側 CPU 欄位為 1,說明為分配給此容器每個執行個體的 vCPU 數量

CPU 和記憶體都是每個執行個體的配置,不是整個 Service 共用的總量。選擇時要一起看單一請求用量、 concurrency 和程式能否有效使用多核心;配置越大,每個執行個體的計費也越高。

四、計費模式決定空閒時還有沒有 CPU

Cloud Run Service 有 request-based 和 instance-based 兩種計費設定。它們常和 minimum instances 混在一起談,但其實回答的是不同問題:計費模式決定執行個體存活時,沒有請求的那段時間是否持續分配 CPU;minimum instances 則決定平台至少保留多少個暖機實例。

Cloud Run 建立服務表單的「帳單」區塊,兩個單選:「以要求為依據」(已選,只有在處理要求時才會收費,如果沒有要求 CPU 會受到限制)與「以執行個體為依據」(針對執行個體的整個生命週期收費,各執行個體可以全程完整使用 CPU)

Request-based billing 只在啟動、關閉和處理請求時對執行個體資源計費,請求之外 CPU 會受限。 Instance-based billing 則按整個執行個體生命週期計費,空閒時仍可使用 CPU。前者適合零散流量;後者適合穩定流量或需要短暫背景處理的服務。

Request-based billing(預設)

CPU 只在請求處理期間分配,空閒時釋放:

啟動/請求進來 → CPU 分配 → 處理完成 → CPU 受限

適合:

  • Bursty / 間歇性流量
  • 純 HTTP API
  • 無背景任務需求

Instance-based billing

即使沒有請求,CPU 也持續分配給執行中的實例:

實例啟動 → CPU 持續分配(可做背景工作)→ 實例停止 → 收費結束

適合:

  • 回應後仍需完成短暫背景工作的服務
  • 流量穩定、實例大部分時間都在工作的應用
  • 需要讓 agent 或監控程式在請求之外繼續執行的容器

開啟 instance-based billing 並不會讓實例永久存在。Autoscaler 仍可能把閒置實例移除;若背景工作必須持續執行,還要搭配 minimum instances,或改用 Job、Worker pool、Cloud Tasks 等更符合工作模型的服務。

設定方式:

gcloud run deploy my-service \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/my-app \
  --no-cpu-throttling

五、Minimum instances 能減少冷啟動,但不會讓它完全消失

縮容至零(預設行為)

預設 minimum instances 為 0,沒有流量時可以縮到零。下一個請求到達後,平台要重新啟動執行個體,延遲取決於映像大小、runtime、初始化工作和網路依賴,不能固定假設是幾秒。

保留暖機實例

gcloud run deploy my-service \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/my-app \
  --min=1 \
  --max=10
  • --min=1:Service 至少保留 1 個暖機實例
  • --max=10:Service 最多擴展到 10 個實例,用來保護資料庫或其他下游資源

這裡使用的是 Service 層級的設定,也是新服務較建議的做法。Revision 層級另有 --min-instances 和 --max-instances,不要混著用,否則帶 tag 的舊 Revision 也可能各自保留實例並產生費用。

費用說明:

  • Request-based billing 下,沒有請求的暖機實例按較低的 idle 費率計費
  • Instance-based billing 下,執行個體從啟動到停止都按完整資源費率計費

Minimum instances 是 best-effort 的暖機目標,執行個體仍可能因維護或故障而重啟,所以它只能降低冷啟動機率,不能取代重試和逾時設計。會讓使用者直接等待的登入、結帳等路徑,才值得拿實測的啟動延遲和閒置成本比較;測試環境或可延後的背景工作通常可以維持在零。

Cloud Run 建立服務表單的「服務資源調度」區塊,選「自動調整資源配置」,下方兩個欄位「執行個體數量下限」填 0、「執行個體數量上限」留空,提示文字為「設為 1 可以減少冷啟動的次數」,最下方另有「手動調整資源配置」選項

Minimum instances 設為 0 時,沒有流量可以縮到零;設為 1 以上則保留暖機容量,以較固定的閒置成本換取較少的冷啟動。Maximum instances 則能限制服務對下游資料庫、第三方 API 或專案 quota 的壓力。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart LR
  START["把 CPU 與實例數<br/>分成兩條決策軌"]
  subgraph CPU["CPU 計費模式"]
    direction TB
    BACKGROUND{"無請求時仍需背景工作、<br/>輪詢或常駐 agent?"}
    BACKGROUND -->|"否"| REQUEST["Request-based<br/>處理請求時計 CPU"]
    BACKGROUND -->|"是"| INSTANCE["Instance-based<br/>存活期間持續有 CPU"]
  end
  subgraph SCALE["最小實例數"]
    direction TB
    LATENCY{"能接受第一個請求的<br/>冷啟動?"}
    LATENCY -->|"可以"| ZERO["minimum instances = 0<br/>無流量時縮到零"]
    LATENCY -->|"不可以"| WARM["minimum instances ≥ 1<br/>保留暖機實例"]
    WARM --> COST{"已接受 24 小時<br/>閒置成本?"}
    COST -->|"否"| TUNE["優化初始化或<br/>降低最小實例"]
    COST -->|"是"| READY["保留暖機設定"]
  end
  START --> BACKGROUND
  START --> LATENCY
  REQUEST --> LIMIT["設定 maximum instances、並發、<br/>CPU 與記憶體上限"]
  INSTANCE --> LIMIT
  ZERO --> LIMIT
  TUNE --> LIMIT
  READY --> LIMIT
  LIMIT --> OBSERVE["監控延遲、實例數與費用<br/>再依流量調整"]

CPU 模式回答「活著但沒請求時還有沒有 CPU」,minimum instances 回答「至少要留幾個實例」。兩者互相獨立,必須連同冷啟動、背景工作與閒置費用一起決定。

六、部署前先決定映像、Region 和公開範圍

Cloud Run 建立服務表單頂部,部署來源三選一:「依據現有的容器映像檔部署單一修訂版本」(已選,含 Artifact Registry、Docker Hub)、「從存放區持續部署(原始碼或函式)」(GitHub、GitLab、Bitbucket)、「使用內嵌編輯器建立函式」;容器映像檔網址填入 us-docker.pkg.dev/cloudrun/container/hello;右側費用摘要顯示 Cloud Run 免費方案:每月前 180,000 vCPU-秒、360,000 GiB-秒、200 萬個要求

已經有映像時,直接從 Artifact Registry 或其他支援的 registry 部署;只有原始碼時,也能交給 Cloud Build 建置。右側顯示的是 request-based billing 的免費額度,實際是否產生費用仍要看區域、資源配置、 網路流量和其他 Google Cloud 服務。

從既有映像部署

gcloud run deploy my-service \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/my-app:v1 \
  --region asia-east1 \
  --no-invoker-iam-check

--no-invoker-iam-check 會把服務公開到網路上,適合公開網站或 Webhook。內部 API 不要加這個參數,讓服務維持預設的 IAM 驗證。

從原始碼部署

gcloud run deploy my-service \
  --source . \
  --region asia-east1

--source 會透過 Cloud Build 建立映像,再存進 Artifact Registry。目錄內有 Dockerfile 時會照它建置;沒有的話則嘗試使用 Google Cloud buildpacks。這種方式很適合快速上線,正式環境若已有 CI/CD,也可以由 pipeline 先建好帶版本標籤的映像,再交給 Cloud Run 部署。

把常用參數放在一起

gcloud run deploy my-api \
  --image asia-east1-docker.pkg.dev/my-project/backend/api:v1.4.2 \
  --region asia-east1 \
  --no-invoker-iam-check \
  --concurrency=80 \
  --min=1 \
  --max=20 \
  --memory=512Mi \
  --cpu=1 \
  --timeout=60s \
  --set-env-vars="NODE_ENV=production,LOG_LEVEL=info"

Region 通常選在主要使用者和資料來源附近,並確認需要的 Cloud Run 功能在該區域可用。正式部署也盡量使用唯一的版本標籤或 image digest,而且不要覆寫既有標籤;只寫 latest 的話,出問題時很難確認每個 Revision 實際跑的是哪個映像。

七、Revision 讓發布和回滾只需要調整流量

每次修改容器映像或服務設定,都會建立新的 Revision。Revision 建立後不可修改,但同一個 Service 可以同時保留多個 Revision,再由穩定不變的 Service URL 決定流量要送到哪一版。

查看 Revision

gcloud run revisions list --service my-service --region asia-east1

將少量流量送到新版

gcloud run services update-traffic my-service \
  --region asia-east1 \
  --to-revisions my-service-00004-abc=90,my-service-00005-xyz=10

切換全部流量到最新版

gcloud run services update-traffic my-service \
  --region asia-east1 \
  --to-latest

用 tag 先測試還沒接正式流量的版本

gcloud run services update-traffic my-service \
  --set-tags canary=my-service-00005-xyz \
  --region asia-east1

# 指令會回傳 canary tag 對應的測試 URL(--set-tags 會先清掉既有的 tag;只想新增請改用 --update-tags)
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  subgraph CREATE["1. 建立不可變版本"]
    direction TB
    SOURCE["原始碼或容器映像"] --> BUILD["Cloud Build/既有 CI<br/>產生帶版本標籤的映像"]
    BUILD --> DEPLOY["部署新 Revision<br/>Service URL 維持不變"]
  end
  subgraph PRECHECK["2. 獨立驗證"]
    direction TB
    TAG["以 Revision tag<br/>取得獨立測試 URL"] --> PASS{"冒煙測試通過?"}
    PASS -->|"否"| FIX["停止發布並修正<br/>再建立新 Revision"]
  end
  subgraph RELEASE["3. 漸進式發布"]
    direction TB
    CANARY["切 1~10% 流量到新版"] --> WATCH["比較錯誤率、延遲、<br/>資源與商業指標"]
    WATCH --> HEALTHY{"新版指標健康?"}
    HEALTHY -->|"否"| ROLLBACK["流量切回舊 Revision"]
    HEALTHY -->|"是"| PROMOTE["逐步提高到 100%<br/>保留舊版供回滾"]
  end
  DEPLOY --> TAG
  PASS -->|"是"| CANARY

Revision 不會覆蓋舊版本。先用 tag 驗證,再逐步放量並觀察錯誤率與延遲;若指標惡化,把流量切回舊 Revision 就能回滾,不必臨時重建服務。

八、公開服務和私有服務的入口權限不同

Cloud Run 建立服務表單的「驗證」區塊,兩個單選:「允許公開存取」(系統不會執行驗證檢查)與「需要驗證」(請選取 Identity and Access Management (IAM) 和/或 Identity-Aware Proxy (IAP))

Cloud Run Service 預設需要驗證。公開網站可以停用 Invoker IAM 檢查;內部服務則保留檢查,只把 roles/run.invoker 授予確實需要呼叫的身分。這一層只管呼叫者能不能進入服務,不會代替應用程式自己的登入與業務授權。

公開服務

gcloud run services update my-service \
  --region asia-east1 \
  --no-invoker-iam-check

停用 Invoker IAM 檢查是目前建議的公開方式。如果組織政策不允許停用,也可以把 roles/run.invoker 授予 allUsers:

gcloud run services add-iam-policy-binding my-service \
  --region asia-east1 \
  --member="allUsers" \
  --role="roles/run.invoker"

私有服務

私有是預設狀態。把 Invoker 角色授予呼叫方使用的 Service Account,不要直接授予整個專案或所有使用者:

gcloud run services add-iam-policy-binding my-service \
  --region asia-east1 \
  --member="serviceAccount:caller-sa@my-project.iam.gserviceaccount.com" \
  --role="roles/run.invoker"

呼叫方還要取得 Google 簽發的 ID token,並把目標 Service URL 設為 audience,再放進 HTTP header:

Authorization: Bearer <ID_TOKEN>
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START["誰需要呼叫 Cloud Run Service?"] --> PUBLIC{"是否刻意提供公開網站、<br/>Webhook 或公開 API?"}
  PUBLIC -->|"是"| OPEN["停用 Invoker IAM 檢查<br/>必要時才改用 allUsers 綁定"]
  OPEN --> APP["應用程式仍須自行處理<br/>登入、授權、速率限制與輸入驗證"]
  PUBLIC -->|"否"| CALLER{"主要呼叫者是誰?"}
  CALLER -->|"另一個服務"| SERVICE["授予呼叫方 Service Account<br/>roles/run.invoker"]
  SERVICE --> TOKEN["呼叫時帶 Google 簽發的 ID Token<br/>audience 指向目標服務"]
  CALLER -->|"員工以瀏覽器使用"| HUMAN["保留 IAM 驗證<br/>需要 Web 入口時評估 IAP"]
  CALLER -->|"排程或自動化"| AUTOMATION["為 Scheduler/Task 使用專用 SA<br/>只授予 invoker"]
  TOKEN --> LEAST["以最小權限與稽核記錄驗證"]
  HUMAN --> LEAST
  AUTOMATION --> TOKEN

roles/run.invoker 控制誰能通過 Cloud Run 的入口驗證,不等於應用程式內的業務授權。公開服務仍要處理使用者身分、輸入驗證和速率限制;私有服務則讓每個呼叫方使用專用 Service Account 與 ID token。

九、連 VPC 是設定出站路徑,不是建立內網入口

Cloud Run 要連私有 IP、Memorystore 或只能從 VPC 存取的服務時,需要設定 VPC egress。這項設定處理的是容器送出去的流量,不是使用者進入 Cloud Run 的路徑;Service 的 ingress 和 IAM 仍要另外設定。

優先評估 Direct VPC Egress

Direct VPC Egress 讓執行個體直接使用指定子網路的位址,不必先建立 Connector:

# 只有私有位址流量進入 VPC
gcloud run deploy my-service \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/my-app:v1 \
  --network my-vpc \
  --subnet my-subnet \
  --vpc-egress=private-ranges-only
比較項目Direct VPC EgressServerless VPC Access Connector
網路路徑執行個體直接連到子網路經由 Connector 執行個體轉送
額外運算費用不需要 Connector VMConnector 本身會產生費用
效能延遲較低,單一實例最高可到 1 Gbps受 Connector 容量與規格影響
擴展時的取捨建立網路介面較慢,也會使用較多 IP要另外規劃最小、最大實例與吞吐量
適合情況多數新服務既有架構或 Direct VPC 不適用時

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

Connector 並沒有停止支援,只是新服務通常先評估 Direct VPC Egress。選用 Direct VPC 時,要替子網路保留足夠位址,也要把建立網路介面造成的擴展延遲納入尖峰測試。

Cloud Run 建立服務「網路連線」分頁,已勾選「連線至虛擬私有雲,以傳出流量」,並選「直接將流量傳送至虛擬私有雲」(延遲較短、處理量較高),網路與子網路皆為 default;另一選項為「使用無伺服器虛擬私有雲存取連接器」;流量轉送有「僅將傳至私人 IP 的要求轉送至虛擬私有雲」(已選)與「將所有流量轉送至虛擬私有雲」

Direct VPC Egress 和 Connector 都能把出站流量送進 VPC。下方的轉送選項決定只有私有位址經過 VPC,或連公網流量也一起送入 VPC;後者通常還要搭配 Cloud NAT,否則容器未必能連到網際網路。

私有位址和全部流量怎麼選

# 私有位址與設定的私有範圍走 VPC
--vpc-egress=private-ranges-only

# 所有出站流量都走 VPC
--vpc-egress=all-traffic

只需要連私有服務時,private-ranges-only 比較單純。第三方 API 若要求固定來源 IP,則可選 all-traffic,再透過 Cloud NAT 對外。無論哪一種,都要檢查 DNS、防火牆、路由、NAT port、區域和網路費用。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START["Cloud Run 要連到哪種目的地?"] --> DEST{"目的地類型"}
  DEST -->|"VPC 私有 IP<br/>Cloud SQL、Redis、內部服務"| PRIVATE["啟用 Direct VPC Egress<br/>選定 network 與 subnet"]
  PRIVATE --> PRIVATE_MODE["private-ranges-only<br/>只有私有位址進入 VPC"]
  DEST -->|"一般公網 API<br/>不要求固定來源 IP"| DIRECT["使用 Cloud Run 預設公網出口<br/>不必為此建立 VPC 路徑"]
  DEST -->|"公網 API需要固定來源 IP,<br/>或所有流量都受 VPC 控制"| ALL["Direct VPC Egress<br/>設定 all-traffic"]
  ALL --> NAT["由 VPC 的 Cloud NAT<br/>提供受控或固定外部 IP"]
  DEST -->|"同時包含私有與固定公網出口"| BOTH["all-traffic 進入 VPC<br/>私有路由直達、外網經 Cloud NAT"]
  BOTH --> NAT
  PRIVATE_MODE --> VERIFY["檢查防火牆、DNS、路由、<br/>NAT port 與跨區費用"]
  DIRECT --> VERIFY
  NAT --> VERIFY

private-ranges-only 適合只把私有位址送進 VPC;若第三方服務要求固定來源 IP,再把 all-traffic 導入 VPC,由 Cloud NAT 出站。單純呼叫一般公網 API 時,不必為此多建一條 VPC 路徑。

十、Secret 不要寫進映像或一般環境變數

資料庫密碼、API key 和憑證應放在 Secret Manager,再授權 Cloud Run 的 Service Account 讀取。這樣可以避免敏感值被寫進 Dockerfile、映像 layer、原始碼或部署腳本。

當成環境變數注入

gcloud run deploy my-service \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/my-app:v1 \
  --update-secrets=DB_PASSWORD=db-password:3

容器內:

import os
db_password = os.environ["DB_PASSWORD"]

環境變數會在執行個體啟動時解析。建議指定明確的版本號,例如 :3,這樣 Secret 新增版本時不會在未部署程式的情況下改變執行結果;要輪替時,更新設定並部署新的 Revision。

掛載為檔案

gcloud run deploy my-service \
  --image my-image \
  --update-secrets=/secrets/config=app-config:latest

容器內:

with open("/secrets/config") as f:
    config = f.read()

掛載的檔案會在讀取時向 Secret Manager 取得內容。使用 latest 時,新版本能在不重新部署的情況下被讀到,適合程式本身能重新載入設定的場景。若程式只在啟動時讀一次,仍然要重啟執行個體才會生效。

兩種方式都需要把 roles/secretmanager.secretAccessor 授予 Service 使用的 Service Account。不要為了省一步而使用權限過大的預設帳號。

十一、批次任務用 Job,常駐拉取用 Worker pool

資料轉換、產生報表和定期清理都有明確的結束點,適合 Cloud Run Job。每次執行可以切成多個 tasks 平行處理,每個 task 失敗後再依設定重試:

gcloud run jobs create my-job \
  --image asia-east1-docker.pkg.dev/my-project/my-repo/batch-processor \
  --region asia-east1 \
  --tasks=10 \
  --max-retries=3 \
  --task-timeout=600s

gcloud run jobs execute my-job --region asia-east1

gcloud run jobs executions list --job my-job --region asia-east1

每個 task 預設逾時 10 分鐘,最長可設 168 小時;使用 GPU 時上限是 1 小時。單次 execution 最多可有 10,000 個 tasks。因為失敗的 task 可能重跑,寫入資料或呼叫外部 API 時要設計成可重複執行,不會因重試產生兩筆訂單或重複扣款。

工作模型ServiceJobWorker pool
怎麼開始收到 HTTP/gRPC 請求手動、排程或 API 建立 execution啟動後持續執行
何時結束單次請求最長 60 分鐘所有 tasks 完成手動停止或縮容
對外端點有負載平衡端點沒有沒有
常見用途API、網站、Webhook批次、ETL、資料清理Kafka 或 Pub/Sub pull consumer
擴縮方式依請求自動擴縮設定 task 數和平行度手動,或另外接外部指標擴縮

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

如果程式要長時間從 queue 主動拉工作,而且沒有 HTTP 請求作為擴縮訊號,再考慮 Worker pool。它預設不會像 Service 一樣依請求自動調整實例數,容量和成本需要另外規劃。

十二、看成本時要把計費模式和下游一起算

Cloud Run 的運算費用由 vCPU、記憶體、請求數和網路流量組成。Request-based billing 主要計算處理請求、啟動和關閉的時間;instance-based billing 則按執行個體的整個生命週期計費。

每月免費額度Request-based billingInstance-based billing
CPU180,000 vCPU-秒240,000 vCPU-秒
記憶體360,000 GiB-秒450,000 GiB-秒
請求數200 萬次不另外按請求計費

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

免費額度會在同一個 billing account 下的專案之間合併計算,不是每個專案各拿一份。它也不代表整套系統免費:Artifact Registry 儲存、Cloud Build、Cloud Logging、Cloud SQL、Cloud NAT 和跨區或對外流量都可能另外收費。

費率會依區域、計費模式和用量級距調整,因此估算時直接使用Cloud Run 官方定價頁與 Pricing Calculator,比把單價寫死在試算表裡可靠。

估算時至少把這幾項放進去:

  • 平均與尖峰實例數,以及 CPU、記憶體配置
  • minimum instances 在低流量時的閒置時間
  • concurrency 是否讓每個實例有效處理多個請求
  • VPC、NAT、跨區和對外網路流量
  • 資料庫連線、日誌量及其他下游服務

十三、Cloud Run 不一定比其他運算服務合適

需求先評估的服務原因
任意容器、HTTP/gRPC 與流量分版Cloud Run Service容器控制彈性高,支援 Revision 和縮容至零
有明確起訖的批次處理Cloud Run Job直接表達 tasks、平行度、重試與完成狀態
以事件為中心的單一函式Cloud Run functions平台代管建置與事件觸發整合
使用受支援 runtime 的傳統 Web AppApp Engine應用版本、流量與平台 runtime 整合成熟
需要 Kubernetes API 或叢集控制GKE能控制網路、排程、DaemonSet 與 Kubernetes 資源

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START["先描述工作負載如何被觸發、<br/>何時算執行完成"] --> K8S{"是否需要 Kubernetes API、DaemonSet、<br/>複雜網路或叢集層控制?"}
  K8S -->|"是"| GKE["GKE<br/>換取完整 Kubernetes 控制"]
  K8S -->|"否"| COMPLETE{"工作是否有明確開始與結束,<br/>不需要持續 HTTP 端點?"}
  COMPLETE -->|"是"| JOBS["Cloud Run Jobs<br/>批次、ETL、排程或平行 tasks"]
  COMPLETE -->|"否"| UNIT{"部署單位是什麼?"}
  UNIT -->|"任意容器/HTTP 或 gRPC 服務"| SERVICE["Cloud Run Services<br/>Revision、流量分配、scale-to-zero"]
  UNIT -->|"單一事件處理函式"| FUNCTIONS["Cloud Run functions<br/>事件觸發與函式導向開發"]
  UNIT -->|"框架受支援的傳統 Web 應用"| APPENGINE["App Engine<br/>平台化 runtime 與應用版本"]
  JOBS --> VERIFY["用逾時、並發、狀態、<br/>事件來源與維運需求再驗證"]
  SERVICE --> VERIFY
  FUNCTIONS --> VERIFY
  APPENGINE --> VERIFY
  GKE --> VERIFY

先分清楚工作是「持續接請求」還是「執行到完成」,通常就能在 Cloud Run Service 與 Job 之間先做選擇。若更在意函式式事件整合、平台 runtime 或 Kubernetes 控制,再比較相鄰服務。

十四、部署前檢查表

Cloud Run 的設定很多,部署前可以先收斂成幾個問題:

  • 容器是否在 4 分鐘內啟動,並監聽平台指定的 PORT?
  • 這是接 HTTP 請求的 Service、有終點的 Job,還是持續拉取工作的 Worker pool?
  • 服務要公開,還是只允許指定 Service Account 呼叫?
  • Request-based billing 是否足夠,還是沒有請求時也需要 CPU?
  • 第一個請求能不能接受冷啟動?若不能,minimum instances 的固定成本是否合理?
  • concurrency、maximum instances 和資料庫連線池能不能一起承受尖峰?
  • Secret 是否來自 Secret Manager,而且執行帳號只有必要權限?
  • 只有私有流量要進 VPC,還是連公網流量也要經 Cloud NAT?
  • 新 Revision 是否先經 tag 測試、小比例分流和指標觀察?

有兩組概念特別容易混淆。第一,instance-based billing 代表實例存活時持續有 CPU,不代表它永遠不會被停止;要保留暖機容量還得設定 minimum instances。第二,minimum instances 只能降低冷啟動機率,無法保證實例不因維護或故障重啟,呼叫端仍要有合理的 timeout 和 retry。

十五、範例:部署一個 Node.js API

# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
# 先把目前專案 ID 存成 shell 變數
PROJECT_ID="$(gcloud config get-value project)"

# 建立 Artifact Registry repository(只需建立一次)
gcloud artifacts repositories create backend \
  --repository-format=docker \
  --location=asia-east1

# 建置帶版本標籤的映像
gcloud builds submit \
  --tag "asia-east1-docker.pkg.dev/${PROJECT_ID}/backend/api:v1"

# 部署公開 Service
gcloud run deploy api \
  --image "asia-east1-docker.pkg.dev/${PROJECT_ID}/backend/api:v1" \
  --region asia-east1 \
  --no-invoker-iam-check \
  --min=1 \
  --max=20 \
  --concurrency=100 \
  --memory=512Mi \
  --cpu=1 \
  --set-env-vars="NODE_ENV=production" \
  --update-secrets="DB_PASSWORD=db-password:3"

# 取得服務 URL
gcloud run services describe api \
  --region asia-east1 \
  --format="value(status.url)"

這個範例刻意把服務設成公開,而且保留一個暖機實例。若是內部 API,移除 --no-invoker-iam-check,再把 roles/run.invoker 授予呼叫方;若延遲要求沒有那麼嚴格,將 --min=1 改成 --min=0 就能避免持續支付暖機容量。

結語

Cloud Run 省下的是主機和叢集管理,不是架構判斷。把工作模型選對之後,再依序處理計費模式、minimum instances、並發、IAM 和出站網路,通常就能避開最常見的延遲與成本問題。

發布時也不需要一次把所有流量押在新版。每次部署留下不可變 Revision,先用 tag 驗證,再從少量流量逐步增加;服務真的出問題時,回滾就是一次流量調整。這套流程比要求每次都不能冷啟動,更能直接改善可靠性。

官方文件

上一篇可以先看 GCP-108:Cloud SQL 入門,補齊資料庫版本、HA、連線和備份的選擇。下一篇 GCP-110:VPC 進階網路設計 會再往 Shared VPC、VPC Peering 與 Cloud NAT 深入。

運算服務選型系列

課程服務適合場景
GCP-109(本篇)Cloud Run容器化 API、微服務與批次工作
GCP-111Cloud Run functions由事件觸發的單一函式
ACE-212App Engine使用受支援 runtime 的 Web 應用
ACE-206GKE需要 Kubernetes API 與叢集層控制
ACE-203綜合比較比較各種 serverless 工作模型

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

GCP 核心服務 — 第 4 篇/共 10 篇 查看系列全覽 →

讀完後,留一個學習紀錄

試著用自己的話說出一個重點,以及你會如何運用。實作文章請先核對結果與清理資源,再標記為讀完。

文章進度以你確認讀完的標記為準,可隨時取消。舊版造訪紀錄保留,但不計入讀完;這份自評不代表已掌握內容。

留言討論

文章目錄與系列

徽章解鎖!