如何删除 CloudFormation 中卡在 DELETE_FAILED 状态或 DELETE_IN_PROGRESS 状态的 Lambda 支持的自定义资源?

上次更新时间:2021 年 8 月 23 日

我的 AWS Lambda 支持的自定义资源在 AWS CloudFormation 中卡在 DELETE_FAILED 状态或 DELETE_IN_PROGRESS 状态。我想删除我的自定义资源。

简短描述

选择以下解决方法之一:

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

解决方法

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

当 Lambda 支持的自定义资源缺少用于处理删除请求的逻辑时,如果您尝试删除堆栈,就会收到错误消息。如果自定义资源包含错误的删除逻辑,您也可能会收到错误消息。该错误消息为:“自定义资源未能在预期时间内实现稳定。” 堆栈的状态会更改为 DELETE_FAILED。

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

1.    打开 CloudFormation 控制台

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

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

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

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

堆栈的状态会更改为 DELETE_COMPLETE。

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

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

如果您的堆栈在删除自定义资源时卡在 DELETE_IN_PROGRESS 状态,那么您的堆栈可能缺少用于处理删除请求的逻辑。或者,您的堆栈可能包含错误的删除逻辑。

要强制删除堆栈,必须手动发送 SUCCESS 信号。该信号需要 ResponseURLRequestId 值,这两个值都包含在从 CloudFormation 发送到 Lambda 的事件中。

1.    确认您的 Lambda 函数会记录事件详细信息。

如果您的 Lambda 函数不包含将事件打印到日志的逻辑,那么您将无法获得 ResponseURLRequestId 值。这些值是发送手动信号所必需的。在这种情况下,您必须等待大约一个小时,CloudFormation 堆栈超时并进入 DELETE_FAILED 状态。然后完成 Delete a custom resource that's stuck in DELETE_FAILED status (删除卡在 DELETE_FAILED 状态的自定义资源) 部分的步骤以删除堆栈。

注意:如果您的 Lambda 函数中已有以下逻辑,请转至第 2 步。

逻辑示例:

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

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

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

3.    打开 Lambda 控制台

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

5.    选择 Monitorin (监控) 选项卡,然后选择 View logs in CloudWatch (查看 CloudWatch 中的日志)

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

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

7.    在最新日志中,确定 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"

8.    要向删除请求发送响应对象中的 SUCCESS 响应信号,请运行以下命令。请务必包含从第 7 步中复制的值。

$ 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
  '

在 CloudFormation 堆栈事件中,您的自定义资源的状态会更改为 DELETE_COMPLETE。