TypeScript CDK 使用紀錄
記錄 TypeScript CDK 的部署步驟、bootstrap 與 CloudFormation stack lifecycle 的運作,並與 Terraform 比較。
Deploy Steps
- 獲得 AWS CLI 存取權,輸出環境變數
aws-vault exec [profile] export AWS_ACCOUNT_ID=(你的 account id) export AWS_REGION=ap-northeast-1 - 初始化 CDK 使用前置 stack
cdk bootstrap aws://$AWS_ACCOUNT_ID/$AWS_REGION - 部署 CDK
cdk deploy MainStack --require-approval never - 上傳環境變數 @root of CDK repo:
chmod +x ./put-secret-values.sh ./put-secret-values.sh - 打包 frontend apps @root of chatbotmodule:
chmod +x ./deploy_frontend.sh ./deploy_frontend.sh - Backend migration
- 建立 ssh connection config (reference: internal wiki)
- 建立 RDS port forwarding
ssh -f -N -L 15432:[rds-endpoint]:5432 bastion - 執行 migration 指令
npm run db:migrate
- 調整 lambda 環境變數 @ ApiLambda:
ALLOWED_ORIGIN={WebsiteDistribution domain name}
CDK 的部署流程與 bootstrap
Terraform 是直接呼叫 AWS API 建立資源,而 CDK 的部署原理則完全不同:
- cdk synth
- 把 TypeScript 程式碼轉換成 CloudFormation Template(JSON/YAML 格式)。
- 你可以
cdk synth > template.yaml來檢查結果。
- cdk bootstrap
- 第一次用 CDK,需要先在 AWS 帳號 & region 裡建一組「舞台環境」。
- bootstrap 會建立:
- 一個 S3 bucket(放 CDK 生成的 CloudFormation template 和資產)
- 一個 ECR repo(放 Docker image 資產)
- 一些 IAM 角色(CloudFormation stack 執行時需要的權限)
- 可以理解成:bootstrap 幫 CDK 準備好環境,讓之後的 deploy 可以順利跑。
- cdk deploy
- 把 template 和資產上傳到 bootstrap 的 S3/ECR,再交給 CloudFormation 執行。
- CloudFormation 處理 stack lifecycle(建立 / 更新 / rollback)。
所以,CDK 其實是 程式碼 → CloudFormation → AWS 資源,中間隔了一層 bootstrap。
CloudFormation Stack Lifecycle
創建流程:
CREATE_IN_PROGRESS → CREATE_COMPLETE (成功)
↓
CREATE_FAILED → ROLLBACK_IN_PROGRESS → ROLLBACK_COMPLETE
↓
ROLLBACK_FAILED
更新流程:
UPDATE_IN_PROGRESS → UPDATE_COMPLETE_CLEANUP_IN_PROGRESS → UPDATE_COMPLETE (成功)
↓
UPDATE_FAILED → UPDATE_ROLLBACK_IN_PROGRESS → UPDATE_ROLLBACK_COMPLETE
↓
UPDATE_ROLLBACK_FAILED
刪除流程:
DELETE_IN_PROGRESS → DELETE_COMPLETE (成功)
↓
DELETE_FAILED (失敗)
特殊狀態
- REVIEW_IN_PROGRESS: 使用 Change Sets 時的狀態,Stack 等待審核和執行
- ROLLBACK_COMPLETE: 只會發生在 create_failed 之後
- Stack 創建失敗後回滾完成
- 此狀態下 Stack 無法更新,只能刪除
- 必須先刪除後重新創建
- _FAILED 狀態: 當 Stack 處於任何 FAILED 狀態時:
- 需要人工介入處理
- 可以選擇繼續回滾或修復問題後重試
- UPDATE_ROLLBACK_FAILED 可使用 ContinueUpdateRollback API
重要概念
- 自動回滾機制
- 創建或更新失敗時,CloudFormation 會自動回滾
- 可以通過
-disable-rollback參數關閉(用於調試) - 回滾會盡可能恢復到先前的穩定狀態
- 終止保護 (Termination Protection)
- 可以啟用以防止意外刪除
- 必須先禁用才能刪除 Stack
- Drift Detection
- 檢測 Stack 資源是否與模板定義不一致
- 不改變 Stack 狀態,僅提供偏移資訊
常見問題
-
有些資源在 rollback 時因為種種原因沒辦法正確被刪除,舉例情境像是:
VPC stack 因後半截的資源配置有誤,在前半截已經部署的 resource 中含有 EIC endpoint。但因為 EIC endpoint 部署時間會比較長(約五分鐘左右),因此當 VPC stack 部署到錯誤配置時、CloudFormation 判斷 stack 建立失敗、準備 rollback。但在 CloudFormation Rollback 時,EIC endpoint 還在 pending 階段、而這個 resource 在 pending 階段是沒辦法接收 delete api 的,最終 EIC endpoint 刪除失敗,從而導致 rollback_failed。
在這個情境下,我們能做的只有等待 EIC endpoint 建立完畢,手動把這些資源刪掉之後,再重新嘗試一次部署。(其他像是 ElastiCache 也會遇到類似的問題)
-
已經建好的 sub-stacks 在 rollback 時被拆光,情境描述如下:
假設有一個 CloudFormation Stack 裡面有 10 個 sub-stacks,在第一次測試部署時、部署到第 9 個 stack 才遇到配置錯誤;根據上面提到的 Lifecycle 運作方式,CloudFormation 會 rollback 到上一次部署成功的狀態,也就是什麼資源都不會留下。
我自己針對這個問題的解決方案:通常一個大架構下,我們會用許多 sub-stack 的架構來構建出一個大的 CloudFormation stack,而這些 sub-stacks 也通常會有部署的先後順序。因此我在測試部署時,我會在 main stack 中依序部署 sub-stacks。
假設 main stack 中的架構如下:main { stack-A → stack-B → stack-C },我會先註解掉 stack-B & stack-C,確認 stack-A 可以正確部署沒有遇到問題後,再依序解除 stack-B 和 stack-C 的註解。
這樣做的好處是,當我確認 stack-A 沒問題,要部署 stack-B 時、遇到問題了,CloudFormation 會「rollback 到前一個正確部署、沒有錯誤的版本」,因此雖然我的 stack-B 被拆光了,至少因為在前一次部署時、stack-A 是好的,也會在部署失敗後被保留下來。
搞懂這些邏輯真的會省掉 debug 非常多時間。CDK 部署真的是 extremely time consuming 的一件事。
Terraform vs CDK:不同維度的比較
-
狀態管理(State)
- Terraform:需要 state 檔案(通常放 S3 + DynamoDB 做鎖),紀錄目前 infra 的狀態。
- 優點:狀態清楚、可追蹤。
- 缺點:需要額外管理 state,團隊協作時容易踩坑、鎖沒設好會衝突。
- CDK:沒有 state 檔,所有狀態、rollback 都交給 CloudFormation。
- 優點:省去 state 管理,部署過程簡單。
- 缺點:debug CloudFormation Stack 錯誤、Rollback 發生時比較痛苦,ChangeSet 也不如 Terraform diff 精確。
- Terraform:需要 state 檔案(通常放 S3 + DynamoDB 做鎖),紀錄目前 infra 的狀態。
-
建立資源的角色與權限
- Terraform:由執行 Terraform 的人 / pipeline IAM 角色直接呼叫 AWS API 建立資源。
- CDK:需要 bootstrap 預先建立的 IAM 角色,後續所有 deploy 都透過 CloudFormation 執行。
換句話說,Terraform 是「我自己蓋房子」,CDK 是「我寫好設計圖,交給 CloudFormation 施工」。
-
AWS 新手友善度
- Terraform:學習曲線比較平滑,因為你寫什麼就是什麼,雖然 verbose 但邏輯清楚。
- CDK:對 AWS 新手來說反而有點黑箱,因為一個 construct 背後可能藏了很多資源。
-
長期維護 vs 一次性專案
- 長期維護:Terraform 更適合,因為資源和程式碼是一一對應,debug、audit、migrate 都比較可控。
- 一次性專案 / 快速開發:CDK 很有優勢,construct 能夠省下很多相依資源建置的時間,特別是要快速拉起 demo、PoC 時。
-
語言與開發體驗
- Terraform:HCL 是專為 IaC 設計的 DSL,簡潔但有限,複雜邏輯要靠 module 或外部工具。
- CDK:用 TypeScript / Python 等語言,能直接用條件式、迴圈、function 抽象化資源定義。對程式背景的人來說更自然。