iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Build on AWS

一步步帶你認識 Cloud Native —— 用AWS免費服務打造雲原生專案系列 第 7

Day7 剖析CDK專案架構 Construct的三個層次| 程式化部署AWS服務邁向CI/CD!(4)

  • 分享至 

  • xImage
  •  

歡迎來到本系列的第七篇文章!


上一篇的內容中,我們認識了CloudFormation以及CDK,並且明白IaC (Infrastructure as Code)的概念,最終建置出了我們的 CDK 專案,而今天我們要深度剖析 CDK專案(python)的檔案目錄,了解在撰寫IaC時究竟會發生什麼事情!


所以 CDK 的真實身分到底是什麼?

之前我們學到了CDK就是包裝成程式的CloudFormation(可以想像成很強的CloudFormation SDK),可以用程式來生成Template,也就是CloudFormation Stack的藍圖。進而創造CloudFormation Stack 而完成 AWS 資源的部署。

但當我們將它放大到程式單位來看時,我們也可以發現該是最終成品的CloudFormation Stack 是如何被慢慢分解成程式的,這就涉及到一個重要的概念 Construct


Construct 概念介紹

在 CDK 中,我們用 Construct 來代表 AWS 的資源,也就是說 Construct 代表基礎設施(AWS 服務)的邏輯單元。無論你定義一個簡單的 S3 Bucket,還是一個複雜的應用系統,Construct 都是組織和管理這些資源的基礎。它提供了一種層次化的方式,讓你從低階到高階逐步構建 IaC。

什麼是 Construct?

作用:它將 AWS 服務(如 S3、Lambda、VPC)封裝成可重用的模塊,並支援層次結構,讓你將小的 Construct 組合為更大的結構。
層次結構:Construct 可以構成一個樹狀結構,最頂層通常是 App,然後是 Stack,最後是具體的資源或自訂 Construct。

像以下這樣:

from aws_cdk import core as cdk, aws_s3 as s3

app = cdk.App()                                                  # app在最頂層
stack = cdk.Stack(app, "MyStack")                                # stack透過繼承app來定義
bucket = s3.Bucket(stack, "MyBucket", bucket_name="my-bucket")   # 最後是Construct

在下圖中,一個App中包含了兩個Stack,而他們各自裏面包含了不同的 AWS 資源。

App
├── Stack1
│   ├── Bucket1
│   └── Lambda1
├── Stack2
│   ├── Bucket2
│   └── Queue1

Construct 的3個 Level
CDK 提供三種類型的 Construct,根據抽象層次不同,分別適用於不同的使用場景:

1.L1 (Level 1) - CloudFormation 資源 (Cfn 資源):

  • 特點:直接映射到 AWS CloudFormation 的資源,名稱通常以 Cfn 開頭(例如 CfnBucket)。
  • 用途:提供底層控制,允許你精確配置每個屬性,對應 CloudFormation 的 JSON/YAML 模板。除非你非常熟練AWS服務的配置,需要調整細節,否則極少用到
  • 範例:
from aws_cdk import core as cdk, aws_s3 as s3

class MyCdkAppStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        bucket = s3.CfnBucket(self, "MyCfnBucket", bucket_name="my-cfn-bucket")

2.L2 (Level 2) - 高階抽象:

  • 特點:基於 L1 資源,提供了更高層次的 API,包含預設值和簡化配置。
  • 用途:減少重複工作,提供常見資源的「最佳實踐」配置,例如 s3.Bucket 自動設置權限。讓你可以省略一些手動設定,直接套用預設值
  • 範例:
bucket = s3.Bucket(self, "MyBucket", bucket_name="my-l2-bucket")

3.L3 (Level 3) - 模式 (Patterns):

  • 特點:封裝多個 L1/L2 資源,形成完整的解決方案,例如 S3 與 CloudFront 的組合。
  • 用途:適用於複雜應用場景,提供開箱即用的模式。
  • 範例(假設使用 aws_cdk.aws_cloudfront):
from aws_cdk import core as cdk, aws_s3 as s3, aws_cloudfront as cloudfront

class MyCdkAppStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        bucket = s3.Bucket(self, "MyBucket", bucket_name="my-l3-bucket")
        distribution = cloudfront.CloudFrontWebDistribution(self, "MyDistribution",
            origin_configs=[{
                "s3_origin_source": {"s3_bucket_source": bucket}
            }]
        )

回到我們前一天建置的專案上

在了解了這些概念後,讓我們看回昨天建置出的這個檔案目錄。來進一步認識他們各自的腳色
https://ithelp.ithome.com.tw/upload/images/20250817/20178103sWUybfooDZ.png

關鍵檔案與資料夾

  1. app.py - 入口點,定義 App 和 Stack (也就是樹狀結構中的頂點 App)
  • 作用:
    • 這是 CDK 應用程式的入口檔案,負責初始化 App 對象並實例化一個或多個 Stack。
    • 當執行 cdk synthcdk deploy 時,CDK 會從 app.py 開始解析,生成 CloudFormation 模板。
  • 內容範例

https://ithelp.ithome.com.tw/upload/images/20250817/20178103lKDkRUVPmG.png

中間一堆註解先不管,有興趣可以讀一下

  • 說明:
    • cdk.App() 創建應用程式實例。
    • MyCdkAppStack 是堆疊類別的實例化。
    • app.synth() 觸發模板合成,生成 cdk.out/ 中的檔案

這些是CDK專案的起點,決定了應用程式的結構和行為。

2.my_cdk_app_stack.py - (Stack 樹狀結構中的第二層,在裡面包含多個Construct)

  • 作用:
    • 這是定義 AWS 資源(如 S3 Bucket、Lambda 函數)的核心檔案。
    • 每個 Stack 類別對應一個 CloudFormation 堆疊,包含資源的邏輯和配置。
  • 內容範例
    https://ithelp.ithome.com.tw/upload/images/20250817/20178103i2Jtt9jQZW.png
  • 說明
    • s3.Bucket 是一個 L2 construct,簡化 S3 資源的配置。
    • CfnOutput 輸出資源屬性,方便檢查或後續使用。

這個就是IaC專案中我們會最常互動的檔案,所有的資源都在這裡透過Construct定義

  1. test_my_cdk_app_stack.py - 單元測試檔案
  • 作用:
    • 利用pytest模擬模板生成過程並檢查模板內容,讓你不必真實部署到AWS就可以偵錯。
# tests/unit/test_my_cdk_app_stack.py
import pytest
from aws_cdk import core as cdk
from my_cdk_app.my_cdk_app_stack import MyCdkAppStack

def test_bucket_created():
    app = cdk.App()
    stack = MyCdkAppStack(app, "MyCdkAppStack")
    template = app.synth().get_stack_by_name("MyCdkAppStack").template
    buckets = [r for r in template["Resources"].values() if r["Type"] == "AWS::S3::Bucket"]
    assert len(buckets) == 1
    assert buckets[0]["Properties"]["BucketName"] == "my-example-bucket"
  • 說明
    • app.synth() 模擬合成過程,生成模板。
    • 檢查模板中的資源數量和屬性(例如 BucketName)。

這份檔案對於CI/CD流程很重要,與Github Action等CI/CD工具有強大的集成。 (敬請期待)


結語

今天的內容都以概念為主,因為篇幅有點長,實作的部分就再拆分到下一集了。請期待實作的各位再過一天馬上要來了哈哈


上一篇
Day6 IaC 程式定義基礎設施 CloudFormation及 CDK介紹| 程式化部署AWS服務邁向CI/CD!(3)
下一篇
Day8 AWS CDK資源部署,CLI 以及 Construct 撰寫| 程式化部署AWS服務邁向CI/CD!(5)
系列文
一步步帶你認識 Cloud Native —— 用AWS免費服務打造雲原生專案23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
viiccwen
iT邦新手 5 級 ‧ 2025-08-18 09:17:48

好的,很期待。

我要留言

立即登入留言