堆疊 - AWS Cloud Development Kit (AWS CDK) V2

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

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

堆疊

AWS Cloud Development Kit (AWS CDK) 堆棧是一個或多個構造的集合,它定義了 AWS 資源。每個 CDK 堆疊代表 CDK 應用程式中的一個 AWS CloudFormation 堆疊。在部署時,堆疊內的建構會佈建為單一單元 (稱為 AWS CloudFormation 堆疊)。若要深入瞭解 AWS CloudFormation 堆疊,請參閱使用AWS CloudFormation 者指南中的使用堆疊

由於 CDK 堆疊是透過 AWS CloudFormation 堆疊實作的,因此適用 AWS CloudFormation 配額和限制。若要深入了解,請參閱AWS CloudFormation 配額

定義堆疊

堆疊是在應用程式內容中定義的。您可以使用「 AWS 建構程式庫」中的Stack類別來定義堆疊。您可以使用下列任何一種方式來定義堆疊:

  • 直接在應用程序的範圍內。

  • 間接由樹中的任何構造。

下列範例會定義包含兩個堆疊的 CDK 應用程式:

TypeScript
const app = new App(); new MyFirstStack(app, 'stack1'); new MySecondStack(app, 'stack2'); app.synth();
JavaScript
const app = new App(); new MyFirstStack(app, 'stack1'); new MySecondStack(app, 'stack2'); app.synth();
Python
app = App() MyFirstStack(app, 'stack1') MySecondStack(app, 'stack2') app.synth()
Java
App app = new App(); new MyFirstStack(app, "stack1"); new MySecondStack(app, "stack2"); app.synth();
C#
var app = new App(); new MyFirstStack(app, "stack1"); new MySecondStack(app, "stack2"); app.Synth();

下列範例是在個別檔案上定義堆疊的常見模式。在這裡,我們擴展或繼承Stack類,並定義一個接受scopeid、和的構造函數props。然後,我們使用接收的scopeid和調super用基Stack類構造函數props

TypeScript
class HelloCdkStack extends Stack { constructor(scope: App, id: string, props?: StackProps) { super(scope, id, props); //... } }
JavaScript
class HelloCdkStack extends Stack { constructor(scope, id, props) { super(scope, id, props); //... } }
Python
class HelloCdkStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # ...
Java
public class HelloCdkStack extends Stack { public HelloCdkStack(final Construct scope, final String id) { this(scope, id, null); } public HelloCdkStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); // ... } }
C#
public class HelloCdkStack : Stack { public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) { //... } }
Go
func HelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } stack := awscdk.NewStack(scope, &id, &sprops) return stack }

下列範例宣告一個名為的堆疊類別,其中包MyFirstStack含單一 Amazon S3 儲存貯體。

TypeScript
class MyFirstStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); new s3.Bucket(this, 'MyFirstBucket'); } }
JavaScript
class MyFirstStack extends Stack { constructor(scope, id, props) { super(scope, id, props); new s3.Bucket(this, 'MyFirstBucket'); } }
Python
class MyFirstStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) s3.Bucket(self, "MyFirstBucket")
Java
public class MyFirstStack extends Stack { public MyFirstStack(final Construct scope, final String id) { this(scope, id, null); } public MyFirstStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); new Bucket(this, "MyFirstBucket"); } }
C#
public class MyFirstStack : Stack { public MyFirstStack(Stack scope, string id, StackProps props = null) : base(scope, id, props) { new Bucket(this, "MyFirstBucket"); } }
Go
func MyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } stack := awscdk.NewStack(scope, &id, &sprops) s3.NewBucket(stack, jsii.String("MyFirstBucket"), &s3.BucketProps{}) return stack }

但是,此代碼只聲明了一個堆棧。為了使堆棧實際合成到 AWS CloudFormation 模板中並進行部署,必須實例化它。而且,像所有 CDK 結構一樣,它必須在某些情況下實例化。就App是上下文。

如果您使用的是標準 AWS CDK 開發模板,則堆棧將在實例化對象的同一文件中實例化。App

TypeScript

以專案資料夾中的專案 (例如hello-cdk.ts) 命名的檔bin案。

JavaScript

以專案資料夾中的專案 (例如hello-cdk.js) 命名的檔bin案。

Python

專案主目錄app.py中的檔案。

Java

名為的文件ProjectNameApp.java,例如HelloCdkApp.java,嵌套在src/main目錄下深處。

C#

例如src\ProjectNameProgram.cs在下命名的檔案src\HelloCdk\Program.cs

堆棧 API

堆棧對象提供了一個豐富的 API,包括以下內容:

  • Stack.of(construct)— 傳回定義建構之 Stack 的靜態方法。如果您需要從可重複使用的構造中與堆棧進行交互,這非常有用。如果在範圍內找不到堆棧,則調用失敗。

  • stack.stackName(Python:stack_name)-返回堆棧的物理名稱。如前所述,所有 AWS CDK 堆棧都具有 AWS CDK 可以在合成過程中解析的物理名稱。

  • stack.regionstack.account — 傳回 AWS 區域和帳戶,分別將部署此堆疊。這些屬性會傳回下列其中一項:

    • 定義堆疊時明確指定的帳戶或區域

    • 字符串編碼的令牌,解析為帳戶和 Region 的 AWS CloudFormation 虛擬參數,以指示此堆棧與環境無關

    如需如何判斷堆疊環境的相關資訊,請參閱環境

  • stack.addDependency(stack)(Python: stack.add_dependency(stack)-可用於顯式定義兩個堆棧之間的依賴關係順序。一次部署多個堆疊時,cdk deploy命令會遵守此順序。

  • stack.tags— 傳回可用來新增或移除堆疊層級標籤的一TagManager個。這個標籤管理器標記堆棧中的所有資源,並且在創建堆棧時也標記堆棧本身 AWS CloudFormation。

  • stack.partitionstack.urlSuffix(Python:url_suffix),stack.stackId(Python:stack_id)和stack.notificationArn(Python:notification_arn)-返回解析為相應 AWS CloudFormation 虛擬參數的令牌,例如{ "Ref": "AWS::Partition" }。這些令牌與特定的堆棧對象相關聯,以便 AWS CDK 框架可以識別跨堆棧引用。

  • stack.availabilityZones(Python:availability_zones) — 傳回部署此堆疊之環境中可用的一組可用區域。對於與環境無關的堆疊,這一定會傳回具有兩個可用區域的陣列。對於環境特定堆疊,會 AWS CDK 查詢環境並傳回您指定之區域中可用的確切可用區域集。

  • stack.parseArn(arn)stack.formatArn(comps) (Python:parse_arn,format_arn) — 可用於使用 Amazon 資源名稱 (ARN).

  • stack.toJsonString(obj)(Python:to_json_string) — 可用於將任意物件格式化為可嵌入 AWS CloudFormation 範本中的 JSON 字串。該對象可以包括令牌,屬性和引用,這些標記和引用僅在部署期間解析。

  • stack.templateOptions(Python:template_options) — 用來指定堆疊的 AWS CloudFormation 範本選項,例如「轉換」、「描述」和「中繼資料」。

使用堆疊

若要列出 CDK 應用程式中的所有堆疊,請使用指cdk ls令。前面的例子將輸出以下內容:

stack1
stack2

堆疊會部署為 AWS CloudFormation 堆疊的一部分到環 AWS 中。環境涵蓋了一個特定的 AWS 帳戶 和 AWS 區域.

當您針對具有多個堆疊的應用程式執行cdk synth命令時,雲端組件會針對每個堆疊執行個體包含個別的範本。即使兩個堆疊是相同類別的執行個體,也會將 AWS CDK 它們當做兩個個別範本發出。

您可以通過在cdk synth命令中指定堆棧名稱來合成每個模板。下面的例子合成了堆棧 1 的模板。

$ cdk synth stack1

這種方法在概念上與模 AWS CloudFormation 板通常使用方式不同,模板可以多次部署並通過AWS CloudFormation 參數參數化。雖然 AWS CloudFormation 參數可以在中定義 AWS CDK,但通常不鼓勵參數,因為 AWS CloudFormation 參數只能在部署期間解析。這意味著您無法在代碼中確定它們的值。

例如,要根據參數值在應用程序中有條件地包含資源,則必須設置AWS CloudFormation 條件並使用它標記資源。 AWS CDK 採用了一種在合成時解析具體模板的方法。因此,您可以使用 if 陳述式來檢查值,以判斷是否應該定義資源或應套用某些行為。

注意

在合成期間 AWS CDK 提供盡可能多的分辨率,以使您的編程語言的慣用和自然使用。

像任何其他構造,堆棧可以組成組合在一起。下列程式碼顯示由三個堆疊組成的服務範例:控制平面、資料平面和監視堆疊。服務結構定義了兩次:一次用於測試版環境,一次用於生產環境。

TypeScript
import { App, Stack } from 'aws-cdk-lib'; import { Construct } from 'constructs'; interface EnvProps { prod: boolean; } // imagine these stacks declare a bunch of related resources class ControlPlane extends Stack {} class DataPlane extends Stack {} class Monitoring extends Stack {} class MyService extends Construct { constructor(scope: Construct, id: string, props?: EnvProps) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } const app = new App(); new MyService(app, "beta"); new MyService(app, "prod", { prod: true }); app.synth();
JavaScript
const { App, Stack } = require('aws-cdk-lib'); const { Construct } = require('constructs'); // imagine these stacks declare a bunch of related resources class ControlPlane extends Stack {} class DataPlane extends Stack {} class Monitoring extends Stack {} class MyService extends Construct { constructor(scope, id, props) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } const app = new App(); new MyService(app, "beta"); new MyService(app, "prod", { prod: true }); app.synth();
Python
from aws_cdk import App, Stack from constructs import Construct # imagine these stacks declare a bunch of related resources class ControlPlane(Stack): pass class DataPlane(Stack): pass class Monitoring(Stack): pass class MyService(Construct): def __init__(self, scope: Construct, id: str, *, prod=False): super().__init__(scope, id) # we might use the prod argument to change how the service is configured ControlPlane(self, "cp") DataPlane(self, "data") Monitoring(self, "mon") app = App(); MyService(app, "beta") MyService(app, "prod", prod=True) app.synth()
Java
package com.myorg; import software.amazon.awscdk.App; import software.amazon.awscdk.Stack; import software.constructs.Construct; public class MyApp { // imagine these stacks declare a bunch of related resources static class ControlPlane extends Stack { ControlPlane(Construct scope, String id) { super(scope, id); } } static class DataPlane extends Stack { DataPlane(Construct scope, String id) { super(scope, id); } } static class Monitoring extends Stack { Monitoring(Construct scope, String id) { super(scope, id); } } static class MyService extends Construct { MyService(Construct scope, String id) { this(scope, id, false); } MyService(Construct scope, String id, boolean prod) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } public static void main(final String argv[]) { App app = new App(); new MyService(app, "beta"); new MyService(app, "prod", true); app.synth(); } }
C#
using Amazon.CDK; using Constructs; // imagine these stacks declare a bunch of related resources public class ControlPlane : Stack { public ControlPlane(Construct scope, string id=null) : base(scope, id) { } } public class DataPlane : Stack { public DataPlane(Construct scope, string id=null) : base(scope, id) { } } public class Monitoring : Stack { public Monitoring(Construct scope, string id=null) : base(scope, id) { } } public class MyService : Construct { public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) { // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } class Program { static void Main(string[] args) { var app = new App(); new MyService(app, "beta"); new MyService(app, "prod", prod: true); app.Synth(); } }

此 AWS CDK 應用程序最終由六個堆棧組成,每個環境三個堆棧:

$ cdk ls betacpDA8372D3 betadataE23DB2BA betamon632BD457 prodcp187264CE proddataF7378CE5 prodmon631A1083

堆 AWS CloudFormation 疊的實體名稱會 AWS CDK 根據樹狀結構中堆疊的建構路徑自動決定。默認情況下,堆棧的名稱是從Stack對象的構造 ID 派生的。但是,您可以使用 stackName prop (在 Python 中stack_name) 來指定明確的名稱,如下所示。

TypeScript
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
JavaScript
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
Python
MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")
Java
new MyStack(this, "not:a:stack:name", StackProps.builder() .StackName("this-is-stack-name").build());
C#
new MyStack(this, "not:a:stack:name", new StackProps { StackName = "this-is-stack-name" });

巢狀堆疊

NestedStack構造提供了一種圍繞堆棧 AWS CloudFormation 500 資源限制的方法。嵌套堆棧算作在包含它的堆棧中只有一個資源。不過,它最多可以包含 500 個資源,包括其他巢狀堆疊。

嵌套堆棧的範圍必須是StackNestedStack構造。嵌套堆棧不需要在其父堆棧中詞法聲明。在實例化嵌套堆棧時,只需要將父堆棧作為第一個參數(scope)傳遞。除了這個限制之外,定義嵌套堆棧中的構造的工作原理與普通堆棧中的結構完全相同。

在合成時,嵌套堆棧合成為其自己的 AWS CloudFormation 模板,該模板在部署時將其上傳到 AWS CDK 臨時存儲桶。巢狀堆疊繫結至其父系堆疊,不會視為獨立的部署成品。它們不是由列出cdk list,而且不能由部署cdk deploy

父堆棧和嵌套堆棧之間的引用會自動轉換為生成的 AWS CloudFormation 模板中的堆棧參數和輸出,就像任何跨堆棧引用一樣。

警告

部署巢狀堆疊之前,不會顯示安全狀況的變更。此資訊僅針對頂層堆疊顯示。