

# 使用自定义资源创建自定义预置逻辑
<a name="template-custom-resources"></a>

自定义资源为您提供了一种将自定义预置逻辑写入 CloudFormation 模板，并让 CloudFormation 在创建、更新（如果更改了自定义资源）或删除堆栈期间运行该逻辑的方式。预置要求涉及无法使用 CloudFormation 的内置资源类型表达的复杂逻辑或工作流程时，这会很有帮助。

例如，您可能需要包含不可作为 CloudFormation 资源类型的资源。您可以使用自定义资源包含这些资源。这样，您仍然可以在一个堆栈中管理所有相关资源。

要在 CloudFormation 模板中定义自定义资源，可以使用 `AWS::CloudFormation::CustomResource` 或 `Custom::{{MyCustomResourceTypeName}}` 资源类型。自定义资源需要一个属性，即服务令牌，它指定 CloudFormation 发送请求的目标，如 Amazon SNS 主题或 Lambda 函数。

以下主题提供有关如何使用自定义资源的信息。

**Topics**
+ [自定义资源的工作原理](#how-custom-resources-work)
+ [响应超时](#response-timeout)
+ [CloudFormation 自定义资源请求和响应参考](crpg-ref.md)
+ [Amazon SNS 支持的自定义资源](template-custom-resources-sns.md)
+ [Lambda 支持的自定义资源](template-custom-resources-lambda.md)

**注意**  
CloudFormation 注册表和自定义资源各有其优点。自定义资源具有以下优点：  
您不需要注册资源。
您无需注册即可将整个资源作为模板的一部分。
支持 `Create`、`Update` 和 `Delete` 操作
基于注册表的资源具有以下优点：  
支持对第三方应用程序资源进行建模、预置和管理
支持 `Create`、`Read`、`Update`、`Delete` 和 `List` (`CRUDL`) 操作
支持对私有和第三方资源类型的偏差检测
与自定义资源不同，基于注册表的资源不需要关联 Amazon SNS 主题或 Lambda 函数即可执行 `CRUDL` 操作。有关更多信息，请参阅 [通过 CloudFormation 注册表管理扩展](registry.md)。

## 自定义资源的工作原理
<a name="how-custom-resources-work"></a>

设置新自定义资源的一般过程包括以下步骤。这些步骤涉及两个角色：拥有该自定义资源的*自定义资源提供者*和创建包含某个自定义资源类型的模板的*模板开发者*。这两个角色可以是同一个人，但如果不是同一个人，自定义资源提供者应该与模板开发者合作。

1. 自定义资源提供者编写的逻辑决定了如何处理来自 CloudFormation 的请求以及如何对自定义资源执行操作。

1. 自定义资源提供者可创建 Amazon SNS 主题或 Lambda 函数，然后 CloudFormation 可向该主题或函数发送请求。该 Amazon SNS 主题或 Lambda 函数必须位于堆栈所在区域。

1. 自定义资源提供者将 Amazon SNS 主题 ARN 或 Lambda 函数 ARN 提供给模板开发者。

1. 模板开发者定义其 CloudFormation 模板中的自定义资源。这包括服务令牌和任何输入数据参数。服务令牌和输入数据的结构由自定义资源提供者定义。服务令牌指定了 Amazon SNS 主题 ARN 或 Lambda 函数 ARN，并且始终为必填项，而输入数据是可选的，具体取决于自定义资源。

现在，每当有人使用模板创建、更新或删除该自定义资源时，CloudFormation 都会向指定的服务令牌发送请求并等待响应，然后才会执行堆栈操作。

以下总结了使用该模板创建堆栈的流程：

1. CloudFormation 向指定的服务令牌发送请求。该请求包含请求类型以及自定义资源用于向其发送请求的预签名 Amazon S3 存储桶 URL 等信息。有关请求中包含的内容的更多信息，请参阅[CloudFormation 自定义资源请求和响应参考](crpg-ref.md)。

   以下示例数据演示了 CloudFormation 在 `Create` 请求中包含的内容：在本示例中，`ResourceProperties` 允许 CloudFormation 创建发送到 Lambda 函数的自定义负载。

   ```
   {
      "RequestType" : "Create",
      "RequestId" : "unique id for this create request",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::TestResource",
      "LogicalResourceId" : "MyTestResource",
      "ResourceProperties" : {
         "Name" : "Value",
         "List" : [ "1", "2", "3" ]
      }
   }
   ```

1. 自定义资源提供商处理 CloudFormation 请求并向预签名 URL 返回 `SUCCESS` 或 `FAILED` 响应。custom resource provider 提供采用 JSON 格式文件的响应并将响应上传到预签名的 S3 URL。有关更多信息，请参阅*《Amazon Simple Storage Service 用户指南》*中的[使用预签名 URL 上传对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html)。

   在响应中，custom resource provider还可以包含template developer可以访问的名称-值对。例如，如果请求成功，响应可以包含输出数据，如果请求失败，可以包含错误消息。有关响应的更多信息，请参阅[CloudFormation 自定义资源请求和响应参考](crpg-ref.md)。
**重要**  
如果名称值对包含敏感信息，应使用 `NoEcho` 字段遮蔽自定义资源的输出。否则，这些值通过显示属性值的 API（例如 `DescribeStackEvents`）可见。  
有关使用 `NoEcho` 遮蔽敏感信息的更多信息，请参阅 [请勿将凭证嵌入您的模板](security-best-practices.md#creds) 最佳实践。

   custom resource provider负责侦听和响应请求。例如，对于 Amazon SNS 通知，自定义资源提供商必须侦听并响应发送到特定主题 ARN 的通知。CloudFormation 在预签名 URL 位置等待并侦听响应。

   以下示例数据说明自定义资源在响应中可以包含的内容：

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique id for this create request",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MyTestResource",
      "PhysicalResourceId" : "TestResource1",
      "Data" : {
         "OutputName1" : "Value1",
         "OutputName2" : "Value2",
      }
   }
   ```

1. 获得 `SUCCESS` 响应后，CloudFormation 继续堆栈操作。如果收到 `FAILED` 响应或未返回任何响应，则操作失败。来自自定义资源的所有输出数据都存储在预签名 URL 位置。模板开发人员可使用 [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) 函数检索该数据。

**注意**  
如果您使用 AWS PrivateLink，则 VPC 中的自定义资源必须能够访问特定于 CloudFormation 的 S3 存储桶。自定义资源必须将响应发送到预签名的 Amazon S3 URL。如果这些资源不能向 Amazon S3 发送响应，则 CloudFormation 将不会收到响应，并且堆栈操作会失败。有关更多信息，请参阅 [使用接口端点 (AWS PrivateLink) 访问 CloudFormation](vpc-interface-endpoints.md)。

## 响应超时
<a name="response-timeout"></a>

自定义资源的默认超时为 3600 秒（1 小时）。如果在此期间内没有收到任何响应，则该堆栈操作将会失败。

您可以根据预期从自定义资源收到响应将需要的时间来调整超时值。例如，在预置将调用某个 Lambda 函数的自定义资源并且预期会在五分钟内收到响应时，您可以在堆栈模板中通过指定 `ServiceTimeout` 属性将超时设置为五分钟。有关更多信息，请参阅 [CloudFormation 自定义资源请求和响应参考](crpg-ref.md)。这样，如果 Lambda 函数出现错误导致其停滞，CloudFormation 将在五分钟后使堆栈操作失败，而不是等待整整一个小时。

但是，请注意不要将超时值设置得过低。为避免意外超时，请确保您的自定义资源有足够的时间来执行必要的操作并返回响应。