Cloud Run 第一次切 Custom Domain 到 Prod: Domain Mapping、Search Console 與憑證等待期踩坑記錄
這篇記錄第一次把 Cloud Run 的 custom domain 從既有環境切到正式 prod service 時, 我實際踩到的幾個坑。
表面上看起來只是把 api.example.com 指到新的 Cloud Run service, 但真正會卡住的通常不是 Terraform syntax, 而是:
- domain ownership
- IAM 身分
- certificate provisioning
- first deploy sequencing
如果這幾件事沒有事先想清楚, 第一次 prod 啟用很容易卡在最後一步。
這個問題的典型場景
通常情境會像這樣:
- custom domain already exists
- old mapping points to a non-prod or legacy service
- new prod service is ready
- Terraform now manages the prod service and wants to own the domain mapping too
這時候最直覺的想法是:
- import the existing mapping
- let Terraform replace it during the first prod deploy
這個方向本身沒有錯, 但會牽動幾個 provider 外的前置條件。
第一個坑: Terraform 能管 domain mapping, 不代表現在這個身分有權重新建立它
我第一次遇到的錯誤不是 DNS, 也不是 Cloud Run service 本身, 而是類似這種訊息:
|
|
這個錯誤的重點不是 Cloud Run 壞掉, 而是:
- the current deploy identity can talk to GCP
- but it is not recognized as a domain owner for that domain
對 Cloud Run custom domain 來說, 能不能 create or recreate domain mapping, 跟 Search Console 的 ownership 有關。
如果現在是新的 deploy-prod service account 要接手第一次正式 prod 切換, 那它也必須被視為這個 domain 的 owner。
第二個坑: Full user 不夠, 要用 Owner
這個差異很容易看漏。
在 Search Console 裡:
- Full user is not the same as Owner
- Full user cannot satisfy domain ownership requirements for this flow
如果你只是把 deploy service account 加成 Full user, Terraform 仍然可能在 create domain mapping 的時候失敗。
比較穩的做法是:
- add the deploy-prod service account as an owner
- add it on the parent domain if possible
- wait a few minutes for the permission change to propagate
- rerun the failed deploy
第三個坑: import 成功不代表 domain 已經完成切換
第一次切 prod 的時候, 常見做法會像這樣:
|
|
這樣做的好處是, Terraform 可以先接手既有 mapping, 然後在 plan 裡看見 route mismatch, 再做 replace。
但要注意:
- import success only means state ownership is established
- it does not mean the new domain target is ready yet
真正的切換是否完成, 還要看 mapping status 和 certificate status。
第四個坑: DNS 正確, HTTPS 仍然可能暫時不能用
這是第一次正式啟用最容易讓人誤判的地方。
你可能會看到:
- DNS already points to
ghs.googlehosted.com DomainRoutable = True- but
curl https://api.example.comstill fails
這時候不一定是 DNS 設錯, 也不一定是 Terraform 沒做完。
很常見的情況是 managed certificate 還在 provisioning。
我會先看 domain mapping status:
|
|
如果你看到類似這些狀態:
|
|
那 GCP 控制層基本上已經完成。這時候本機還短暫打不到 HTTPS, 很可能只是 edge propagation 還沒完全擴散到位。
第五個坑: 第一次 prod deploy 的順序不能亂
如果 domain mapping 也要在第一次 prod deploy 一起切, 順序要很嚴格。
我現在會建議用這個順序:
|
|
這裡最容易做錯的是 3 和 4。
如果舊 root 還在管 domain mapping, 新 root 又要 import 同一個 mapping, state ownership 會混亂。
第六個坑: push trigger 是否要在第一次 prod deploy 前就打開
這不是 Cloud Run 問題, 但跟第一次 prod 啟用很有關。
如果 deploy-prod.yml 已經有 push: main, 那某次 merge 本身就可能直接變成第一次 prod deploy。
這代表你不能用平常 merge feature 的心態看這個 PR。你要把它當成正式部署事件。
比較穩的做法通常是二選一:
- keep the first prod deploy manual
- or finish every prerequisite before the merge that enables auto prod deploy
只要前置還沒做完, 就不該讓 main 自動踩進第一次 prod 切換。
我現在會怎麼驗證第一次切換真的完成
我會分成三層看:
Terraform layer
- prod service root plans cleanly
- the import block is no longer needed
- the old root no longer owns the mapping
GCP 控制層
mappedRouteNamepoints to the prod serviceReady = TrueCertificateProvisioned = TrueDomainRoutable = True
User-visible layer
curl -I https://api.example.com/healthsucceeds- opening the domain in a browser works
- the service behavior matches prod, not legacy/dev
如果只有前兩層成立, 第三層還沒過, 我通常不會說切換完成。
一個實用的心理模型
我現在會把這件事拆成兩個不同問題:
- who owns the domain mapping state
- who is authorized to administer the domain
Terraform import 只是在處理第一題。
Search Console ownership 和 Cloud Run domain authorization, 才是在處理第二題。
這兩題如果混在一起看, 很容易以為 import 成功就代表一切都 ready。
常用 gcloud 指令
第一次切 custom domain 到 prod 時, 最容易回頭查的通常是 mapping 狀態和 service URL。這幾條我會直接留在筆記裡。
查 domain mapping 的完整狀態
|
|
只看 mapping 目前對到哪條 route
|
|
列出目前 region 內的 domain mappings
|
|
查 prod service 的 Cloud Run URL
|
|
查 prod service 現在用的 image
|
|
查目前 custom domain 對應的 service 詳細資訊
|
|
結論
第一次把 Cloud Run custom domain 切到正式 prod service, 真正難的通常不是 HCL, 而是 cloud 控制層以外的邊界條件。
最重要的幾件事是:
- make sure the deploy identity is a real domain owner
- treat the first prod deploy as a rollout event
- verify mapping status and certificate status separately
- remove one-time import scaffolding after cutover
只要把這幾件事分開看, 第一次 prod 啟用就會清楚很多。