

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

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

# 标签和 AWS CDK
<a name="tagging"></a>

标签是信息性键-值元素，可将其添加到 AWS CDK 应用程序的构造中。应用于给定构造的标签也可应用于其所有可标记的子构造。标签包含在从应用程序合成的 AWS CloudFormation 模板中，并应用于其部署的 AWS 资源。您可以使用标签对资源进行标识和分类，以实现以下目的：
+ 简化管理
+ 成本分配
+ 访问控制
+ 您设计的任何其他目的

**提示**  
有关如何对 AWS 资源使用标签的更多信息，请参阅《AWS 白皮书》**中的 [Best Practices for Tagging AWS Resources](https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html)。

## 使用标签
<a name="tagging-use"></a>

[标签](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html)类包括静态方法 `of()`，通过该方法可以向指定构造添加标签或从中删除标签。
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props) 可将新标签应用于给定构造及其所有子构造。
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props) 可从给定构造及其任何子构造中删除标签，包括子构造可能已应用于自身的标签。

**注意**  
标记是使用[方面和 AWS CDK](aspects.md) 实现的。“方面”是一种将操作（例如标记）应用于给定范围内所有构造的方法。

以下示例将值为 **value** 的标签 **key** 应用于构造。

**Example**  

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(my_construct).add("key", "value")
```

```
Tags.of(myConstruct).add("key", "value");
```

```
Tags.Of(myConstruct).Add("key", "value");
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{})
```

以下示例从构造中删除了标签 **key**。

**Example**  

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(my_construct).remove("key")
```

```
Tags.of(myConstruct).remove("key");
```

```
Tags.Of(myConstruct).Remove("key");
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("key"), &awscdk.TagProps{})
```

如果您使用的是 `Stage` 构造，请在 `Stage` 级别或更低级别应用标签。标签不能跨 `Stage` 边界应用。

## 标签优先级
<a name="tagging-priorities"></a>

AWS CDK 以递归方式应用和删除标签。如果存在冲突，则先进行优先级最高的标记操作。（使用可选 `priority` 属性设置优先级。） 如果两个操作的优先级相同，则先进行最靠近构造树底部的标记操作。默认情况下，应用优先级为 100 的标签（直接添加到 AWS CloudFormation 资源的标签除外，其优先级为 50）。删除标签的默认优先级为 200。

以下示例将优先级为 300 的标签应用于构造。

**Example**  

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(my_construct).add("key", "value", priority=300)
```

```
Tags.of(myConstruct).add("key", "value", TagProps.builder()
        .priority(300).build());
```

```
Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 });
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{
  Priority: jsii.Number(300),
})
```

## 可选属性
<a name="tagging-props"></a>

标签支持 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html)，可微调标签应用到资源或从资源中删除的方式。所有其他属性均为可选。

 `applyToLaunchedInstances`（Python：`apply_to_launched_instances`）  
仅适用于 add()。默认情况下，标签应用于在自动扩缩组中启动的实例。将此属性设置为 **false** 可忽略在自动扩缩组中启动的实例。

 `includeResourceTypes`/`excludeResourceTypes`（Python：`include_resource_types`/`exclude_resource_types`）  
根据 AWS CloudFormation 资源类型，使用这些属性仅在资源的子集上操作标签。默认情况下，该操作将应用于构造子树中的所有资源，但可以通过包含或排除某些资源类型来更改此操作。如果同时指定了两者，则排除将优先于包含。

 `priority`   
使用此属性来设置此操作相对于其他 `Tags.add()` 和 `Tags.remove()` 操作的优先级。较高值优先于较低值。添加操作的默认值为 100（直接应用于 AWS CloudFormation 资源的标签为 50），删除操作的默认值为 200。

以下示例将值为 **value** 且优先级为 **100** 的标签 **tagname** 应用于构造中** AWS::Xxx::Yyy** 类型的资源。它不会将标签应用于在 Amazon EC2 Auto Scaling 组中启动的实例或** AWS::Xxx::Zzz** 类型的资源。（这些是两种任意但不同 AWS CloudFormation 资源类型的占位符。）

**Example**  

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100,
});
```

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100
});
```

```
Tags.of(my_construct).add("tagname", "value",
    apply_to_launched_instances=False,
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=100)
```

```
Tags.of(myConstruct).add("tagname", "value", TagProps.builder()
                .applyToLaunchedInstances(false)
                .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
                .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
                .priority(100).build());
```

```
Tags.Of(myConstruct).Add("tagname", "value", new TagProps
{
    ApplyToLaunchedInstances = false,
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("tagname"), jsii.String("value"), &awscdk.TagProps{
  ApplyToLaunchedInstances: jsii.Bool(false),
  IncludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:                 jsii.Number(100),
})
```

以下示例从构造中** AWS::Xxx::Yyy** 类型的资源中删除优先级为 **200** 的标签 **tagname**，而非从** AWS::Xxx::Zzz**类型的资源中进行删除。

**Example**  

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200,
});
```

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200
});
```

```
Tags.of(my_construct).remove("tagname",
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=200,)
```

```
Tags.of((myConstruct).remove("tagname", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
        .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
        .priority(100).build());
        )
```

```
Tags.Of(myConstruct).Remove("tagname", new TagProps
{
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("tagname"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:             jsii.Number(200),
})
```

## 示例
<a name="tagging-example"></a>

以下示例将值为 **TheBest** 的标签键 **StackType** 添加到名为 `MarketingSystem` 的 `Stack` 中创建的任何资源。然后，它会再次从除 Amazon EC2 VPC 子网之外的所有资源中将其删除。结果是只有子网应用了标签。

**Example**  

```
import { App, Stack, Tags } from 'aws-cdk-lib';

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

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

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

```
from aws_cdk import App, Stack, Tags

app = App();
the_best_stack = Stack(app, 'MarketingSystem')

# Add a tag to all constructs in the stack
Tags.of(the_best_stack).add("StackType", "TheBest")

# Remove the tag from all resources except subnet resources
Tags.of(the_best_stack).remove("StackType",
    exclude_resource_types=["AWS::EC2::Subnet"])
```

```
import software.amazon.awscdk.App;
import software.amazon.awscdk.Tags;

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove("StackType", TagProps.builder()
        .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
using Amazon.CDK;

var app = new App();
var theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.Of(theBestStack).Add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.Of(theBestStack).Remove("StackType", new TagProps
{
    ExcludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
import "github.com/aws/aws-cdk-go/awscdk/v2"
app := awscdk.NewApp(nil)
theBestStack := awscdk.NewStack(app, jsii.String("MarketingSystem"), &awscdk.StackProps{})

// Add a tag to all constructs in the stack
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{})

// Remove the tag from all resources except subnet resources
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

以下代码实现了同样的结果。考虑哪种方法（包含或排除）更能实现您的意图。

**Example**  

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(the_best_stack).add("StackType", "TheBest",
    include_resource_types=["AWS::EC2::Subnet"])
```

```
Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps {
    IncludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

## 标记单个构造
<a name="tagging-single"></a>

 `Tags.of(scope).add(key, value)` 是向 AWS CDK 中的构造添加标签的标准方法。其树遍历行为以递归方式标记给定范围内的所有可标记资源，几乎总能满足您的需求。然而，有时您需要标记一个特定的任意构造（或多个构造）。

其中一种情况涉及应用标签，其值派生自被标记的构造的某个属性。标准标记方法以递归方式将相同的键和值应用于范围内所有匹配的资源。但是，此处每个标记构造的值都可能不同。

标签是使用[方面](aspects.md)实现的，CDK 在您使用 `Tags.of(scope)` 指定的范围内为每个构造调用标签的 `visit()` 方法。我们可以直接调用 `Tag.visit()` 将标签应用于单个构造。

**Example**  

```
new cdk.Tag(key, value).visit(scope);
```

```
new cdk.Tag(key, value).visit(scope);
```

```
cdk.Tag(key, value).visit(scope)
```

```
Tag.Builder.create(key, value).build().visit(scope);
```

```
new Tag(key, value).Visit(scope);
```

```
awscdk.NewTag(key, value, &awscdk.TagProps{}).Visit(scope)
```

您可以标记某个范围内的所有构造，但让标签的值派生自每个构造的属性。为此，请编写一个方面并在该方面的 `visit()` 方法中应用标签，如上述示例所示。然后，使用 `Aspects.of(scope).add(aspect)` 将此方面添加到所需的范围。

以下示例将标签应用于包含资源路径的堆栈中的每个资源。

**Example**  

```
class PathTagger implements cdk.IAspect {
  visit(node: IConstruct) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
class PathTagger {
  visit(node) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
@jsii.implements(cdk.IAspect)
class PathTagger:
    def visit(self, node: IConstruct):
        cdk.Tag("aws-cdk-path", node.node.path).visit(node)

stack = MyStack(app)
cdk.Aspects.of(stack).add(PathTagger())
```

```
final class PathTagger implements IAspect {
	public void visit(IConstruct node) {
		Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node);
	}
}

stack stack = new MyStack(app);
Aspects.of(stack).add(new PathTagger());
```

```
public class PathTagger : IAspect
{
    public void Visit(IConstruct node)
    {
        new Tag("aws-cdk-path", node.Node.Path).Visit(node);
    }
}

var stack = new MyStack(app);
Aspects.Of(stack).Add(new PathTagger);
```

**提示**  
`Tag` 类中内置了条件标记的逻辑，包括优先级、资源类型等。在将标签应用于任意资源时，您可以使用这些功能；如果不满足条件，则不会应用该标签。此外，`Tag` 类仅标记可标记的资源，因此在应用标签之前，您无需测试构造是否可标记。