我想解决 AWS CloudFormation 中的自定义资源错误。
解决方法
由于 AWS Lambda 函数遇到错误或操作超时,自定义资源操作失败。当自定义资源向 CloudFormation 发送 FAILED 信号时,就会发生此错误。当 CloudFormation 没有在预期的时间范围内收到来自自定义资源的响应时,就会发生超时故障。
要对此类错误进行故障排除,请执行以下操作。
检查 Lambda 的 Amazon CloudWatch 日志
完成以下步骤:
- 打开 CloudFormation 控制台。
- 选择失败的堆栈。
- 选择 Resources(资源)选项卡,查找支持自定义资源的 Lambda 函数的物理 ID。
- 选择 Lambda 函数。
- 选择 Monitor(监控)选项卡。
- 选择 View CloudWatch logs(查看 CloudWatch 日志)以显示 Lambda 函数日志。
CloudFormation 可能在回滚期间删除了 Lambda 函数。但是,日志组可能会保留 CloudWatch 日志。要查找日志,请完成以下步骤:
- 打开 CloudWatch 控制台。
- 在导航菜单中,选择 Log groups(日志组)。
- 在搜索框中,输入以下命令:
/aws/lambda/LambdaFunctionName
**注意:**将 LambdaFunctionName 替换为您的 Lambda 函数的名称。您可以在 CloudFormation 资源中查找您的 Lambda 函数名称,其资源类型标识为 AWS::Lambda::Function。
如果 CloudWatch 找不到日志,则使用禁用回滚选项重新部署堆栈,以便保留已成功预置的资源。如果您使用禁用回滚选项进行重新部署,则 CloudFormation 无法删除已成功创建的资源。
检查失败的 Lambda 函数
如果支持自定义资源的 Lambda 函数失败且存在异常处理逻辑,您可能会收到以下错误消息:
"Received response status [FAILED] from custom resource.Message returned: .....See the details in CloudWatch Log Stream or related to the resource that the custom resource is creating or managing."
要解决此错误,请查看错误消息中的失败原因,然后检查 Lambda 的 CloudWatch 日志。
查看 CloudFormation 未收到响应的原因
如果 CloudFormation 未收到响应,请执行以下操作:
确保在 Lambda 函数中正确实现了 cfn-response 模块,以便向 CloudFormation 发送信号。如果您错误地实现了该模块,或者该模块缺失,则 CloudFormation 将不会收到响应。
确保您的 Lambda 函数的超时值设置得足够长以完成其任务。Lambda 函数超时的最大值为 15 分钟。默认情况下,CloudFormation 最多等待 1 小时才能接收响应,这与 Lambda 超时是分开的。要缩短等待时间,请在自定义资源中配置 ServiceTimeout 属性。
检查 Amazon Simple Storage Service (Amazon S3) 端点访问权限。为了让 CloudFormation 接收信号,自定义资源必须访问预签名的 Amazon S3 URL。如果您在虚拟私有云 (VPC) 中配置了 Lambda 函数,请确保它位于子网中。子网必须通过 NAT 网关路由出站流量才能访问互联网或使用 Amazon S3 VPC 端点。
监控 Lambda 指标是否并行执行。如果您的 Lambda 日志显示超时后发送的信号,请检查您的 Lambda 函数并发。当大量 Lambda 函数在同一 AWS 区域同时运行时,就会发生超时。要减少超时,请为您的 Lambda 函数使用预留并发。
手动将堆栈从 IN_PROGRESS 状态中移除。如果 CloudFormation 自定义资源一直保持 *_IN_PROGRESS 状态,直到自定义资源达到其超时时间,那么 CloudFormation 可能需要一段时间才能将资源标记为 FAIL。要稳定自定义资源,请使用以下 cURL 命令直接发出 HTTP 请求。要发出请求,必须包含请求对象的详细信息。
$ curl -H 'Content-Type: ''' -X PUT -d '{ "Status": "SUCCESS", "PhysicalResourceId": "examplephysicalresourceid",
"StackId": "examplestackid",
"RequestId": "e2fc8f5c-0391-4a65-a645-7c695646739",
"LogicalResourceId": "CloudWatchtrigger"
}' 'https://cloudformation-custom-resource-response'
**注意:**将 examplephysicalresourceid 替换为您的物理资源 ID,将 examplestackid 替换为您的堆栈 ID。
如果 Lambda 函数记录了请求对象,您可以在关联的 Amazon CloudWatch Logs 中找到 RequestID 和 S3 预签名 URL。有关详细信息,请参阅如何删除 CloudFormation 中卡滞在 DELETE_FAILED 状态或 DELETE_IN_PROGRESS 状态的 Lambda 支持的自定义资源?
相关信息
使用 CloudFormation 实施由 Lambda 支持的自定义资源有哪些最佳实践?