如何对 AWS CloudFormation 中卡在 DELETE_FAILED 状态或 DELETE_IN_PROGRESS 状态的 AWS Lambda 支持的自定义资源进行故障排除?

上次更新时间:2019 年 11 月 11 日

在 AWS CloudFormation 中,我的自定义资源卡在 DELETE_FAILED 状态或 DELETE_IN_PROGRESS 状态。如何才能删除我的自定义资源?

简短描述

选择以下任一解决方法:

  • 删除卡在 DELETE_FAILED 状态的自定义资源
  • 删除卡在 DELETE_IN_PROGRESS 状态的自定义资源

解决方法

删除卡在 DELETE_FAILED 状态的自定义资源

如果您的 AWS Lambda 支持的自定义资源缺少处理 Delete 请求的逻辑,而您要尝试删除堆栈,则会收到“Custom Resource failed to stabilize in expected time”错误消息。同时,堆栈的状态会更改为 DELETE_FAILED。

要删除您的堆栈,请完成以下步骤:

1.    打开 AWS CloudFormation 控制台

2.    选择包含卡在 DELETE_FAILED 状态的自定义资源的堆栈。

3.    依次选择操作删除堆栈

4.    在提供要保留的资源列表的弹出窗口中,选择卡在 DELETE_FAILED 状态的自定义资源。然后选择删除

5.    依次选择操作删除堆栈

堆栈的状态会更改为 DELETE_COMPLETE。

注意:您的自定义资源不是物理资源,因此您不必在删除堆栈后清理自定义资源。

删除卡在 DELETE_IN_PROGRESS 状态的自定义资源

如果您无法删除处于 DELETE_IN_PROGRESS 状态的堆栈,则您的堆栈可能缺少用于处理 Delete 请求的逻辑。要添加正确的逻辑,您必须完成以下步骤,手动向 AWS CloudFormation 发送 SUCCESS 信号:

1.    在 AWS CloudFormation 模板中,找到您的自定义资源向之发送请求的 Lambda 函数的名称。您可以在 AWS::CloudFormation::CustomResourceCustom::String 资源的 ServiceToken 属性中找到该函数名称。请参阅以下示例:

MyCustomResource: 
  Type: "Custom::PingTester"
  Properties: 
    ServiceToken:
      !Sub |
        arn:aws:lambda:us-east-1:111122223333:function:awsexamplelambdafunction

2.    打开 Lambda 控制台

3.    在导航窗格中,选择函数,然后选择您在步骤 1 中确定的函数。例如,在前面提供的代码示例中,awsexamplelambdafunction 为函数名称。

4.    选择监控选项卡,然后选择查看 CloudWatch 中的日志

5.    在 Amazon CloudWatch 控制台中,选择最新的日志。

注意:仅当您的函数有权访问用于日志流式处理的 Amazon CloudWatch Logs 时,您才能查看 CloudWatch 日志。

6.    在最新日志中,确定 RequestType 为 Delete 的事件,然后复制 RequestIdResponseURLStackIdLogicalResourceIdPhysicalResourceId 的值。请参阅以下示例:

Received event: {
  "RequestType": "Delete",
  "ServiceToken": "arn:aws:lambda:us-east-1:111122223333:function:awsexamplelambdafunction",
  "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3.us-east-1.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A111122223333%3Astack/awsexamplecloudformation/33ad60e0-5f25-11e9-a734-0aa6b80efab2%7CMyCustomResource%7Ce2fc8f5c-0391-4a65-a645-7c695646739?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20170313T0212304Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=QWERTYUIOLASDFGBHNZCV%2F20190415%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=dgvg36bh23mk44nj454bjb54689bg43r8v011uerehiubrjrug5689ghg94hb",
  "StackId": "arn:aws:cloudformation:us-east-1:111122223333:stack/awsexamplecloudformation/33ad60e0-5f25-11e9-a734-0aa6b80efab2",
  "RequestId": "e2fc8f5c-0391-4a65-a645-7c695646739",
  "LogicalResourceId": "MyCustomResource",
  "PhysicalResourceId": "test-MyCustomResource-1URTEVUHSKSKDFF",
  "ResourceType": "Custom::PingTester"

7.    要查看第 6 步的事件日志输出,请在 Lambda 函数的开始处输入以下 console.log() 调用:

exports.handler = function(event, context) {
    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event));
...
}

重要提示:上述输出显示了包含 ResponseURLStackIdPhysicalResourceIdLogicalResourceIdRequestId请求对象。您将在第 8 步中使用此请求对象。此输出是必需的,因为它包括 AWS CloudFormation 在每次请求中生成的预先签名的 ResponseURL

8.    要向 Delete 请求发送请求对象中的 SUCCESS 响应信号,请使用您在第 6 步中复制的值运行 curl 命令。请参阅以下示例:

$ curl -H 'Content-Type: ''' -X PUT -d '{
    "Status": "SUCCESS",
    "PhysicalResourceId": "test-CloudWatchtrigger-1URTEVUHSKSKDFF",
    "StackId": "arn:aws:cloudformation:us-east-1:111122223333:stack/awsexamplecloudformation/33ad60e0-5f25-11e9-a734-0aa6b80efab2
  ",
    "RequestId": "e2fc8f5c-0391-4a65-a645-7c695646739",
    "LogicalResourceId": "CloudWatchtrigger"
  }' 'https://cloudformation-custom-resource-response-useast1.s3.us-east-1.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A111122223333%3Astack/awsexamplecloudformation/33ad60e0-5f25-11e9-a734-0aa6b80efab2%7CMyCustomResource%7Ce2fc8f5c-0391-4a65-a645-7c695646739?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20170313T0212304Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=QWERTYUIOLASDFGBHNZCV%2F20190415%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=dgvg36bh23mk44nj454bjb54689bg43r8v011uerehiubrjrug5689ghg94hb
  '

您的自定义资源的状态会更改为 DELETE_COMPLETE。