格局打開,我們要更多的 Cloud Run 設定
經驗具現化 — EP05:需求又推著 skill 往前走了
接著另一個 side project 冒出來了——tcat-qrcode-form,黑貓宅配的 QRCode 填單小工具。它是給零售業主用的,不需要電腦操作,給你一個實體的預建單號,掃 QRCode 用手機打開網頁就可以填寫寄貨資訊,相當方便。這個專案裡得跑 Playwright 跟 QRCode scanner,需要更細緻地控制 Cloud Run 的行為——加大記憶體、調整 request timeout、設定 startup probe,這些在前一個專案都不需要操心,但這次不行。
問題是,mini-deployment.yaml 裡沒有地方放這些設定。Claude 問我:要直接在 deploy 的時候加 gcloud 的 flag,還是擴充設定檔的格式?
直接加 flag 的話,每次部署都要記一長串參數,而且這些參數散落在 skill 的邏輯裡,不在使用者的 repo 中,換個專案又要重新設定。擴充設定檔的話,v1 的 components 格式已經開始不夠用了——同一個清單裡,有的 entry 只需要一個 dockerfile,有的需要額外的設定欄位,格式開始分裂。
再加上 media archive 那邊曾經想過要加 sidecar——開一個 tailscale sidecar 連到自己的電腦,透過「內網」呼叫地端的服務。雖然最後覺得需求不夠強烈沒有進行,但光是「想描述這件事」就讓我意識到,v1 的一個 dockerfile 欄位根本描述不了這種組合。
Knative YAML:讓 Cloud Run 回到它的原生格式
這時候過去寫 Kubernetes 服務的經驗就派上用場了。Cloud Run 底層本來就是 Knative,它接受 Knative service YAML 作為部署設定。與其自己再包一層格式去描述這些進階設定,不如直接讓使用者寫 Knative YAML,工具只負責 build image 和處理認證。resource、probe、concurrency、sidecar——全部寫在 Knative YAML 裡,一目了然。
mini-deployment.yaml v2
於是我們決定做 v2。先把現有的格式正式標為 v1,然後設計新格式:components 拆成 services 和 jobs 兩個頂層 key,不再靠 type 欄位區分。需要進階設定的 service 就多一個 spec 欄位指向 Knative YAML,build 欄位列出需要 build 的 image。簡單的 service 還是一個 build 字串搞定。
version: 2
services:
- name: znepwgud
spec: knative/service.yaml
build:
app: ./Dockerfile
需要進階設定的 service 加一個 spec 指向 Knative YAML,裡面可以寫 resource limits、startup probe、container concurrency 這些 Cloud Run 原生支援的設定。build 裡列出要 build 的 image,名稱對應 Knative YAML 裡 container 的 image 欄位。
Migration:v1 到 v2 的路
光定格式還不夠。既然有了 v1 和 v2,就需要 migration 的路徑。Claude 做了一個 v1-to-v2 的 converter 工具,也做了對應的 migration skill——偵測 repo 裡的設定檔版本,預覽轉換結果,確認後就地轉換。deploy skill 那邊也同步更新,讓它能同時讀懂 v1 和 v2,在記憶體裡統一轉成 v2 的結構來處理。
你依然可以感受到,這些規格都不是事先想好的,而是有需求才去把它做出來,並且模擬著一個 migration 的歷程。當然我可以直接叫 agent 幫我從 v2 重寫,反正現在也只累積到第二個 side project 在用。但我就是順便想一下,如果這是在工作上用的話,流程應該要是什麼樣子才會順暢,特別是當已經有很多專案用你的工具在管理的情況,更要注意這樣的演進過程。
需求推著格式走,格式推著工具走。每一次改版都是因為真的有一個部署需求卡住了,才回頭去改。
下一篇,部署的事告一段落。但部署會花錢,而花最多錢的,不一定是你以為的那個地方。