Cloud Run 入門:部署、擴縮、權限與 VPC 怎麼設定
手上已經有一個能接 HTTP 請求的容器,卻不想為它維護 VM 或 Kubernetes 叢集時,Cloud Run 往往是最快能上線的選擇。
它會處理 HTTPS 端點、負載分配和執行個體擴縮,但「無伺服器」不等於不用做維運。容器啟動速度、並發數、IAM、最小實例、VPC 路徑和下游連線,仍然會影響延遲、穩定性與帳單。這篇會沿著一次部署的完整流程,把這些設定串起來。

每次部署都會產生不可變的 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 相容性:
| 特性 | Gen1 | Gen2 |
|---|---|---|
| 基礎技術 | gVisor 沙盒(Google 自家的輕量隔離層) | MicroVM(迷你虛擬機,完整 Linux 核心) |
| 系統呼叫 | 受限(不支援全部 syscall) | 完整支援 |
| 冷啟動速度 | 較快(Bursty 流量佳) | 較慢 |
| CPU 效能 | 標準 | 更高(適合計算密集) |
| 記憶體下限 | 128 MiB | 512 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 情境啟動得更快。沒有一個選項適合所有容器,應以實際映像量測啟動時間、系統相容性和尖峰負載。
三、資源上限先知道,但不要直接照上限配置
| 項目 | 限制 |
|---|---|
| 最大 vCPU | 8 個(每實例) |
| 最大記憶體 | 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,也不能只用表格中的數字判斷。

CPU 和記憶體都是每個執行個體的配置,不是整個 Service 共用的總量。選擇時要一起看單一請求用量、 concurrency 和程式能否有效使用多核心;配置越大,每個執行個體的計費也越高。
四、計費模式決定空閒時還有沒有 CPU
Cloud Run Service 有 request-based 和 instance-based 兩種計費設定。它們常和 minimum instances 混在一起談,但其實回答的是不同問題:計費模式決定執行個體存活時,沒有請求的那段時間是否持續分配 CPU;minimum instances 則決定平台至少保留多少個暖機實例。

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

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 和公開範圍

已經有映像時,直接從 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 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 Egress | Serverless VPC Access Connector |
|---|---|---|
| 網路路徑 | 執行個體直接連到子網路 | 經由 Connector 執行個體轉送 |
| 額外運算費用 | 不需要 Connector VM | Connector 本身會產生費用 |
| 效能 | 延遲較低,單一實例最高可到 1 Gbps | 受 Connector 容量與規格影響 |
| 擴展時的取捨 | 建立網路介面較慢,也會使用較多 IP | 要另外規劃最小、最大實例與吞吐量 |
| 適合情況 | 多數新服務 | 既有架構或 Direct VPC 不適用時 |
表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。
Connector 並沒有停止支援,只是新服務通常先評估 Direct VPC Egress。選用 Direct VPC 時,要替子網路保留足夠位址,也要把建立網路介面造成的擴展延遲納入尖峰測試。

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 時要設計成可重複執行,不會因重試產生兩筆訂單或重複扣款。
| 工作模型 | Service | Job | Worker 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 billing | Instance-based billing |
|---|---|---|
| CPU | 180,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 App | App 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 驗證,再從少量流量逐步增加;服務真的出問題時,回滾就是一次流量調整。這套流程比要求每次都不能冷啟動,更能直接改善可靠性。
官方文件
- Cloud Run 執行環境
- Request-based 與 instance-based billing
- 設定 minimum instances
- 容器 runtime contract 與資源限制
- Cloud Run quotas
- 公開服務與私有服務的驗證方式
- Direct VPC egress
- 在 Cloud Run 使用 Secret Manager
- 建立與執行 Cloud Run Jobs
- Cloud Run 定價
上一篇可以先看 GCP-108:Cloud SQL 入門,補齊資料庫版本、HA、連線和備份的選擇。下一篇 GCP-110:VPC 進階網路設計 會再往 Shared VPC、VPC Peering 與 Cloud NAT 深入。
運算服務選型系列
| 課程 | 服務 | 適合場景 |
|---|---|---|
| GCP-109(本篇) | Cloud Run | 容器化 API、微服務與批次工作 |
| GCP-111 | Cloud Run functions | 由事件觸發的單一函式 |
| ACE-212 | App Engine | 使用受支援 runtime 的 Web 應用 |
| ACE-206 | GKE | 需要 Kubernetes API 與叢集層控制 |
| ACE-203 | 綜合比較 | 比較各種 serverless 工作模型 |
表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。
讀完後,留一個學習紀錄
試著用自己的話說出一個重點,以及你會如何運用。實作文章請先核對結果與清理資源,再標記為讀完。
文章進度以你確認讀完的標記為準,可隨時取消。舊版造訪紀錄保留,但不計入讀完;這份自評不代表已掌握內容。