

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

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

# AWS CDK 堆疊簡介
<a name="stacks"></a>

 AWS CDK 堆疊是最小的單一部署單位。它代表您使用 CDK 建構定義之 AWS 資源的集合。當您部署 CDK 應用程式時，CDK 堆疊內的資源會一起部署為 an AWS CloudFormation 堆疊。若要進一步了解 AWS CloudFormation 堆疊，請參閱《[AWS CloudFormation 使用者指南》中的使用 CloudFormation 堆疊以單一單位管理 AWS 資源](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html)。 * AWS CloudFormation *

您可以透過延伸或繼承[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)建構來定義堆疊。下列範例是在個別檔案上定義 CDK 堆疊的常見模式，稱為*堆疊檔案*。在這裡，我們擴展或繼承 `Stack`類別，並定義接受 `scope`、 `id`和 的建構函數`props`。然後，我們使用 `super` 搭配收到的 `scope`、 `id`和 來調用基本`Stack`類別建構函數`props`：

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Define your constructs here

  }
}
```

```
const { Stack } = require('aws-cdk-lib');

class MyCdkStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define your constructs here

  }
}

module.exports = { MyCdkStack }
```

```
from aws_cdk import (
  Stack,
)
from constructs import Construct

class MyCdkStack(Stack):

  def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
    super().__init__(scope, construct_id, **kwargs)

    # Define your constructs here
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class MyCdkStack extends Stack {
  public MyCdkStack(final Construct scope, final String id) {
    this(scope, id, null);
  }

  public MyCdkStack(final Construct scope, final String id, final StackProps props) {
    super(scope, id, props);

    // Define your constructs here
  }
}
```

```
using Amazon.CDK;
using Constructs;

namespace MyCdk
{
  public class MyCdkStack : Stack
  {
    internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
    {
      // Define your constructs here
    }
  }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return stack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

//...
```

上一個範例只定義了堆疊。若要建立堆疊，必須在 CDK 應用程式的內容中執行個體化。常見的模式是定義 CDK 應用程式，並在稱為*應用程式檔案*的個別檔案上初始化您的堆疊。

以下是建立名為 之 CDK 堆疊的範例`MyCdkStack`。在這裡，CDK 應用程式會建立`MyCdkStack`並在應用程式的內容中執行個體化：

**Example**  

```
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MyCdkStack } from '../lib/my-cdk-stack';

const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
```

```
#!/usr/bin/env node

const cdk = require('aws-cdk-lib');
const { MyCdkStack } = require('../lib/my-cdk-stack');

const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
```
位於 ： `app.py`  

```
#!/usr/bin/env python3
import os

import aws_cdk as cdk

from my_cdk.my_cdk_stack import MyCdkStack


app = cdk.App()
MyCdkStack(app, "MyCdkStack",)

app.synth()
```

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;

import java.util.Arrays;

public class MyCdkApp {
  public static void main(final String[] args) {
    App app = new App();

    new MyCdkStack(app, "MyCdkStack", StackProps.builder()
      .build());

    app.synth();
  }
}
```

```
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCdk
{
  sealed class Program
  {
    public static void Main(string[] args)
    {
      var app = new App();
      new MyCdkStack(app, "MyCdkStack", new StackProps
      {});
      app.Synth();
    }
  }
}
```

```
package main

import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/constructs-go/constructs/v10"
  "github.com/aws/jsii-runtime-go"
)

// ...

func main() {
  defer jsii.Close()

  app := awscdk.NewApp(nil)

  NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{
    awscdk.StackProps{
      Env: env(),
    },
  })

  app.Synth(nil)
}

// ...
```

下列範例會建立包含兩個堆疊的 CDK 應用程式：

**Example**  

```
const app = new App();

new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');

app.synth();
```

```
const app = new App();

new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');

app.synth();
```

```
app = App()

MyFirstStack(app, 'stack1')
MySecondStack(app, 'stack2')

app.synth()
```

```
App app = new App();

new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");

app.synth();
```

```
var app = new App();

new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");

app.Synth();
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type MyFirstStackProps struct {
	awscdk.StackProps
}

func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	myFirstStack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return myFirstStack
}

type MySecondStackProps struct {
	awscdk.StackProps
}

func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	mySecondStack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return mySecondStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	NewMySecondStack(app, "MySecondStack", &MySecondStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

// ...
```

## 關於堆疊 API
<a name="stack-api"></a>

[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) 物件提供豐富的 API，包括下列項目：
+  `Stack.of(construct)` – 傳回定義建構之**堆疊**的靜態方法。如果您需要在可重複使用的建構中與堆疊互動，這非常有用。如果在範圍內找不到堆疊，呼叫會失敗。
+  `stack.stackName` (Python：`stack_name`) – 傳回堆疊的實體名稱。如前所述，所有 AWS CDK 堆疊都有實體名稱， AWS CDK 可以在合成期間解析。
+  `stack.region` 和 `stack.account` – 分別傳回要部署此堆疊的區域 AWS 和帳戶。這些屬性會傳回下列其中一項：
  + 定義堆疊時明確指定的帳戶或區域
  + 字串編碼字符，可解析為帳戶和區域的 AWS CloudFormation 虛擬參數，以指出此堆疊與環境無關

    如需如何決定堆疊環境的資訊，請參閱 [AWS CDK 的環境](environments.md)。
+  `stack.addDependency(stack)` (Python：`stack.add_dependency(stack)`) – 可用於明確定義兩個堆疊之間的相依性順序。一次部署多個堆疊時，`cdk deploy`命令會遵守此順序。
+  `stack.tags` – 傳回可用來新增或移除堆疊層級標籤的 [TagManager](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html)。此標籤管理員會標記堆疊中的所有資源，也會在透過 AWS CloudFormation 建立堆疊時標記堆疊本身。
+  `stack.partition`、 `stack.urlSuffix`(Python：`url_suffix`)、 `stack.stackId`(Python：`stack_id`) 和 `stack.notificationArn`(Python：`notification_arn`) – 傳回解析為 respective 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 Resource Name (ARNs)。
+  `stack.toJsonString(obj)` (Python：`to_json_string`) – 可用於將任意物件格式化為可內嵌在 an AWS CloudFormation 範本中的 JSON 字串。物件可以包含權杖、屬性和參考，這些權杖、屬性和參考只能在部署期間解析。
+  `stack.templateOptions` (Python：`template_options`) – 使用 為您的堆疊指定 AWS CloudFormation 範本選項，例如 Transform、Description 和 Metadata。

## 使用堆疊
<a name="stacks-work"></a>

堆疊會以 an AWS CloudFormation 堆疊的形式部署到 AWS [環境中](environments.md)。環境涵蓋特定 AWS 帳戶和 AWS 區域。

當您為具有多個堆疊的應用程式執行 `cdk synth`命令時，雲端組件會包含每個堆疊執行個體的個別範本。即使兩個堆疊是相同類別的執行個體， AWS CDK 仍會以兩個個別範本的形式發出它們。

您可以在 `cdk synth`命令中指定堆疊名稱，以合成每個範本。下列範例會合成 的 範本`stack1`：

```
$ cdk synth <stack1>
```

此方法在概念上不同於 AWS CloudFormation 範本通常的使用方式，其中範本可以透過 [AWS CloudFormation 參數](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)部署多次和參數化。雖然 AWS CloudFormation 參數可以在 AWS CDK 中定義，但通常不鼓勵它們，因為 AWS CloudFormation 參數只會在部署期間解析。這表示您無法在程式碼中判斷其值。

例如，若要根據參數值在應用程式中有條件地包含資源，您必須設定 [AWS CloudFormation 條件](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html)並使用它標記資源。 AWS CDK 採用一種方法，在合成時解析具體範本。因此，您可以使用 `if`陳述式來檢查 值，以判斷是否應定義資源或應套用某些行為。

**注意**  
 AWS CDK 在合成期間盡可能提供解析度，以啟用程式設計語言的栩栩如生和自然使用。

如同任何其他建構，堆疊可以組合成群組。下列程式碼顯示由三個堆疊組成的服務範例：控制平面、資料平面和監控堆疊。服務建構定義兩次：一次用於測試環境，一次用於生產環境。

**Example**  

```
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();
```

```
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();
```

```
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()
```

```
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();
    }
}
```

```
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();
    }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type ControlPlaneStackProps struct {
	awscdk.StackProps
}

func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return ControlPlaneStack
}

type DataPlaneStackProps struct {
	awscdk.StackProps
}

func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return DataPlaneStack
}

type MonitoringStackProps struct {
	awscdk.StackProps
}

func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return MonitoringStack
}

type MyServiceStackProps struct {
	awscdk.StackProps
	Prod bool
}

func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{
		StackProps: sprops,
	})
	NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{
		StackProps: sprops,
	})
	NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{
		StackProps: sprops,
	})

	return MyServiceStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	betaProps := MyServiceStackProps{
		StackProps: awscdk.StackProps{
			Env: env(),
		},
		Prod: false,
	}

	NewMyServiceStack(app, "beta", &betaProps)

	prodProps := MyServiceStackProps{
		StackProps: awscdk.StackProps{
			Env: env(),
		},
		Prod: true,
	}

	NewMyServiceStack(app, "prod", &prodProps)

	app.Synth(nil)
}

// ...
```
此 AWS CDK 應用程式最終包含六個堆疊，每個環境三個堆疊：  

```
$ cdk ls

betacpDA8372D3
betadataE23DB2BA
betamon632BD457
prodcp187264CE
proddataF7378CE5
prodmon631A1083
```

 AWS CloudFormation 堆疊的實體名稱是由 AWS CDK 根據堆疊在樹狀結構中的建構路徑自動決定。根據預設，堆疊的名稱衍生自`Stack`物件的建構 ID。不過，您可以使用 prop `stackName` （在 Python 中為 `stack_name`) 指定明確名稱，如下所示。

**Example**  

```
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
```

```
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
```

```
MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")
```

```
new MyStack(this, "not:a:stack:name", StackProps.builder()
    .StackName("this-is-stack-name").build());
```

```
new MyStack(this, "not:a:stack:name", new StackProps
{
    StackName = "this-is-stack-name"
});
```

### 使用巢狀堆疊
<a name="stack-nesting"></a>

*巢狀堆疊*是您在另一個堆疊中建立的 CDK 堆疊，稱為父堆疊。您可以使用 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html) 建構模組建立巢狀堆疊。

透過使用巢狀堆疊，您可以跨多個堆疊組織資源。巢狀堆疊也提供堆疊的 AWS CloudFormation 500 資源限制。巢狀堆疊只會計為堆疊中包含它的一個資源。不過，它最多可包含 500 個資源，包括額外的巢狀堆疊。

巢狀堆疊的範圍必須是 `Stack`或 `NestedStack` 建構。巢狀堆疊不需要在其父堆疊內以合法方式宣告。只有在執行個體化巢狀堆疊時，才需要傳遞父堆疊做為第一個參數 (`scope`)。除了此限制之外，在巢狀堆疊中定義建構的運作方式與一般堆疊完全相同。

在合成時間，巢狀堆疊會合成至其自己的 AWS CloudFormation 範本，並在部署時上傳至 AWS CDK 預備儲存貯體。巢狀堆疊繫結至其父堆疊，不會視為獨立的部署成品。它們不會由 列出`cdk list`，也無法由 部署`cdk deploy`。

父堆疊和巢狀堆疊之間的參考會自動轉譯為 generated AWS CloudFormation 範本中的堆疊參數和輸出，就像任何[跨堆疊參考](resources.md#resource-stack)一樣。

**警告**  
部署巢狀堆疊之前，不會顯示安全狀態的變更。此資訊只會針對最上層堆疊顯示。