使用 AWS CDK 開發和部署雲端基礎設施的最佳實務 - AWS 雲端開發套件 (AWS CDK) v2

這是 AWS CDK v2 開發人員指南。較舊的 CDK v1 已於 2022 年 6 月 1 日進入維護,並於 2023 年 6 月 1 日結束支援。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 AWS CDK 開發和部署雲端基礎設施的最佳實務

透過 AWS CDK,開發人員或管理員可以使用支援的程式設計語言來定義其雲端基礎設施。CDK 應用程式應組織成邏輯單位,例如 API、資料庫和監控資源,並選擇性地擁有自動化部署的管道。邏輯單位應實作為建構,包括下列項目:

  • 基礎設施 (例如 Amazon S3 儲存貯體、Amazon RDS 資料庫或 Amazon VPC 網路)

  • 執行時間程式碼 (例如 AWS Lambda 函數)

  • 組態程式碼

Stacks 定義這些邏輯單位的部署模型。如需 CDK 背後概念的更詳細介紹,請參閱 AWS CDK 入門

AWS CDK 會仔細考量客戶和內部團隊的需求,以及部署和持續維護複雜雲端應用程式時常出現的故障模式。我們發現故障通常與未經完整測試的應用程式的「out-of-band」變更有關,例如組態變更。因此,我們圍繞一個模型開發 AWS CDK,其中您的整個應用程式在程式碼中定義,不只是商業邏輯,還有基礎設施和組態。如此一來,即可仔細檢閱提議的變更、在類似生產環境內以不同程度全面測試,並在發生問題時完全復原。

代表基礎設施、應用程式、原始程式碼、組態和部署的軟體開發生命週期圖示。

在部署時間, AWS CDK 會合成包含下列項目的雲端組件:

  • 在所有目標環境中描述基礎設施的 AWS CloudFormation 範本

  • 包含執行時間程式碼及其支援檔案的檔案資產

使用 CDK,應用程式主要版本控制分支中的每個遞交都可以代表應用程式的完整、一致、可部署版本。然後,只要進行變更,即可自動部署您的應用程式。

AWS CDK 背後的理念是我們建議的最佳實務,我們分為四大類。

提示

同時考慮適用於 CDK 定義基礎設施的 AWS CloudFormation 最佳實務和您使用的個別 AWS 服務。

組織最佳實務

在 AWS CDK 採用的開始階段,請務必考慮如何設定您的組織以取得成功。最佳實務是讓專家團隊在採用 CDK 時,負責訓練和指導公司的其餘人員。此團隊的大小可能有所不同,從小型公司的一到兩個人員,到大型公司的成熟雲端卓越中心 (CCoE)。此團隊負責為貴公司的雲端基礎設施設定標準和政策,以及培訓和指導開發人員。

CCoE 可能會提供有關雲端基礎設施應使用哪些程式設計語言的指導。每個組織的詳細資訊會有所不同,但良好的政策有助於確保開發人員可以了解和維護公司的雲端基礎設施。

CCoE 也會建立在其中定義組織單位的「登陸區域」 AWS。登陸區域是根據最佳實務藍圖預先設定、安全、可擴展的多帳戶 AWS 環境。若要將組成登陸區域的服務綁定在一起,您可以使用 AWS Control Tower,透過單一使用者介面設定和管理整個多帳戶系統。

開發團隊應該能夠視需要使用自己的帳戶來測試和部署這些帳戶中的新資源。個別開發人員可以將這些資源視為自己開發工作站的延伸。使用 CDK 管道,即可透過 CI/CD 帳戶部署 AWS CDK 應用程式,以測試、整合和生產環境 (各自在自己的 AWS 區域或帳戶中隔離)。這可透過將開發人員的程式碼合併到組織的正式儲存庫來完成。

圖表顯示透過 CI/CD 管道從開發人員帳戶到多個目標帳戶的部署程序。

編碼最佳實務

本節介紹組織 AWS CDK 程式碼的最佳實務。下圖顯示團隊與團隊程式碼儲存庫、套件、應用程式和建構程式庫之間的關係。

顯示團隊程式碼組織的圖表:儲存庫、套件、CDK 應用程式或建構程式庫。
啟動簡單並僅在您需要時才新增複雜性

大多數最佳實務的指導原則是盡可能讓事情簡單,但不會更簡單。只有在您的需求要求更複雜的解決方案時,才增加複雜性。使用 AWS CDK,您可以視需要重構程式碼,以支援新的需求。您不需要預先為所有可能案例進行架構。

與 AWS Well-Architected Framework 保持一致

AWS Well-Architected Framework 將元件定義為一起根據需求交付的程式碼、組態 AWS 和資源。一個元件往往是技術擁有的單元,並自其他元件所解偶。術語工作負載是指一組一起提供業務價值的元件。工作負載通常是商業和技術領導人溝通所談及的最細節的內容。

AWS CDK 應用程式會映射至 AWS Well-Architected Framework. AWS CDK 應用程式定義的元件。CDK 應用程式是一種機制,可編寫和提供 Well-Architected 雲端應用程式最佳實務。您也可以透過成品儲存庫,例如 AWS CodeArtifact,建立和共用元件做為可重複使用的程式碼庫。

每個應用程式都從單一儲存庫中的單一套件開始

單一套件是 AWS CDK 應用程式的進入點。在這裡,您可以定義部署應用程式不同邏輯單位的方式和位置。您也可以定義 CI/CD 管道來部署應用程式。應用程式建構定義解決方案的邏輯單位。

針對您在多個應用程式中使用的建構使用其他套件。(共享建構也應該有自己的生命週期和測試策略。) 相同儲存庫中套件之間的相依性是由您儲存庫的建置工具管理。

雖然可以,但不建議在同一個儲存庫中放置多個應用程式,尤其是在使用自動化部署管道時。這樣做會增加部署期間變更的「爆量半徑」。當儲存庫中有多個應用程式時,變更一個應用程式會觸發其他應用程式部署 (即使其他應用程式尚未變更)。此外,一個應用程式中的中斷可防止部署其他應用程式。

根據程式碼生命週期或團隊擁有權將程式碼移至儲存庫

當套件開始用於多個應用程式時,請將它們移至自己的儲存庫。如此一來,使用它們的應用程式建置系統就可以參考套件,也可以在獨立於應用程式生命週期的節奏上進行更新。不過,一開始將所有共用建構放在一個儲存庫中可能很合理。

此外,在不同團隊處理時,將套件移至自己的儲存庫。這有助於強制執行存取控制。

若要跨儲存庫界限使用套件,您需要一個私有套件儲存庫,類似於 NPM、PyPi 或 Maven Central,但在您的組織內部。您也需要一個發行程序,來建置、測試和發佈套件到私有套件儲存庫。CodeArtifact 可以託管大多數熱門程式設計語言的套件。

套件儲存庫中套件的相依性是由語言的套件管理員管理,例如 TypeScript 或 JavaScript 應用程式的 NPM。您的套件管理員有助於確保組建是可重複的。它透過記錄應用程式依賴的每個套件的特定版本來執行此操作。它還可讓您以受控制的方式升級這些相依性。

共用套件需要不同的測試策略。對於單一應用程式,將應用程式部署到測試環境並確認它仍然有效,可能就足夠了。但共用套件必須獨立於取用應用程式進行測試,就像是公開發行一樣。(您的組織可能會選擇實際將一些共用套件發行給大眾。)

請記住,建構可以是任意簡單或複雜的。Bucket 是建構,但也可以CameraShopWebsite是建構。

相同套件中的基礎設施和執行期程式碼

除了用於部署基礎設施的 generating AWS CloudFormation 範本之外, AWS CDK 還綁定執行期資產,例如 Lambda 函數和 Docker 映像,並將其與您的基礎設施一起部署。這可讓您將定義基礎設施的程式碼,以及實作執行時間邏輯的程式碼,結合到單一建構中。這是最佳實務。這兩種類型的程式碼不需要存在於不同的儲存庫中,甚至在不同的套件中。

若要一起發展這兩種類型的程式碼,您可以使用獨立式建構來完全描述功能,包括其基礎設施和邏輯。使用獨立建構,您可以單獨測試兩種類型的程式碼、跨專案共用和重複使用程式碼,以及同步對所有程式碼進行版本。

建構最佳實務

本節包含開發建構的最佳實務。建構是可重複使用、可組合的模組,可封裝資源。它們是 AWS CDK 應用程式的建置區塊。

使用建構的模型,使用堆疊部署

堆疊是部署單位:堆疊中的所有項目都會一起部署。因此,從多個 AWS 資源建置應用程式的更高層級邏輯單位時, 會將每個邏輯單位表示為建構,而非堆疊。僅使用堆疊來描述應如何針對各種部署案例撰寫和連線您的建構。

例如,如果其中一個邏輯單位是網站,則構成它的建構 (例如 Amazon S3 儲存貯體、API Gateway、Lambda 函數或 Amazon RDS 資料表) 應該組成單一高階建構。然後,該建構應該在一或多個堆疊中執行個體化以進行部署。

透過使用建構和堆疊進行部署,您可以提高基礎設施的重複使用潛力,並提高部署方式的靈活性。

使用屬性和方法設定 ,而非環境變數

建構和堆疊內的環境變數查詢是常見的反模式。建構和堆疊都應該接受屬性物件,以允許完全在程式碼中設定。否則, 會對程式碼執行所在的機器引入相依性,這會建立更多您必須追蹤和管理的組態資訊。

一般而言,環境變數查詢應限於 AWS CDK 應用程式的頂層。它們也應該用來傳入在開發環境中執行 所需的資訊。如需詳細資訊,請參閱 AWS CDK 的環境

單元測試您的基礎設施

若要在所有環境中的建置時間持續執行完整的單元測試套件,請避免在合成期間進行網路查詢,並在程式碼中建立所有生產階段的模型。(以下將介紹這些最佳實務。) 如果任何單一遞交一律會產生相同的產生範本,您可以信任您寫入的單位測試,以確認產生的範本看起來像您預期的方式。如需詳細資訊,請參閱測試 AWS CDK 應用程式

請勿變更具狀態資源的邏輯 ID

變更資源的邏輯 ID 會導致資源在下次部署時被新的資源取代。對於資料庫和 S3 儲存貯體等具狀態資源,或 Amazon VPC 等持久性基礎設施,這很少是您想要的。請注意可能導致 ID 變更的任何 AWS CDK 程式碼重構。撰寫單位測試,宣告具狀態資源IDs 保持靜態。邏輯 ID 衍生自id您在執行個體化建構結構時指定的 ,以及建構結構在建構樹中的位置。如需詳細資訊,請參閱邏輯 IDs

建構不足以合規

許多企業客戶為 L2 建構模組 (代表具有內建 Sane 預設值和最佳實務的個別 AWS 資源的「策劃」建構模組) 編寫自己的包裝函式。這些包裝函式會強制執行安全最佳實務,例如靜態加密和特定 IAM 政策。例如,您可以建立您在應用程式中使用的 MyCompanyBucket,以取代一般的 Amazon S3 Bucket 建構。此模式對於在軟體開發生命週期的早期出現安全指導很有用,但不要依賴它作為唯一強制執行方法。

反之,請使用服務控制政策和許可界限等 AWS 功能,在組織層級強制執行您的安全防護機制。在部署之前,使用 Aspects 和 AWS CDKCloudFormation Guard 等工具來宣告基礎設施元素的安全屬性。將 AWS CDK 用於其最佳用途。

最後,請記住,撰寫您自己的 "L2+" 建構可能會阻止您的開發人員利用 AWS CDK 套件,例如AWS 解決方案建構或第三方建構。這些套件通常以標準 AWS CDK 建構模組為基礎,且無法使用您的包裝函式建構模組。

應用程式最佳實務

在本節中,我們討論如何撰寫 AWS CDK 應用程式,結合 建構來定義 AWS 資源的連線方式。

在合成時間做出決策

雖然 AWS CloudFormation 可讓您在部署時間 (使用 Conditions、 和 Parameters) 做出決策{ Fn::If },而 AWS CDK 可讓您存取這些機制,我們建議您不要使用這些機制。相較於一般用途程式設計語言中可用的值,您可以使用的值類型和可以對其執行的操作類型會受到限制。

反之,請嘗試使用程式設計語言的if陳述式和其他功能,在 AWS CDK 應用程式中做出所有決策,例如要執行個體化的建構。例如,常見的 CDK 慣用詞,在清單上反覆運算,並使用清單中每個項目的值來執行個體化建構,只是無法使用 AWS CloudFormation 表達式。

將 AWS CloudFormation 視為 AWS 實作詳細資訊,CDK 用於強大的雲端部署,而不是語言目標。您不是在 TypeScript 或 Python 中撰寫 AWS CloudFormation 範本,而是撰寫使用 CloudFormation 進行部署的 CDK 程式碼。

使用產生的資源名稱,而非實體名稱

名稱是寶貴的資源。每個名稱只能使用一次。因此,如果您將資料表名稱或儲存貯體名稱硬式編碼到您的基礎設施和應用程式中,您就無法在同一個帳戶中部署該基礎設施兩次。(此處討論的名稱是由 Amazon S3 儲存貯體建構的 bucketName 屬性所指定的名稱。)

更糟的是,您無法變更需要取代的資源。如果屬性只能在資源建立時設定,例如 Amazon DynamoDB 資料表KeySchema的 ,則該屬性是不可變的。變更此屬性需要新的資源。不過,新資源必須具有相同的名稱,才能真正取代。但當現有資源仍在使用該名稱時,它不能具有相同的名稱。

更好的方法是盡可能少地指定名稱。如果您省略資源名稱, AWS CDK 將以不會造成問題的方式為您產生它們。假設您有資料表做為資源。然後,您可以將產生的資料表名稱做為環境變數傳遞至 AWS Lambda 函數。在 AWS CDK 應用程式中,您可以將資料表名稱參考為 table.tableName。或者,您可以在啟動時在 Amazon EC2 執行個體上產生組態檔案,或將實際資料表名稱寫入 AWS Systems Manager 參數存放區,讓您的應用程式可以從該處讀取。

如果您需要的地方是另一個 AWS CDK 堆疊,這更直接。假設一個堆疊定義資源,而另一個堆疊需要使用它,則適用以下條件:

  • 如果兩個堆疊位於相同的 AWS CDK 應用程式中,請在兩個堆疊之間傳遞參考。例如,將資源建構的參考儲存為定義堆疊的屬性 (this.stack.uploadBucket = amzn-s3-demo-bucket)。然後,將該屬性傳遞給需要資源的堆疊建構函式。

  • 當兩個堆疊位於不同的 AWS CDK 應用程式中時,請使用靜態from方法來根據其 ARN、名稱或其他屬性使用外部定義的資源。(例如,Table.fromArn()針對 DynamoDB 資料表使用 )。使用 CfnOutput 建構在 的輸出中列印 ARN 或其他必要值cdk deploy,或在 AWS 管理主控台中查看 。或者,第二個應用程式可以讀取第一個應用程式產生的 CloudFormation 範本,並從 Outputs區段擷取該值。

定義移除政策和日誌保留

AWS CDK 會預設為保留您建立的所有項目的政策,以嘗試防止您遺失資料。例如,包含資料之資源 (例如 Amazon S3 儲存貯體和資料庫資料表) 的預設移除政策是在從堆疊移除資源時,不會將其刪除。反之,資源會從堆疊中孤立。同樣地,CDK 的預設值是永久保留所有日誌。在生產環境中,這些預設值可能會快速導致儲存您實際不需要的大量資料,以及對應的 AWS 帳單。

仔細考慮您希望每個生產資源的這些政策為何,並相應地指定它們。使用 Aspects 和 AWS CDK 驗證堆疊中的移除和記錄政策。

根據部署需求,將您的應用程式分成多個堆疊

對於您的應用程式需要多少堆疊,沒有硬且快速的規則。您通常會根據部署模式做出決策。請記住下列準則:

  • 將盡可能多的資源保留在相同的堆疊中通常更簡單,因此除非您知道它們是分開的,否則請將它們放在一起。

  • 考慮將具狀態資源 (例如資料庫) 保留在與無狀態資源不同的堆疊中。然後,您可以在具狀態堆疊上開啟終止保護。如此一來,您可以自由銷毀或建立無狀態堆疊的多個副本,而不會有資料遺失的風險。

  • 具狀態資源對於建構重新命名更為敏感,重新命名會導致資源取代。因此,請勿在可能移動或重新命名的建構中巢狀具狀態資源 (除非遺失時可以重建狀態,例如快取)。這是在自己的堆疊中放置具狀態資源的另一個好理由。

承諾cdk.context.json避免非確定性的行為

確定性是成功部署 AWS CDK 的關鍵。每當 AWS CDK 應用程式部署到指定的環境時,其結果基本上應該相同。

由於您的 AWS CDK 應用程式是以一般用途程式設計語言撰寫,因此可以執行任意程式碼、使用任意程式庫,以及進行任意網路呼叫。例如,您可以使用 AWS SDK 從 AWS 您的帳戶擷取一些資訊,同時合成您的應用程式。認識到這樣做將導致額外的登入資料設定要求、增加的延遲,以及每次執行 時發生失敗的機率,無論多小cdk synth

請勿在合成期間修改 AWS 您的帳戶或資源。合成應用程式不應有副作用。只有在產生 AWS CloudFormation 範本之後,才應該在部署階段變更基礎設施。如此一來,如果發生問題, AWS CloudFormation 可以自動轉返變更。若要進行無法在 AWS CDK 架構中輕鬆進行的變更,請使用自訂資源在部署時間執行任意程式碼。

即使是嚴格唯讀呼叫也不一定是安全的。考慮網路呼叫傳回的值變更時會發生什麼情況。這會影響基礎設施的哪個部分? 已部署的資源會發生什麼情況? 以下是兩個範例情況,其中值突然變更可能會導致問題。

  • 如果您將 Amazon VPC 佈建至指定區域中所有可用的可用區域,且 AZs 數量在部署日為兩個,則您的 IP 空間會分割成一半。如果 第二天 AWS 啟動新的可用區域,則 之後的下一個部署會嘗試將您的 IP 空間分割為第三個,要求重新建立所有子網路。這可能是不可能的,因為您的 Amazon EC2 執行個體仍在執行中,您必須手動清除。

  • 如果您查詢最新的 Amazon Linux 機器映像並部署 Amazon EC2 執行個體,並在第二天發行新映像,後續部署會挑選新的 AMI 並取代所有執行個體。這可能不是您預期會發生的情況。

這些情況可能很危險,因為 AWS端變更可能會在成功部署數月或數年後發生。突然,您的部署「無故」失敗,而且您很久之前忘記了您做了什麼和原因。

所幸, AWS CDK 包含稱為內容提供者的機制,可記錄非確定性值的快照。這可讓未來的合成操作產生與第一次部署時完全相同的範本。新範本中唯一的變更是您在程式碼中所做的變更。當您使用建構的 .fromLookup()方法時,呼叫的結果會快取在 中cdk.context.json。您應該將此與其餘程式碼一起遞交至版本控制,以確保 CDK 應用程式的未來執行使用相同的值。CDK Toolkit 包含管理內容快取的命令,因此您可以在需要時重新整理特定項目。如需詳細資訊,請參閱內容值和 AWS CDK

如果您需要一些沒有原生 CDK 內容提供者的值 (來自 AWS 或其他位置),建議您撰寫單獨的指令碼。指令碼應該擷取 值並將其寫入檔案,然後在 CDK 應用程式中讀取該檔案。只有在您想要重新整理預存值時才執行指令碼,而不是作為一般建置程序的一部分。

讓 AWS CDK 管理角色和安全群組

使用 AWS CDK 建構程式庫的grant()便利方法,您可以建立 AWS Identity and Access Management 角色,使用最小範圍的許可將存取權授予另一個資源。例如,請考慮如下的行:

amzn-s3-demo-bucket.grantRead(myLambda)

此單行會將政策新增至 Lambda 函數的角色 (也會為您建立)。該角色及其政策是十幾行的 CloudFormation,您不需要撰寫。 AWS CDK 只會授予函數從儲存貯體讀取所需的最低許可。

如果您需要開發人員一律使用安全團隊建立的預先定義角色, AWS CDK 編碼會變得更加複雜。您的團隊在設計應用程式的方式上可能會失去許多彈性。更好的替代方案是使用服務控制政策和許可界限,以確保開發人員保持在護欄內。

建立程式碼中所有生產階段的模型

在傳統 AWS CloudFormation 案例中,您的目標是產生參數化的單一成品,以便在套用這些環境特有的組態值之後,將其部署到各種目標環境。在 CDK 中,您可以且應該將該組態建置到原始程式碼中。為您的生產環境建立堆疊,並為每個其他階段建立個別的堆疊。然後,將每個堆疊的組態值放入程式碼中。使用 Secrets ManagerSystems Manager 參數存放區之類的服務,找出您不想透過這些資源的名稱或 ARNs 來簽入來源控制的敏感值。

當您合成應用程式時,在cdk.out資料夾中建立的雲端組件包含每個環境的個別範本。您的整個建置是確定性的。您的應用程式沒有out-of-band變更,任何指定的遞交一律會產生完全相同的 AWS CloudFormation 範本和隨附的資產。這使得單元測試更加可靠。

測量所有項目

達成完全持續部署的目標,無需人為介入,需要高層級的自動化。只有大量監控才能實現該自動化。若要測量已部署資源的所有層面,請建立指標、警示和儀表板。請勿停止測量 CPU 用量和磁碟空間等項目。同時記錄您的業務指標,並使用這些測量來自動化部署決策,例如轉返。 AWS CDK 中的大多數 L2 建構都有方便的方法可協助您建立指標,例如 dynamodb.Table類別上的 metricUserErrors()方法。