開發和部署雲端基礎架構的最佳做法 AWS CDK - AWS Cloud Development Kit (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 函數)

  • 配置代碼

堆疊定義這些邏輯單元的部署模型。如需「」背後概念的更詳細介紹CDK,請參閱開始使用 AWS CDK

這 AWS CDK 反映了我們的客戶和內部團隊的需求,以及在部署和持續維護複雜雲端應用程式期間經常出現的故障模式。我們發現失敗通常與未完全測試之應用程式的 out-of-band "" 變更有關,例如組態變更。因此,我們開發了 AWS CDK 圍繞一個模型,其中您的整個應用程序在代碼中定義,不僅業務邏輯,而且基礎設施和配置。如此一來,可以仔細檢閱提議的變更,在類似於生產程度的環境中進行全面測試,並在出現問題時完全回復。

Software development lifecycle icons representing infrastructure, application, source code, configuration, and deployment.

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

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

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

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

背後的理念 AWS CDK 導致了我們建議的最佳實踐,我們分為四大類。

提示

同時考慮最佳做法,以 AWS CloudFormation及您使用的個別 AWS 服務 (在適用於 CDK-define 基礎結構的情況下)。

組織最佳實務

在 AWS CDK 採用的開始階段,請務必考慮如何設定組織以取得成功。這是一個最佳做法,有一個專家團隊負責培訓和指導公司的其餘部分,因為他們採用CDK. 這個團隊的規模可能會有所不同,從一個小公司的一個或兩個人到一個成熟的卓越雲中心(CCoE)在一個大公司。該團隊負責為貴公司的雲端基礎架構設定標準和政策,以及培訓和指導開發人員。

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

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

開發團隊應該能夠根據需要使用自己的帳戶在這些帳戶中測試和部署新資源。個別開發人員可以將這些資源視為自己開發工作站的擴充功能。使用 P CDKipelines,可以透過 CI/CD 帳戶將 AWS CDK 應用程式部署到測試、整合和生產環境 (每個環境都隔離在自己的 AWS 區域或帳戶中)。這是通過將開發人員的代碼合併到您組織的規範存儲庫中來完成的。

Diagram showing deployment process from developer accounts to multiple target accounts via CI/CD pipeline.

編碼最佳實踐

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

Diagram showing team's code organization: repository, package, CDK app or construct library.

從簡單開始,只有在需要時才增加複雜性

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

與 Well-Architected 的框 AWS 架保持一致

AWS Well-Architected 的框架將一個組定義為代碼,配置和 AWS 資源,共同提供針對需求。組件通常是技術所有權的單位,並且與其他組件分離。工作負載一詞用於識別一組共同提供商業價值的元件。工作負載通常是企業和技術領導者溝通的詳細程度。

AWS CDK 應用程序映射到由 AWS Well-Architected 的框架定義的組件。 AWS CDK 應用程式是編碼並提供 Well-Architected 雲端應用程式最佳實務的機制。您也可以透過人工因素儲存庫,建立並共用元件做為可重複使用的程式碼庫,例如 AWS CodeArtifact.

每個應用程序都從單個存儲庫中的單個軟件包開始

單個軟件包是應 AWS CDK 用程序的進入點。在這裡,您可以定義如何以及在何處部署應用程序的不同邏輯單元。您也可以定義 CI/CD 管線來部署應用程式。該應用程序的構造定義了解決方案的邏輯單元。

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

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

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

當套件開始在多個應用程式中使用時,請將它們移至自己的儲存庫。如此一來,使用這些套件的應用程式建置系統就可以參考這些套件,也可以在不受應用程式生命週期影響的節奏上進行更新。但是,首先將所有共享結構放在一個存儲庫中可能是有意義的。

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

若要跨儲存庫邊界使用套件,您需要一個私有套件儲存庫 — 類似於NPM PyPi、或 Maven Central,但是組織內部。您也需要一個發行程序來建置、測試套裝程式,並將其發佈至私有套裝程式儲存區域。CodeArtifact可以託管大多數流行編程語言的軟件包。

套裝程式儲存區域中套裝軟體的相依性是由您語言的套件管理員所管理,例如 NPM for TypeScript or JavaScript 應用程式。您的軟件包管理器有助於確保構建是可重複的。它通過記錄應用程序所依賴的每個軟件包的特定版本來實現此目的。它還允許您以受控的方式升級這些依賴關係。

共用套件需要不同的測試策略。對於單個應用程序,將應用程序部署到測試環境並確認它仍然可以正常工作可能足夠好。但是,共享軟件包必須獨立於消費應用程序進行測試,就好像它們被發布給公眾一樣。(您的組織可能會選擇實際發行一些共用套件給大眾。)

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

基礎結構和運行時代碼存在於同一個包中

除了產生用於部署基礎設施的 AWS CloudFormation 範本之外, AWS CDK 還會將 Lambda 函數和 Docker 映像等執行階段資產捆綁在一起,並將它們與基礎設施一起部署。這樣就可以將定義基礎結構的程式碼和實作執行階段邏輯的程式碼結合成單一建構。這是執行此操作的最佳做法。這兩種程式碼不需要位於單獨的儲存庫中,甚至不需要位於單獨的套件中。

若要同時發展這兩種程式碼,您可以使用完整描述功能 (包括其基礎結構和邏輯) 的獨立建構。使用獨立建構,您可以隔離測試這兩種程式碼、跨專案共用和重複使用程式碼,以及同步化所有程式碼的版本。

建構最佳做法

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

具有構造的模型,使用堆棧部署

堆棧是部署的單元:堆棧中的所有內容都一起部署。因此,當從多個 AWS 資源構建應用程序的更高級別的邏輯單元時,將每個邏輯單元表示為 a Construct,而不是. Stack 只使用堆疊來描述如何針對各種部署案例組成和連接建構。

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

透過使用建構來建置和用於部署的堆疊,您可以提高基礎結構的重複使用潛力,並在部署方式上提供更大的彈性。

使用屬性和方法進行配置,而不是環境變量

構造和堆棧中的環境變量查找是常見的反模式。構造和堆棧都應該接受一個屬性對象,以便完全在代碼中完全可配置。否則會引入執行程式碼之機器的相依性,這會建立您必須追蹤和管理的更多設定資訊。

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

單元測試基礎架構

要在所有環境中始終如一地在構建時運行完整的單元測試套件,請避免在合成期間進行網絡查找,並在代碼中對所有生產階段進行模型。(這些最佳做法將在稍後介紹。) 如果任何單次提交總是導致相同的生成模板,則可以信任您編寫的單元測試,以確認生成的模板看起來像您期望的那樣。如需詳細資訊,請參閱測試 AWS CDK 應用

不要變更可設定狀態資源的邏輯 ID

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

構造是不夠的合規

許多企業客戶為 L2 構造編寫自己的包裝函數(「策劃」構造,它們代表具有內置理智默認值和最佳實踐的個別 AWS 資源)。這些包裝函式會強制執行安全性最佳作法,例如靜態加密和特定IAM原則。例如,您可以建立一個MyCompanyBucket,然後在應用程式中使用它來取代一般的 Amazon S3 建Bucket構。這種模式對於在軟體開發生命週期的早期呈現安全性指引非常有用,但不要依賴它作為執行的唯一手段。

而是使用服務控制原則權限界限等 AWS 功能,在組織層級強制執行安全防護。在部署之前,使用方面和 AWS CDK或諸如 CloudFormation Guard 之類的工具,對基礎結構元素的安全性屬性進行宣告。用 AWS CDK 於它最擅長的東西。

最後,請記住,撰寫您自己的「L2+」結構可能會阻止您的開發人員利用 AWS CDK 套件,例如AWS 解決方案結構或來自 Construc t Hub 的協力廠商建構。這些套件通常建立在標準 AWS CDK 結構上,而且無法使用您的包裝函式結構。

應用程式最佳做

在本節中,我們將討論如何編寫 AWS CDK 應用程序,結合構造來定義資 AWS 源的連接方式。

在合成時間做出決定

雖然 AWS CloudFormation 可讓您在部署階段做出決策 (使用Conditions{ Fn::If }、和Parameters),並且可 AWS CDK 讓您存取這些機制,但我們建議您不要使用它們。與通用程式設計語言中可用的值類型相比,您可以使用的值類型以及可對其執行的操作類型受到限制。

相反地,請嘗試使用程式設計語言的if陳述式和其他功能,在 AWS CDK 應用程式中做出所有決定,例如要實體化的建構。例如,一個常見的CDK習慣用法,迭代列表並使用列表中每個項目的值實例化構造,根本不可能使用表達式。 AWS CloudFormation

視 AWS CloudFormation 為 AWS CDK 用於強大雲端部署的實作詳細資料,而不是作為語言目標。您不是在 Python 中 TypeScript 編寫 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 應用程序中,請在兩個堆棧之間傳遞引用。例如,將對資源構造的引用保存為定義的 stack (this.stack.uploadBucket = myBucket) 的屬性。然後,將該屬性傳遞給需要資源的堆棧的構造函數。

  • 當兩個堆棧位於不同的 AWS CDK 應用程序中時,請使用靜態from方法根據其ARN,名稱或其他屬性使用外部定義的資源。(例如,用Table.fromArn()於動 DynamoDB 料表)。使用CfnOutput建構在的輸出中列印ARN或其他所需值cdk deploy,或在中查看 AWS Management Console。或者,第二個應用程序可以讀取第一個應用程序生成的 CloudFormation模板,並從該Outputs部分中檢索該值。

定義移除原則和記錄保留

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

請仔細考慮您希望這些原則適用於每個生產資源的原則,並相應地指定它們。用方面和 AWS CDK於驗證堆疊中的移除和記錄原則。

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

您的應用程序需要多少堆棧沒有硬性和快速的規則。您通常最終會根據部署模式做出決定。請記住以下準則:

  • 將盡可能多的資源盡可能多地保留在同一堆棧中通常更直接,因此除非您知道要將它們分開,否則請將它們保持在一起。

  • 考慮將有狀態資源(如數據庫)與無狀態資源保存在單獨的堆棧中。然後,您可以在可設定狀態堆疊上開啟終止保護。如此一來,您就可以自由銷毀或建立無狀態堆疊的多個副本,而不會造成資料遺失的風險。

  • 有狀態資源對於建構重新命名更敏感 — 重新命名會導致資源取代。因此,請勿將有狀態資源嵌套在可能被移動或重新命名的建構內 (除非遺失時可重建狀態,例如快取)。這是將有狀態資源放在自己的堆棧中的另一個很好的理由。

提交cdk.context.json以避免非確定性行為

決定性是成功 AWS CDK 部署的關鍵。每當 AWS CDK 應用程序部署到給定的環境時,應該具有基本相同的結果。

由於您的 AWS CDK 應用程序是以通用編程語言編寫的,因此它可以執行任意代碼,使用任意庫並進行任意網絡調用。例如,您可以使用 a 在合成應用程序時從您的 AWS 帳戶中檢索某些信息。 AWS SDK認識到這樣做會導致額外的認證設置要求,增加延遲,並且每次運行時都有很小的機會失敗cdk synth

在合成過程中,切勿修改您的 AWS 帳戶或資源。合成應用程序不應該有副作用。只有在產生 AWS CloudFormation 範本之後,才會在部署階段變更基礎結構。這樣,如果有問題, AWS CloudFormation 可以自動回滾更改。要進行無法在 AWS CDK 框架中輕鬆進行的更改,請使用自定義資源在部署時執行任意代碼。

即使嚴格只讀調用也不一定安全。考慮如果網路呼叫傳回的值變更,會發生什麼情況。您的基礎架構的哪一部分會影響? 已部署的資源會發生什麼情況? 以下是其中值突然改變可能會導致一個問題兩個例子的情況。

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

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

這些情況可能是有害的,因為 AWS-side 變更可能會在成功部署數月或數年後發生。突然間,您的部署「無緣無故」失敗,您很久以前就忘記了自己做了什麼以及為什麼。

幸運的是, AWS CDK 包括一種稱為上下文提供者的機制,用於記錄非確定性值的快照。這可讓 future 的合成作業產生與第一次部署時完全相同的範本。新範本中唯一的變更是在程式碼中所做的變更。當你使用一個構造的.fromLookup()方法,調用的結果被緩存在cdk.context.json。您應該將其與代碼的其餘部分一起提交給版本控制,以確保 future 的應用CDK程序執行使用相同的值。CDKToolkit 包含用於管理前後關聯快取的命令,因此您可以在需要時重新整理特定項目。如需詳細資訊,請參閱上下文值和 AWS CDK

如果您需要一些沒有本機CDK上下文提供者的值(來自 AWS 或其他地方),我們建議您編寫單獨的腳本。該腳本應檢索該值並將其寫入文件,然後在您的應CDK用程序中讀取該文件。只有當您想要重新整理儲存的值時,才執行指令碼,而不是做為一般建置程序的一部分。

讓 AWS CDK 管理角色和安全組

使用建AWSCDK構程式庫的grant()便利方法,您可以建立 AWS Identity and Access Management 角色,以使用最低限度範圍的權限來授與另一個資源的存取權。例如,考慮如下所示的一行:

myBucket.grantRead(myLambda)

這一行將政策添加到 Lambda 函數的角色(也是為您創建的)。這個角色及其政策是十幾行 CloudFormation ,你不必寫。僅 AWS CDK 授予函數從值區讀取所需的最低權限。

如果您要求開發人員始終使用由安全團隊創建的預定義角色,則 AWS CDK 編碼變得更加複雜。您的團隊在設計應用程式方面可能會失去很多彈性。更好的替代方法是使用服務控制政策權限界限,以確保開發人員保持在護欄內。

在代碼中為所有生產階段建模

在傳統 AWS CloudFormation 案例中,您的目標是產生一個參數化的單一成品,以便在套用特定於這些環境的組態值之後,將其部署到各種目標環境中。在中CDK,您可以而且應該將該配置構建到您的源代碼中。為您的生產環境建立堆疊,並為其他每個階段建立單獨的堆疊。然後,將每個堆棧的配置值放在代碼中。使用 Secrets ManagerSystems Manager 參數存放區等服務來取得您不想簽入原始檔控制 (使用名稱或這些資源) ARNs 的敏感值。

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

衡量一切

實現完全持續部署的目標,無需人為干預,需要高水平的自動化。只有大量監控才能實現自動化。若要衡量已部署資源的所有層面,請建立指標、警示和儀表板。不要停止測量使用情CPU況和磁盤空間之類的東西。同時記錄您的業務指標,並使用這些測量來自動化部署決策,例如復原。中的大部分 L2 建構 AWS CDK 都有方便的方法來協助您建立度量,例如 Dynamo DB.Table 類別上的metricUserErrors()方法。