

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段，并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 资源和 AWS CDK
<a name="resources"></a>

 *资源*是您为在应用程序中使用 AWS 服务而配置的资源。资源是的功能 AWS CloudFormation。通过在 AWS CloudFormation 模板中配置资源及其属性，您可以部署 AWS CloudFormation 到以配置资源。借助 C AWS loud Development Kit (AWS CDK)，您可以通过结构配置资源。然后，您部署您的 CDK 应用程序，其中包括合成 AWS CloudFormation 模板并部署 AWS CloudFormation 到以配置您的资源。

## 使用构造来配置资源
<a name="resources-configure"></a>

正如 [AWS CDK Constructs](constructs.md) 中所述， AWS CDK 提供了一个丰富的构造类库，称为*构造*，代表所有资源。 AWS 

要使用资源对应的构造来创建资源实例，请将作用域作为第一个参数、构造的逻辑 ID 和一组配置属性（props）传入。例如，以下是如何使用构造库中的[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html)构造创建采用 AWS KMS 加密的 Amazon SQS 队列。 AWS 

**Example**  

```
import * as sqs from '@aws-cdk/aws-sqs';

new sqs.Queue(this, 'MyQueue', {
    encryption: sqs.QueueEncryption.KMS_MANAGED
});
```

```
const sqs = require('@aws-cdk/aws-sqs');

new sqs.Queue(this, 'MyQueue', {
    encryption: sqs.QueueEncryption.KMS_MANAGED
});
```

```
import aws_cdk.aws_sqs as sqs

sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED)
```

```
import software.amazon.awscdk.services.sqs.*;

Queue.Builder.create(this, "MyQueue").encryption(
        QueueEncryption.KMS_MANAGED).build();
```

```
using Amazon.CDK.AWS.SQS;

new Queue(this, "MyQueue", new QueueProps
{
    Encryption = QueueEncryption.KMS_MANAGED
});
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{
  Encryption: sqs.QueueEncryption_KMS_MANAGED,
})
```

有些配置 props 是可选的，而且在许多情况下具有默认值。在某些情况下，所有 props 都是可选的，最后一个参数可以完全省略。

### 资源属性
<a name="resources-attributes"></a>

 AWS 构造库中的大多数资源都公开属性，这些属性在部署时由解析 AWS CloudFormation。特性以属性的形式在资源类上公开，并以类型名称为前缀。以下示例展示了如何使用 `queueUrl`（Python：`queue_url`）属性获取 Amazon SQS 队列的 URL。

**Example**  

```
import * as sqs from '@aws-cdk/aws-sqs';

const queue = new sqs.Queue(this, 'MyQueue');
const url = queue.queueUrl; // => A string representing a deploy-time value
```

```
const sqs = require('@aws-cdk/aws-sqs');

const queue = new sqs.Queue(this, 'MyQueue');
const url = queue.queueUrl; // => A string representing a deploy-time value
```

```
import aws_cdk.aws_sqs as sqs

queue = sqs.Queue(self, "MyQueue")
url = queue.queue_url # => A string representing a deploy-time value
```

```
Queue queue = new Queue(this, "MyQueue");
String url = queue.getQueueUrl();    // => A string representing a deploy-time value
```

```
var queue = new Queue(this, "MyQueue");
var url = queue.QueueUrl; // => A string representing a deploy-time value
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

queue := sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{})
url := queue.QueueUrl() // => A string representing a deploy-time value
```

有关 [AWS CDK 如何将部署时属性编码为字符串的信息，请参阅令牌](tokens.md)和 AWS CDK。

## 引用资源
<a name="resources-referencing"></a>

配置资源时，您通常需要引用其他资源的属性。示例如下：
+ Amazon Elastic Container Service（Amazon ECS）资源需要引用其运行所在的集群。
+ 亚马逊 CloudFront 分发需要引用包含源代码的亚马逊简单存储服务 (Amazon S3) 存储桶。

您可以通过以下任何一种方式引用资源：
+ 通过传递在 CDK 应用程序中定义的资源，无论是在同一堆栈还是在不同的堆栈中均可
+ 通过传递代理对象，该代理对象引用您的 AWS 账户中定义的资源，该资源是根据资源的唯一标识符（例如 ARN）创建的

如果某一构造的属性表示另一种资源的构造，则其类型就是该构造的接口类型。例如，Amazon ECS 构造采用了类型 `ecs.ICluster` 的属性 `cluster`。另一个例子是采用以下类型的属性 `sourceBucket` (Python:`source_bucket`) 的 CloudFront 分布结构`s3.IBucket`。

您可以直接传递在同一 AWS CDK 应用程序中定义的适当类型的任何资源对象。以下示例定义了一个 Amazon ECS 集群，然后使用该集群来定义 Amazon ECS 服务。

**Example**  

```
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ });

const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
```

```
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ });

const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
```

```
cluster = ecs.Cluster(self, "Cluster")

service = ecs.Ec2Service(self, "Service", cluster=cluster)
```

```
Cluster cluster = new Cluster(this, "Cluster");
Ec2Service service = new Ec2Service(this, "Service",
        new Ec2ServiceProps.Builder().cluster(cluster).build());
```

```
var cluster = new Cluster(this, "Cluster");
var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster });
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  ecs "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

cluster := ecs.NewCluster(stack, jsii.String("MyCluster"), &ecs.ClusterProps{})
service := ecs.NewEc2Service(stack, jsii.String("MyService"), &ecs.Ec2ServiceProps{
  Cluster: cluster,
})
```

### 引用其他堆栈中的资源
<a name="resource-stack"></a>

您可以引用不同堆栈中的资源，前提是这些资源是在同一个应用程序中定义的，并且处于相同的 AWS 环境中。通常使用以下模式：
+ 将对构造的引用存储为生成资源的堆栈属性。（要获取对当前构造堆栈的引用，请使用 `Stack.of(this)`。）
+ 将此引用传递给堆栈的构造函数，该构造函数将资源作为参数或属性使用。然后，使用堆栈将其作为属性传递给任何需要它的构造。

以下示例定义了堆栈 `stack1`。此堆栈定义了 Amazon S3 存储桶，并将对存储桶构造的引用存储为堆栈的属性。然后，该应用程序定义了第二个堆栈`stack2`，该堆栈在实例化时接受一个存储桶。 `stack2`例如，可以定义一个使用存储桶进行数据存储的 AWS Glue 表。

**Example**  

```
const prod = { account: '123456789012', region: 'us-east-1' };

const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod });

// stack2 will take a property { bucket: IBucket }
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});
```

```
const prod = { account: '123456789012', region: 'us-east-1' };

const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod });

// stack2 will take a property { bucket: IBucket }
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});
```

```
prod = core.Environment(account="123456789012", region="us-east-1")

stack1 = StackThatProvidesABucket(app, "Stack1", env=prod)

# stack2 will take a property "bucket"
stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod)
```

```
// Helper method to build an environment
static Environment makeEnv(String account, String region) {
    return Environment.builder().account(account).region(region)
            .build();
}

App app = new App();

Environment prod = makeEnv("123456789012", "us-east-1");

StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1",
        StackProps.builder().env(prod).build());

// stack2 will take an argument "bucket"
StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,",
        StackProps.builder().env(prod).build(), stack1.bucket);
```

```
Amazon.CDK.Environment makeEnv(string account, string region)
{
    return new Amazon.CDK.Environment { Account = account, Region = region };
}

var prod = makeEnv(account: "123456789012", region: "us-east-1");

var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod });

// stack2 will take a property "bucket"
var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod,
    bucket = stack1.Bucket});
```

如果 AWS CDK 确定资源位于同一个环境中，但位于不同的堆栈中，则它会自动合成生成堆栈和使用堆栈[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)中的 AWS CloudFormation [导出](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)，将该信息从一个堆栈传输到另一个堆栈。

#### 解决依赖死锁
<a name="resources-deadlock"></a>

从一个堆栈引用另一个堆栈的资源会在两个堆栈之间建立依赖关系。这样可以确保堆栈按正确的顺序进行部署。部署堆栈后，这种依赖关系就具体化了。之后，从使用堆栈中删除对共享资源的使用可能会意外导致部署失败。如果两个堆栈之间存在另一种依赖关系，但迫使它们按相同的顺序进行部署，就会发生这种情况。如果只是由 CDK Toolkit 选择首先部署生成堆栈，那么在没有依赖关系时也可能发生这种情况。由于不再需要 AWS CloudFormation 导出，因此已将其从生成堆栈中删除，但是由于尚未部署更新，导出的资源仍在使用堆栈中使用。因此，生产者堆栈会部署失败。

要打破这种死锁，请从使用堆栈中删除对共享资源的使用。（这将从生成堆栈中删除自动导出。） 接下来，使用与自动生成的导出完全相同的逻辑 ID，手动将相同的导出添加到生成堆栈中。删除使用堆栈中共享资源的使用，然后部署两个堆栈。然后删除手动导出（以及不再需要的共享资源），并再次部署两个堆栈。堆栈的 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options) 方法是一种为此目的创建手动导出的便捷方法。（请参阅链接方法参考中的示例。）

### 引用您 AWS 账户中的资源
<a name="resources-external"></a>

假设您想在 AWS CDK 应用程序中使用 AWS 账户中已有的资源。这可能是通过控制台、 AWS SDK、直接使用 AWS CloudFormation或在其他 AWS CDK 应用程序中定义的资源。您可以将资源的 ARN（或其他标识属性或属性组）转换为代理对象。代理对象通过调用资源类上的静态工厂方法来用作对资源的引用。

当您创建这样的代理时，外部资源**不会**成为您的 AWS CDK 应用程序的一部分。因此，您在 AWS CDK 应用程序中对代理所做的更改不会影响已部署的资源。但是，可以将代理传递给需要该类型资源的任何 AWS CDK 方法。

以下示例展示了如何基于具有 ARN `arn:aws:s3:::amzn-s3-demo-bucket1` 的现有存储桶来引用存储桶，以及如何基于具有特定 ID 的现有 VPC 来引用 Amazon Virtual Private Cloud。

**Example**  

```
// Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1');

// Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1');

// Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.fromVpcAttributes(this, 'MyVpc', {
  vpcId: 'vpc-1234567890abcde',
});
```

```
// Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1');

// Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1');

// Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.fromVpcAttributes(this, 'MyVpc', {
  vpcId: 'vpc-1234567890abcde'
});
```

```
# Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.from_bucket_name(self, "MyBucket", "amzn-s3-demo-bucket1")

# Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1")

# Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef")
```

```
// Construct a proxy for a bucket by its name (must be same account)
Bucket.fromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1");

// Construct a proxy for a bucket by its full ARN (can be another account)
Bucket.fromBucketArn(this, "MyBucket",
        "arn:aws:s3:::amzn-s3-demo-bucket1");

// Construct a proxy for an existing VPC from its attribute(s)
Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder()
        .vpcId("vpc-1234567890abcdef").build());
```

```
// Construct a proxy for a bucket by its name (must be same account)
Bucket.FromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1");

// Construct a proxy for a bucket by its full ARN (can be another account)
Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1");

// Construct a proxy for an existing VPC from its attribute(s)
Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes
{
    VpcId = "vpc-1234567890abcdef"
});
```

```
// Define a proxy for a bucket by its name (must be same account)
s3.Bucket_FromBucketName(stack, jsii.String("MyBucket"), jsii.String("amzn-s3-demo-bucket1"))

// Define a proxy for a bucket by its full ARN (can be another account)
s3.Bucket_FromBucketArn(stack, jsii.String("MyBucket"), jsii.String("arn:aws:s3:::amzn-s3-demo-bucket1"))

// Define a proxy for an existing VPC from its attributes
ec2.Vpc_FromVpcAttributes(stack, jsii.String("MyVpc"), &ec2.VpcAttributes{
  VpcId: jsii.String("vpc-1234567890abcde"),
})
```

让我们来详细了解一下 [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options) 方法。由于 `ec2.Vpc` 构造很复杂，您可以通过多种方式选择要与 CDK 应用程序一起使用的 VPC。为了解决这个问题，VPC 结构有一个`fromLookup`静态方法 (Python:`from_lookup`)，允许您在综合时通过查询您的 AWS 账户来查找所需的 Amazon VPC。

要使用 `Vpc.fromLookup()`，合成堆栈的系统必须有权访问拥有 Amazon VPC 的账户。这是因为 CDK Toolkit 会在合成时查询账户以找到正确的 Amazon VPC。

此外，仅`Vpc.fromLookup()`适用于使用明确的**账户**和**区域**定义的堆栈（参见 [AWS CDK 的环境](environments.md)）。如果 AWS CDK 尝试从与[环境无关的堆栈](stacks.md#stack-api)中查找 Amazon VPC，则 CDK 工具包不知道要查询哪个环境才能找到该 VPC。

您必须提供足以唯一标识您 AWS 账户中的 VPC 的`Vpc.fromLookup()`属性。例如，只能有一个默认 VPC，因此将该 VPC 指定为默认 VPC 就足够了。

**Example**  

```
ec2.Vpc.fromLookup(this, 'DefaultVpc', {
  isDefault: true
});
```

```
ec2.Vpc.fromLookup(this, 'DefaultVpc', {
  isDefault: true
});
```

```
ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True)
```

```
Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder()
        .isDefault(true).build());
```

```
Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true });
```

```
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{
  IsDefault: jsii.Bool(true),
})
```

您也可以使用该`tags`属性 VPCs 按标签进行查询。在创建 Amazon VPC 时，您可以使用 AWS CloudFormation 或 AWS CDK 向其添加标签。创建标签后，您可以随时使用 AWS 管理控制台、 AWS CLI 或 S AWS DK 编辑标签。除了您自己添加的任何标签外， AWS CDK 还会自动在其创建的所有 VPCs 标签中添加以下标签。
+  **名称**：VPC 的名称。
+  **aws-cdk:subnet-name**：子网的名称。
+  **aws-cdk:subnet-type**：子网类型：公有子网、私有子网或隔离子网。

**Example**  

```
ec2.Vpc.fromLookup(this, 'PublicVpc',
    {tags: {'aws-cdk:subnet-type': "Public"}});
```

```
ec2.Vpc.fromLookup(this, 'PublicVpc',
    {tags: {'aws-cdk:subnet-type': "Public"}});
```

```
ec2.Vpc.from_lookup(self, "PublicVpc",
    tags={"aws-cdk:subnet-type": "Public"})
```

```
Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder()
        .tags(java.util.Map.of("aws-cdk:subnet-type", "Public"))  // Java 9 or later
        .build());
```

```
Vpc.FromLookup(this, id: "PublicVpc", new VpcLookupOptions
{
    Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" }
});
```

```
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{
  Tags: &map[string]*string{"aws-cdk:subnet-type": jsii.String("Public")},
})
```

`Vpc.fromLookup()` 的结果缓存在项目的 `cdk.context.json` 文件中。（请参阅[上下文值和 AWS CDK。）](context.md) 将此文件提交到版本控制，这样您的应用程序就可以继续引用同一 Amazon VPC。即使您稍后更改了您的属性，从而导致选择 VPCs 了不同的 VPC，这也仍然有效。如果您在无法访问定义VPC的 AWS 账户（例如 [CDK](cdk-pipeline.md) Pipelines）的环境中部署堆栈，这一点尤其重要。

尽管你可以在任何地方使用在 AWS CDK 应用程序中定义的类似资源的地方使用外部资源，但你无法对其进行修改。例如，在外部 `s3.Bucket` 上调用 `addToResourcePolicy`（Python：`add_to_resource_policy`）不会执行任何操作。

## 资源物理名称
<a name="resources-physical-names"></a>

中 AWS CloudFormation 资源的逻辑名称与部署后在 AWS 管理控制台中显示的资源名称不同 AWS CloudFormation。 AWS CDK 称这些姓氏为*物理名称*。

例如， AWS CloudFormation 可能使用逻辑 ID `Stack2MyBucket4DD88B4F` 和物理名称创建 Amazon S3 存储桶`stack2MyBucket4dd88b4f-iuv1rbv9z3to`。

在创建表示资源的构造时，您可以使用属性 `<resourceType>Name` 来指定物理名称。以下示例创建了物理名称为 `amzn-s3-demo-bucket` 的 Amazon S3 存储桶。

**Example**  

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: 'amzn-s3-demo-bucket',
});
```

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: 'amzn-s3-demo-bucket'
});
```

```
bucket = s3.Bucket(self, "MyBucket", bucket_name="amzn-s3-demo-bucket")
```

```
Bucket bucket = Bucket.Builder.create(this, "MyBucket")
        .bucketName("amzn-s3-demo-bucket").build();
```

```
var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "amzn-s3-demo-bucket" });
```

```
bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{
  BucketName: jsii.String("amzn-s3-demo-bucket"),
})
```

为资源分配物理名称有一些缺点 AWS CloudFormation。最重要的是，如果资源已分配了物理名称，则对需要替换资源的已部署资源进行任何更改（例如更改创建后不可变的资源属性）都将失败。如果您最终处于这种状态，唯一的解决方案是删除 AWS CloudFormation 堆栈，然后再次部署 AWS CDK 应用程序。有关详细信息，请参阅 [AWS CloudFormation 文档](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html)。

在某些情况下，例如在创建具有跨环境引用的 AWS CDK 应用程序时，需要物理名称才能让 AWS CDK 正常运行。在这种情况下，如果你不想费心自己想出一个真实的名字，你可以让 AWS CDK 为你命名。为此，请使用特殊值 `PhysicalName.GENERATE_IF_NEEDED`，如下所示。

**Example**  

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: core.PhysicalName.GENERATE_IF_NEEDED,
});
```

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: core.PhysicalName.GENERATE_IF_NEEDED
});
```

```
bucket = s3.Bucket(self, "MyBucket",
                         bucket_name=core.PhysicalName.GENERATE_IF_NEEDED)
```

```
Bucket bucket = Bucket.Builder.create(this, "MyBucket")
        .bucketName(PhysicalName.GENERATE_IF_NEEDED).build();
```

```
var bucket = new Bucket(this, "MyBucket", new BucketProps
    { BucketName = PhysicalName.GENERATE_IF_NEEDED });
```

```
bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{
  BucketName: awscdk.PhysicalName_GENERATE_IF_NEEDED(),
})
```

## 传递唯一资源标识符
<a name="resources-identifiers"></a>

应尽可能通过引用来传递资源，如上节中所述。但是，在某些情况下，您别无选择，只能通过资源的某个属性来引用该资源。以下是使用案例示例：
+ 当你使用低级 AWS CloudFormation 资源时。
+ 当您需要向 AWS CDK 应用程序的运行时组件公开资源时，例如通过环境变量引用 Lambda 函数时。

这些标识符可用作资源的属性，如下所示。

**Example**  

```
bucket.bucketName
lambdaFunc.functionArn
securityGroup.groupArn
```

```
bucket.bucketName
lambdaFunc.functionArn
securityGroup.groupArn
```

```
bucket.bucket_name
lambda_func.function_arn
security_group_arn
```
Java AWS CDK 绑定使用获取器方法作为属性。  

```
bucket.getBucketName()
lambdaFunc.getFunctionArn()
securityGroup.getGroupArn()
```

```
bucket.BucketName
lambdaFunc.FunctionArn
securityGroup.GroupArn
```

```
bucket.BucketName()
fn.FunctionArn()
```

以下示例说明如何将生成的存储桶名称传递给 AWS Lambda 函数。

**Example**  

```
const bucket = new s3.Bucket(this, 'Bucket');

new lambda.Function(this, 'MyLambda', {
  // ...
  environment: {
    BUCKET_NAME: bucket.bucketName,
  },
});
```

```
const bucket = new s3.Bucket(this, 'Bucket');

new lambda.Function(this, 'MyLambda', {
  // ...
  environment: {
    BUCKET_NAME: bucket.bucketName
  }
});
```

```
bucket = s3.Bucket(self, "Bucket")

lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name))
```

```
final Bucket bucket = new Bucket(this, "Bucket");

Function.Builder.create(this, "MyLambda")
        .environment(java.util.Map.of(    // Java 9 or later
                "BUCKET_NAME", bucket.getBucketName()))
        .build();
```

```
var bucket = new Bucket(this, "Bucket");

new Function(this, "MyLambda", new FunctionProps
{
    Environment = new Dictionary<string, string>
    {
        ["BUCKET_NAME"] = bucket.BucketName
    }
});
```

```
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{
  Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()},
})
```

## 在资源之间授予权限
<a name="resources-grants"></a>

更高级别的结构通过提供简单的、基于意图 APIs 的表达权限要求来实现最低权限权限。例如，许多结构都提供了授权方法，您可以使用这些方法向实体（例如 IAM 角色或用户）授予使用资源的权限，而无需手动创建 IAM 权限声明。

授权方法可通过授权类获得（`BucketGrants`例如 Amazon S3 存储桶）。这些类同时适用于 L1 和 L2 结构。为了方便起见，L2 构造公开了一个`grants`属性，但你也可以直接从 L1 构造中创建 Grants 类。你可以将 Grants 类与 [Mixins](mixins.md) 结合使用，在 L1 构造上获得类似 L2 的便利。

以下示例创建了权限以允许 Lambda 函数的执行角色读取对象并将其写入特定 Amazon S3 存储桶。如果使用 AWS KMS 密钥对 Amazon S3 存储桶进行加密，则此方法还会向 Lambda 函数的执行角色授予使用该密钥进行解密的权限。

**Example**  

```
if (bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if ( bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if bucket.grants.read_write(func).success:
    # ...
```

```
if (bucket.getGrants().readWrite(func).getSuccess()) {
    // ...
}
```

```
if (bucket.Grants.ReadWrite(func).Success)
{
    // ...
}
```

```
if *bucket.Grants().ReadWrite(function, nil).Success() {
  // ...
}
```

授权方法会返回一个 `iam.Grant` 对象。使用 `Grant` 对象的 `success` 属性来确定是否有效应用了授权（例如，其可能尚未应用于[外部资源](#resources-referencing)）。您也可以使用 `Grant` 对象的 `assertSuccess`（Python：`assert_success`）方法来强制执行授权已成功应用。

如果特定的使用案例没有可用的特定授权方法，则可以使用通用的授权方法，通过指定的操作列表来定义新的授权。

以下示例显示了如何授予 Lambda 函数对 Amazon DynamoDB `CreateBackup` 操作的访问权限。

**Example**  

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, "dynamodb:CreateBackup")
```

```
table.getGrants().actions(func, "dynamodb:CreateBackup");
```

```
table.Grants.Actions(func, "dynamodb:CreateBackup");
```

```
table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{})
table.Grants().Actions(function, jsii.String("dynamodb:CreateBackup"))
```

许多资源（例如 Lambda 函数）都需要在执行代码时承担角色。配置属性让您能够指定 `iam.IRole`。如果未指定角色，则该函数会自动创建一个专门用于此用途的角色。然后您可以对资源使用授权方法，以向该角色添加语句。

授予方法是使用较低级别构建的， APIs 用于处理 IAM 策略。策略被建模为[PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html)对象。使用 `addToRolePolicy` 方法（Python：`add_to_role_policy`）将语句直接添加到角色（或构造的附加角色），或者使用 `addToResourcePolicy`（Python：`add_to_resource_policy`）方法将语句添加到资源的策略（例如 `Bucket` 策略）中。

## 资源指标和警报
<a name="resources-metrics"></a>

许多资源会发出可用于设置监控仪表板和警报的 CloudWatch 指标。更高级别的构造具备指标方法，允许您访问指标而无需查找要使用的正确名称。

以下示例显示了如何定义当 Amazon SQS 队列的 `ApproximateNumberOfMessagesNotVisible` 超过 100 时的警报。

**Example**  

```
import * as cw from '@aws-cdk/aws-cloudwatch';
import * as sqs from '@aws-cdk/aws-sqs';
import { Duration } from '@aws-cdk/core';

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5),
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100,
  // ...
});
```

```
const cw = require('@aws-cdk/aws-cloudwatch');
const sqs = require('@aws-cdk/aws-sqs');
const { Duration } = require('@aws-cdk/core');

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5)
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100
  // ...
});
```

```
import aws_cdk.aws_cloudwatch as cw
import aws_cdk.aws_sqs as sqs
from aws_cdk.core import Duration

queue = sqs.Queue(self, "MyQueue")
metric = queue.metric_approximate_number_of_messages_not_visible(
    label="Messages Visible (Approx)",
    period=Duration.minutes(5),
    # ...
)
metric.create_alarm(self, "TooManyMessagesAlarm",
    comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    threshold=100,
    # ...
)
```

```
import software.amazon.awscdk.core.Duration;
import software.amazon.awscdk.services.sqs.Queue;
import software.amazon.awscdk.services.cloudwatch.Metric;
import software.amazon.awscdk.services.cloudwatch.MetricOptions;
import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions;
import software.amazon.awscdk.services.cloudwatch.ComparisonOperator;

Queue queue = new Queue(this, "MyQueue");

Metric metric = queue
        .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder()
                .label("Messages Visible (Approx)")
                .period(Duration.minutes(5)).build());

metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder()
                .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD)
                .threshold(100)
                // ...
                .build());
```

```
using cdk = Amazon.CDK;
using cw = Amazon.CDK.AWS.CloudWatch;
using sqs = Amazon.CDK.AWS.SQS;

var queue = new sqs.Queue(this, "MyQueue");
var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions
{
    Label = "Messages Visible (Approx)",
    Period = cdk.Duration.Minutes(5),
    // ...
});
metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions
{
    ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    Threshold = 100,
    // ..
});
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  cw "github.com/aws/aws-cdk-go/awscdk/v2/awscloudwatch"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{})
metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{
  Label: jsii.String("Messages Visible (Approx)"),
  Period: awscdk.Duration_Minutes(jsii.Number(5)),
})

metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{
  ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD,
  Threshold: jsii.Number(100),
})
```

如果没有针对特定指标的方法，则可以使用通用指标方法来手动指定指标名称。

也可以将指标添加到 CloudWatch 仪表板中。请参阅[CloudWatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html)。

## 网络流量
<a name="resources-traffic"></a>

在许多情况下，您必须启用网络权限才能使应用程序正常运行，例如当计算基础设施需要访问持久层时。建立或侦听连接的资源会暴露支持流量的方法，包括设置安全组规则或网络 ACLs。

 [IConnectable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html)资源有一个`connections`属性，即网络流量规则配置的网关。

您可以使用 `allow` 方法让数据能够在给定的网络路径上流动。以下示例启用了与 Web 的 HTTPS 连接以及来自 Amazon EC2 Auto Scaling 组 `fleet2` 的传入连接。

**Example**  

```
import * as asg from '@aws-cdk/aws-autoscaling';
import * as ec2 from '@aws-cdk/aws-ec2';

const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
const asg = require('@aws-cdk/aws-autoscaling');
const ec2 = require('@aws-cdk/aws-ec2');

const fleet1 = asg.AutoScalingGroup();

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2 = asg.AutoScalingGroup();
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import aws_cdk.aws_autoscaling as asg
import aws_cdk.aws_ec2 as ec2

fleet1 = asg.AutoScalingGroup( ... )

# Allow surfing the (secure) web
fleet1.connections.allow_to(ec2.Peer.any_ipv4(),
  ec2.Port(PortProps(from_port=443, to_port=443)))

fleet2 = asg.AutoScalingGroup( ... )
fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic())
```

```
import software.amazon.awscdk.services.autoscaling.AutoScalingGroup;
import software.amazon.awscdk.services.ec2.Peer;
import software.amazon.awscdk.services.ec2.Port;

AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet")
        /* ... */.build();

// Allow surfing the (secure) Web
fleet1.getConnections().allowTo(Peer.anyIpv4(),
        Port.Builder.create().fromPort(443).toPort(443).build());

AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2")
        /* ... */.build();
fleet1.getConnections().allowFrom(fleet2, Port.allTraffic());
```

```
using cdk = Amazon.CDK;
using asg = Amazon.CDK.AWS.AutoScaling;
using ec2 = Amazon.CDK.AWS.EC2;

// Allow surfing the (secure) Web
var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps
  { FromPort = 443, ToPort = 443 }));

var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling"
  ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2"
)

fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web"))

fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic"))
```

某些资源具有与之关联的默认端口。示例包括公有端口上负载均衡器的侦听器，以及数据库引擎接受 Amazon RDS 数据库实例连接的端口。在这种情况下，您可以实施严格的网络控制，而无需手动指定端口。为此，请使用 `allowDefaultPortFrom` 和 `allowToDefaultPort` 方法（Python：`allow_default_port_from`、`allow_to_default_port`）。

以下示例说明如何启用来自任意 IPV4 地址的连接，以及如何启用来自 Auto Scaling 组的连接以访问数据库。

**Example**  

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allow_default_port_from_any_ipv4("Allow public access")

fleet.connections.allow_to_default_port(rds_database, "Fleet can access database")
```

```
listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access");

fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access");

fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access"))
fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database"))
```

## 事件处理
<a name="resources-events"></a>

有些资源可以充当事件源。使用 `addEventNotification` 方法（Python：`add_event_notification`）将事件目标注册到资源发出的特定事件类型。除此之外，`addXxxNotification` 方法还提供了一种简单的方式来注册常见事件类型的处理程序。

以下示例显示了如何在将对象添加到 Amazon S3 存储桶时触发 Lambda 函数。

**Example**  

```
import * as s3nots from '@aws-cdk/aws-s3-notifications';

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
const s3nots = require('@aws-cdk/aws-s3-notifications');

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
import aws_cdk.aws_s3_notifications as s3_nots

handler = lambda_.Function(self, "Handler", ...)
bucket = s3.Bucket(self, "Bucket")
bucket.add_object_created_notification(s3_nots.LambdaDestination(handler))
```

```
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.s3.notifications.LambdaDestination;

Function handler = Function.Builder.create(this, "Handler")/* ... */.build();
Bucket bucket = new Bucket(this, "Bucket");
bucket.addObjectCreatedNotification(new LambdaDestination(handler));
```

```
using lambda = Amazon.CDK.AWS.Lambda;
using s3 = Amazon.CDK.AWS.S3;
using s3Nots = Amazon.CDK.AWS.S3.Notifications;

var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. });
var bucket = new s3.Bucket(this, "Bucket");
bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler));
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
  s3nots "github.com/aws/aws-cdk-go/awscdk/v2/awss3notifications"
)

handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{})
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil)
```

## 删除策略
<a name="resources-removal"></a>

维护持久性数据的资源（例如数据库、Amazon S3 存储桶和 Amazon ECR 注册表）都具有*删除策略*。移除策略指示在包含永久对象的 AWS CDK 堆栈被销毁时是否将其删除。指定删除策略的值可通过 AWS CDK `core` 模块中的`RemovalPolicy`枚举获得。

**注意**  
除了持久存储数据的资源之外，其他资源还可能具有用于其他目的的 `removalPolicy`。例如，Lambda 函数版本使用 `removalPolicy` 属性来确定是否在部署新版本时保留给定版本。与 Amazon S3 存储桶或 DynamoDB 表上的删除策略相比，这些策略具有不同的含义和默认值。


| 值 | 含义 | 
| --- | --- | 
|   `RemovalPolicy.RETAIN`   |  销毁堆栈时保留资源内容（默认）。该资源在堆栈中处于孤立状态，必须手动删除。如果您在资源仍然存在的情况下尝试重新部署堆栈，则您会因名称冲突而收到错误消息。  | 
|   `RemovalPolicy.DESTROY`   |  该资源将随堆栈一起被销毁。  | 

 AWS CloudFormation 不会移除包含文件的 Amazon S3 存储桶，即使其删除策略设置为。`DESTROY`尝试这样做是 AWS CloudFormation 错误的。要让 AWS CDK 在销毁存储桶之前从存储桶中删除所有文件，请将存储桶的`autoDeleteObjects`属性设置为。`true`

以下是创建 Amazon S3 存储桶的示例，其中 `RemovalPolicy` 为 `DESTROY` 且 `autoDeleteOjbects` 设置为 `true`。

**Example**  

```
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';

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

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}
```

```
const cdk = require('@aws-cdk/core');
const s3 = require('@aws-cdk/aws-s3');

class CdkTestStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}

module.exports = { CdkTestStack }
```

```
import aws_cdk.core as cdk
import aws_cdk.aws_s3 as s3

class CdkTestStack(cdk.stack):
    def __init__(self, scope: cdk.Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        bucket = s3.Bucket(self, "Bucket",
            removal_policy=cdk.RemovalPolicy.DESTROY,
            auto_delete_objects=True)
```

```
software.amazon.awscdk.core.*;
import software.amazon.awscdk.services.s3.*;

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

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

        Bucket.Builder.create(this, "Bucket")
                .removalPolicy(RemovalPolicy.DESTROY)
                .autoDeleteObjects(true).build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
{
    new Bucket(this, "Bucket", new BucketProps {
        RemovalPolicy = RemovalPolicy.DESTROY,
        AutoDeleteObjects = true
    });
}
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
)

s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{
  RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
  AutoDeleteObjects: jsii.Bool(true),
})
```

您也可以通过`applyRemovalPolicy()`方法将移除策略直接应用于底层 AWS CloudFormation 资源。此方法适用于某些在其 L2 资源的 props 中没有 `removalPolicy` 属性的有状态资源。示例包括：
+  AWS CloudFormation 堆栈
+ Amazon Cognito 用户群体
+ Amazon DocumentDB 数据库实例
+ Amazon EC2 卷
+ 亚马逊 OpenSearch 服务域名
+ Amazon FSx 文件系统
+ Amazon SQS 队列

**Example**  

```
const resource = bucket.node.findChild('Resource') as cdk.CfnResource;
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
const resource = bucket.node.findChild('Resource');
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
resource = bucket.node.find_child('Resource')
resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY);
```

```
CfnResource resource = (CfnResource)bucket.node.findChild("Resource");
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
var resource = (CfnResource)bucket.node.findChild('Resource');
resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

**注意**  
 AWS CDK 的`RemovalPolicy`意思是's。 AWS CloudFormation `DeletionPolicy`但是， AWS CDK 中的默认设置是保留数据，这与 AWS CloudFormation 默认设置相反。