iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0
Cloud Native

EKS in Practice:IaC × GitOps 實戰 30 天系列 第 30

[Day 30] Terraform vs CDK:誰更適合你的部署流程?

  • 分享至 

  • xImage
  •  

今天來到系列的最後一天 🥳 前面我們一路聊了 EKS、K8s 網路、Cilium、Service Mesh,到升級維運的實戰。最後,想用一個和 EKS 本身沒有太大的直接關係,但我自己在不同專案裡實際踩過的議題收尾 —— IaC 工具的比較:Terraform vs TypeScript CDK


Terraform:宣告式 IaC

Terraform 的設計思路很直白:你寫什麼,就長什麼

  • 在 HCL 裡定義 aws_vpc,apply 之後就會建立一個最基本的 VPC。
  • 如果需要更多設定(subnet、route table、NAT gateway…),要嘛一個個 resource 宣告,要嘛就引用 module。

這種方式優點是透明、可控、精細。缺點是有時候會顯得繁瑣,尤其對剛入門 AWS 的人來說,可能很快就被一堆 resource 和 dependency 給淹沒。


CDK:程式化 IaC

AWS CDK(Cloud Development Kit)走的是另一條路:用程式語言描述基礎建設,再轉換成 CloudFormation 來建立資源。舉例來說:

  • Terraform:只宣告一個 VPC → 真的只會出現一個空 VPC。
  • CDKnew ec2.Vpc(...) → 你不只得到 VPC,還會同時建立子網、route table、安全群組等。

這讓 CDK 在「快速啟動專案」時非常方便,因為它幫你帶上合理的預設值。但同時也代表:使用者要搞清楚 construct 背後到底建立了什麼,不然會有「一行程式碼、結果建出十幾個資源」的黑箱感。另外,如果需求和預設不一樣,可能還要花時間去覆寫設定。


CDK 的部署流程與 bootstrap

Terraform 是直接呼叫 AWS API 建立資源,而 CDK 的部署原理則完全不同:

  1. cdk synth
    • 把 TypeScript 程式碼轉換成 CloudFormation Template(JSON/YAML 格式)。
    • 你可以 cdk synth > template.yaml 來檢查結果。
  2. cdk bootstrap
    • 第一次用 CDK,需要先在 AWS 帳號 & region 裡建一組「舞台環境」。
    • bootstrap 會建立:
      • 一個 S3 bucket(放 CDK 生成的 CloudFormation template 和資產)
      • 一個 ECR repo(放 Docker image 資產)
      • 一些 IAM 角色(CloudFormation stack 執行時需要的權限)
    • 可以理解成:bootstrap 幫 CDK 準備好環境,讓之後的 deploy 可以順利跑。
  3. 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 狀態,僅提供偏移資訊

常見問題

  1. 有些資源在 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 也會遇到類似的問題)

  2. 已經建好的 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:不同維度的比較

  1. 狀態管理(State)
    • Terraform:需要 state 檔案(通常放 S3 + DynamoDB 做鎖),紀錄目前 infra 的狀態。
      • 優點:狀態清楚、可追蹤。
      • 缺點:需要額外管理 state,團隊協作時容易踩坑(鎖沒設好會衝突)。
    • CDK:沒有 state 檔,所有狀態、rollback 都交給 CloudFormation。
      • 優點:省去 state 管理,部署過程簡單。
      • 缺點:debug CloudFormation Stack 錯誤、Rollback 發生時比較痛苦,ChangeSet 也不如 Terraform diff 精確。
  2. 建立資源的角色與權限
    • Terraform:由執行 Terraform 的人 / pipeline IAM 角色直接呼叫 AWS API 建立資源。
    • CDK:需要 bootstrap 預先建立的 IAM 角色,後續所有 deploy 都透過 CloudFormation 執行。
      • 換句話說,Terraform 是「我自己蓋房子」,CDK 是「我寫好設計圖,交給 CloudFormation 施工」。
  3. AWS 新手友善度
    • Terraform:學習曲線比較平滑,因為你寫什麼就是什麼,雖然 verbose 但邏輯清楚。
    • CDK:對 AWS 新手來說反而有點黑箱,因為一個 construct 背後可能藏了很多資源。
  4. 長期維護 vs 一次性專案
    • 長期維護:Terraform 更適合,因為資源和程式碼是一一對應,debug、審計、遷移都比較可控。
    • 一次性專案 / 快速開發:CDK 很有優勢,construct 能夠省下很多相依資源建置的時間,特別是要快速拉起 demo、PoC 時。
  5. 語言與開發體驗
    • Terraform:HCL 是專為 IaC 設計的 DSL,簡潔但有限,複雜邏輯要靠 module 或外部工具。
    • CDK:用 TypeScript / Python 等語言,能直接用條件式、迴圈、function 抽象化資源定義。對程式背景的人來說更自然。

Vibe Coding 與 IaC

偷搭一下 vibe coding 的熱潮,我的 CDK 專案全部都是用 vibe coding 做出來的。這真的讓 IaC 開發快了好幾倍,因為我在這之前基本上沒碰過 CDK、也只寫過 JavaScript、沒碰過 TypeScript,因此要我從頭開始學這兩個東西、並在短時間內把它們組成 production ready 的架構基本上非常困難。但有了 vibe coding 這個概念之後,我只要懂 AWS 架構邏輯,後面的 TS 程式碼、以及 CDK 的基本設定都可以直接交給 AI 生成。

雖然 vibe coding 讓人人都能寫程式這件事成真,但我認為沒有必要直接想成工程師都會被取代,而是我們更要看得懂 LLM 在幹嘛,否則可能產出有嚴重資安或效能問題的程式碼;並且要會判斷哪些寫法只是「能跑」而不是「最佳實踐」。所以對我來說,vibe coding 更像是是一個放大器:基礎功好的人,能用它成為超高生產力的工程師;但基礎不穩的人,很可能會被它坑得更慘。


結語

Terraform 與 CDK 並不是非此即彼,而是解決問題的角度不同:

  • Terraform:宣告式,透明、嚴謹,適合長期維護的大型專案。
  • CDK:程式化,快速、方便,適合一次性建置、與應用程式緊密綁定的場景。

我很慶幸自己有機會同時接觸兩者,因為這讓我能站在不同的角度思考 IaC —— 一邊是「宣告式藍圖」,一邊是「程式化抽象」。

而在 vibe coding 的時代,工具不再是限制,關鍵在於 你能不能理解背後的原理與架構。基礎功好的人不但不會被取代,反而會因為能駕馭 AI 而更有價值。

這篇也是我鐵人賽系列的最後一篇 🥳(終於可以休息了!)。感謝一路以來的閱讀,希望我的 30 天紀錄能帶給你一些無論是對 EKS、Kubernetes、還是 IaC 思維的啟發!>.O


上一篇
[Day 29] EKS 升級紀錄:Kubernetes vs EKS
系列文
EKS in Practice:IaC × GitOps 實戰 30 天30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言