iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
Claude AI

奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲系列 第 28 篇

Day 28:【週記】Day 22-27 回顧:從本機到 AWS,那些部署當下才會踩到的雷

  • 分享至 

  • xImage
  •  

claude_28

系列:奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲
今日工具:Claude Code / CloudWatch Logs Insights / Cost Explorer
今日進度:十二個「本機永遠遇不到」的雷整理成表、一張從 US$105.6 掉到 US$1.35 的月費帳、本週數據

前言

第四週結束。這週吃掉時間的是部署當下才會出現的東西:本機 make dev 全綠、CI 全綠、terraform apply 成功,然後正式環境回 401。

這篇週記把十二個雷排成一張表:症狀、原因、修法,以及 Claude 幫上什麼、沒幫上什麼。最後三個是第一次 apply 就炸出來的,嚴格說不屬於這六天。第二節是錢:Day 9 承諾的月費表,改成無伺服器之後整個翻了過來。

一、十二個雷

# 症狀 原因 修法 Claude 的角色
1 上線後所有 /saves/{id}/* 回 401,本機正常 CloudFront /api/* 預設不把 Authorization 轉給 origin 設 origin_request_policy_id = AllViewerExceptHostHeader;不能用 AllViewer——API GW 靠 Host 選 API,轉過去直接 403 它第二題就問有沒有轉 header;但 Day 22 生成 behavior 時沒提醒
2 deploy-api 綠燈,煙霧測試卻打到舊版行為 update-function-code 回來只代表新映像收下了,LastUpdateStatus 仍是 InProgress 中間插一行 aws lambda wait function-updated-v2,實測約 6 秒 它第一版 workflow 沒這行;我問「為什麼偶爾抓到舊行為」才指對
3 部署後玩家看到舊畫面,Console 一排 chunk 404 s3 sync 沒設 Cache-Control,被快取的舊 index.html 指向已被 --delete 刪掉的 chunk 兩段 sync:assets/* 給 max-age=31536000, immutable、index.html 給 no-cache;只失效 /index.html 「只失效 index」是它補的,省下每次 /* 的錢
4 更新存檔噴 ValidationException: reserved keyword 第一版用 UpdateItem,SET name = :n, status = :s——兩個字都在保留字表裡 先用 ExpressionAttributeNames 別名;後來改成整包 PutItem + 樂觀鎖,這雷自己消失 它第一版就寫 UpdateItem——關聯式資料庫的肌肉記憶
5 infra.yml 的 apply 連續失敗六次,每次少一個 IAM 權限 部署 role 從最小權限開始加,每多一種資源就缺一個 action:lambda:CreateFunction、cloudfront:CreateDistributionWithTags 等六個 改成 PowerUserAccess 等效的 inline policy + deny iam:*User*、iam:*AccessKey* 它每次都猜得出缺哪個 action,但六次來回本身就是訊號:IaC role 不該從零列
6 GetItem/PutItem 全正常,只有一句 GSI 查詢回 AccessDeniedException 執行角色只列了表 ARN,沒列 ${table_arn}/index/GSI1 兩個 ARN 都列 Day 16 的雷換個載體再踩一次(那次是 log group ARN 少了 :*)。記憶體版與 CI 都碰不到
7 前端 res.json() throw Unexpected token '<',只在錯誤路徑上 Day 16 為 SPA 深連結加的 custom_error_response 是 distribution 層設定,把 API 的 403、404 一起改寫成 200 + HTML 拿掉它,改成只掛在 default behavior 的 CloudFront Function,/api/* 不掛 我問「為什麼 404 會變成 HTML」才問對
8 Day 24 第一次演練沒收到信 SNS email 訂閱要按確認信,沒按就是 PendingConfirmation 按確認;terraform output 加一行提醒 沒問它,20 分鐘後自己在主控台看到
9 Logs Insights 查「昨天的錯誤」查到今天的 Insights 的時間範圍是 UTC 查詢用 datefloor,runbook 註明 UTC 它提醒過一次我還是忘了。和 Day 21 的坑 #6 同一組:時間在系統邊界永遠要標時區
10 plan 過了兩次,apply 第一句就死:HTTP APIs are not available in this AWS region ap-east-2 的服務目錄裡沒有 apigatewayv2 API 邊緣整個換成 REST API v1:{proxy+} 與 root 各一組 ANY、具名 stage prod 貼上錯誤就拿到 ssm get-parameters-by-path 這條查法;但沒人在我動工前查
11 同一次 apply 的第二個錯:EnableAcceptEncodingGzip is invalid for policy with caching disabled 自建 cache policy 的 TTL 全 0 就是「快取關閉」,這種 policy 不准開 gzip 改用託管 CachingDisabled,壓縮上移到 REST API 的 minimum_compression_size = 1024:實測 1,885 → 663 bytes 它一眼認出是 AWS 的參數限制,不是 HCL 寫錯
12 映像 build 綠、push 綠,apply 才紅:The image manifest, config or layer media type ... is not supported buildx 預設附掛 provenance/SBOM attestation,推上去的是 OCI manifest list,Lambda 只吃單一平台的 Docker manifest docker build --provenance=false --sbom=false;build log 那行 exporting attestation manifest 就是徵兆 它問「build log 有沒有 attestation」——問題問對,答案就在我自己的終端機裡

claude_28_diagram_01

十二個雷有一個共同點:沒有一個是程式邏輯錯。前九個是「兩個系統的預設值合起來不對」——CloudFront 預設不轉 header、s3 sync 預設不寫 Cache-Control、SNS 訂閱預設要人按確認;後三個更狠:這個區域根本沒有那個服務、那組參數 AWS 根本不收、那種 manifest Lambda 根本不拉。Claude 對每個預設值都知道,但它只在被問到時才說,而我只在踩到時才問。

二、月費表

假設刻意保守:API 8,000 次/月、Lambda 160 GB-秒、DynamoDB 3,000 寫/5,000 讀、CloudFront 3 萬次請求 + 1.5 GB 傳出,而且把永久免費額度當成用完。

項目 月費 備註
CloudWatch alarms(6 個) 0.60 US$0.10/個;占 44%
CloudWatch 自訂指標(ErrorCount) 0.30 Day 24 的 metric filter
CloudFront 0.25 還在免費額度內,這列是保守值
CloudWatch Logs(攝入 + 儲存) 0.07
S3(網站 + tfstate) 0.04
DynamoDB(on-demand + PITR) 0.02
ECR(映像 44 MB × 5) 0.02 US$0.10/GB/月
API Gateway REST API 0.03 US$3.50/百萬;HTTP API 只要 1.00,但台北沒有
Lambda(arm64、512 MB) 0.01
SNS(email) 0.01 每月前 1,000 封免費
SSM Parameter Store/Budgets/CF Functions 0.00 免費範圍內
VPC / NAT / ALB / RDS / Fargate — 不存在
合計 1.35 WAF 開著另計 +8.03

claude_28_diagram_02

三個觀察:

第一,最貴的東西是「告警」,不是「運算」。 監控(六個 alarm + 自訂指標)0.90,占 67%;真正在跑遊戲的 Lambda + API GW + DynamoDB 只有 0.06。省錢的下一步不是優化程式,是問「六個告警需要六個嗎」。

第二,零玩家 US$0.92,一百個玩家 US$1.35。 舊架構我寫過「一百個玩家跟零個玩家差不了三美元」,理由是固定費占 88%;新架構固定費占 0%,同一句話變成「差不了半美元」,理由卻是變動費太低——同一個現象,兩種相反的原因。

第三,WAF 是這裡唯一貴的東西。 US$8.03,是其餘全部的六倍。Day 27 開起來第一小時就擋了 37 次對 /wp-login.php、/.env 的掃描——但我用一週的錢買了它,今天把 enable_waf 設回 false。這一開一關抵消:加一個 aws_cloudfront_function、關掉一個 Web ACL,plan 仍是 51 個資源。

但書:ap-east-2 是新區域,單價未必和別區一樣,上表是用公開單價推的量級,不是帳單抄本。

更該寫下來的是代價:冷啟動仍在,而且換成容器映像之後更明顯(實測 1.6 秒,熱請求 0.15–0.25 秒);每 IP 的精準限流做不到,行程內 token bucket 在 Lambda 上無效,只剩全域 throttling;單表設計把「換一種查詢方式」的成本從一句 SQL 變成一次資料遷移。這三件都不是錢能解決的。

三、本週數據

以下是這六天(Day 22–27)的數字,不含今天。

項目 數值 備註
專注工時 1,010 分鐘(6 天) 排雷佔 260 分鐘
Claude Code session 13 含 Day 26 的 2 個 worktree、/ultracode(我自訂的 slash command,不是官方功能)的 3 個 subagent
部署次數 api 11、web 9、infra apply 6 6 次 apply 有 4 次是雷 5
測試總數 Go 62、vitest 20、Playwright 9 本週新增 Go 8、vitest 8、Playwright 9
/ultracode 1 次,24 分鐘 Day 26 的池子 bug
告警 2 次演練 + 1 次真實(Day 26 壓測觸發 lambda-duration-p99)
排雷平均耗時 29 分鐘/個 本週九個,最長是雷 5(75 分鐘)

跟前三週對照:830、790、1,120、1,010。session 數跟第三週差不多,形狀卻不同:這週有一半是「貼錯誤訊息、拿到方向、關掉」的短對話。

四、三個教訓

預設值是雷的原料。 十二個雷有八個是預設值——buildx 那個也是:沒人叫它加 attestation,是它自己預設加的。現在我在 apply 前多一步:把 plan 貼給 Claude 問「哪個預設值會讓我在部署當下嚇一跳」——雷 3、7 就是這樣擋下的。

同一個雷會踩兩次,除非它變成檢查項。 雷 6 就是 Day 16 那個「ARN 少一截」的翻版。「只追加、不重寫」的 PITFALLS.md 因此多一行「新增資源 → 執行角色的 Resource 連子資源都列了嗎」。

本機全綠只證明本機,plan 全綠也只證明 plan。 contract test、storylint、tfsec 都在 CI 裡,但雷 1、3、7 只在真實的 CloudFront、S3、Lambda 上發生;雷 10–12 更極端——plan 不會問 AWS「這個區域有沒有這個服務」「這種 manifest 你收不收」,那條安全帶根本沒拉上。所以 deploy-api 最後一步是煙霧測試:等 function-updated-v2,再用真實 token 打 /healthz。

小結

這週六個主題都完成,但週記只寫雷,因為雷是「Claude 知道、我沒問」的集合——只有最後兩個例外,那要真的 apply 下去才知道。AI 對預設值的知識很完整,卻不會主動拿你的架構推演它們的後果——除非你問對問題。

至於那張從 105.6 掉到 1.35 的帳,我最想說的不是「省了一百美元」,而是沒有任何一個資源在我睡覺時按小時計費。錢的形狀變了,煩惱也跟著變:以前擔心帳單,現在擔心冷啟動。

明天上線 demo,後天終章。

今日產出

  • [x] 十二個雷的表(第一節);雷 6、9、10 的檢查項寫進 PITFALLS.md
  • [x] modules/cdn 用 aws_cloudfront_function.spa_rewrite 取代 custom_error_response;enable_waf 設回 false(plan 仍是 51)
  • [x] deploy-api.yml 補 wait function-updated-v2 與部署後煙霧測試
  • [x] 月費表(第二節)與本週數據(第三節)——倉庫裡沒有 docs/weekly/

明日預告

Day 29:塔防遊戲正式上線:demo 展示、架構全貌圖與開發數據總結。


上一篇
Day 27:安全性防禦工事:API 認證、Rate Limit 與雲端資安基本盤補強
下一篇
Day 29:塔防遊戲正式上線:demo 展示、架構全貌圖與開發數據總結
系列文
奇幻塔防開發實錄:用 Claude 打造一款有靈魂的塔防遊戲 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言