更新自定义资源会导致它们被删除吗? [英] Updating custom resources causes them to be deleted?

查看:62
本文介绍了更新自定义资源会导致它们被删除吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用CloudFormation模板时,我发现具有Lambda支持功能实现的自定义资源功能对于处理CloudFormation不提供良好支持的各种任务非常有用。

When using CloudFormation templates, I find the "Custom Resource" feature, with its Lambda backing function implementation, very useful to handle all kinds of tasks that CloudFormation does not provide good support for.

通常,我使用自定义资源在堆栈创建过程中进行设置(例如查找AMI名称),或在删除过程中进行清理(例如从S3或Route53中删除将阻止删除操作的对象)-这是可行的

Usually, I use custom resources to setup things during stack creation (such as looking up AMI names) or clean up things during deletion (such as removing objects from S3 or Route53 that would block deletion) - and this works great.

但是当我尝试实际使用自定义资源来管理实际的自定义资源时,该资源必须在创建堆栈时创建,并在删除堆栈时删除,并且-这就是问题所在-有时在堆栈更新期间使用新值进行更新,CloudFormation集成的行为异常,并导致自定义资源失败。

But when I try to actually use a "custom resource" to manage an actual custom resource, that has to be created during stack creation, deleted during stack deletion, and - this is where the problem lies - sometimes updated with new values during a stack update, the CloudFormation integration behaves unexpectedly and causes the custom resource to fail.

是在堆栈的 UPDAT期间自定义资源属性之一已更改的堆栈更新期间在E_IN_PROGRESS 阶段,CloudFormation将更新事件发送到后备Lambda函数,所有值均已正确设置,并且还发送了旧值的副本。但是更新完成后,CloudFormation将启动 UPDATE_COMPLETE_CLEANUP_IN_PROGRESS 阶段,并向后备Lambda函数发送删除事件( RequestType 设置为删除)。

The problem seems to be that during a stack update where one of the custom resource properties has changed, during the stack's UPDATE_IN_PROGRESS stage, CloudFormation sends an update event to the backing Lambda function, with all values set correctly and a copy of the old values sent as well. But after the update completes, CloudFormation starts the UPDATE_COMPLETE_CLEANUP_IN_PROGRESS stage and sends the backing Lambda function a delete event (RequestType set to Delete).

发生这种情况时,后备lambda函数假定堆栈已被删除并删除了自定义资源。结果是在更新后,自定义资源消失了。

When that happens, the backing lambda function assumes the stack is being deleted and removes the custom resource. The result is that after an update the custom resource is gone.

我已经查看了日志中的请求数据,清除删除看起来与真正的删除事件:

I've looked at the request data in the logs, and the "cleanup delete" looks identical to a real "delete" event:

{
RequestType: 'Delete',
ServiceToken: 'arn:aws:lambda:us-east-2:1234567890:function:stackname-resname-J0LWT56QSPIA',
ResponseURL: 'https://cloudformation-custom-resource-response-useast2.s3.us-east-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-2%3A1234567890%3Astack/stackname/3cc80cf0-5415-11e8-b6dc-503f3157b0d1%7Cresnmae%7C15521ba8-1a3c-4594-9ea9-18513efb6e8d?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180511T140259Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7199&X-Amz-Credential=AKISOMEAWSKEYID%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=3abc68e1f8df46a711a2f6084debaf2a16bd0acf7f58837b9d02c805975df91b',
StackId: 'arn:aws:cloudformation:us-east-2:1234567890:stack/stackname/3cc80cf0-5415-11e8-b6dc-503f3157b0d1',
RequestId: '15521ba8-1a3c-4594-9ea9-18513efb6e8d',
LogicalResourceId: 'resname',
PhysicalResourceId: '2018/05/11/[$LATEST]28bad2681fb84c0bbf80990e1decbd97',
ResourceType: 'Custom::Resource',
ResourceProperties: {
    ServiceToken: 'arn:aws:lambda:us-east-2:1234567890:function:stackname-resname-J0LWT56QSPIA',
    VpcId: 'vpc-35512e5d',
    SomeValue: '4'
} 
}



实际删除:



Real Delete:

{
RequestType: 'Delete',
ServiceToken: 'arn:aws:lambda:us-east-2:1234567890:function:stackname-resname-J0LWT56QSPIA',
ResponseURL: 'https://cloudformation-custom-resource-response-useast2.s3.us-east-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-2%3A1234567890%3Astack/stackname/3cc80cf0-5415-11e8-b6dc-503f3157b0d1%7Cresname%7C6166ff92-009d-47ac-ac2f-c5be2c1a7ab2?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180524T154453Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=AKISOMEAWSKEYID%2F20180524%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=29ca1d0dbdbe9246f7f82c1782726653b2aac8cd997714479ab5a080bab03cac',
StackId: 'arn:aws:cloudformation:us-east-2:123456780:stack/stackname/3cc80cf0-5415-11e8-b6dc-503f3157b0d1',
RequestId: '6166ff92-009d-47ac-ac2f-c5be2c1a7ab2',
LogicalResourceId: 'resname',
PhysicalResourceId: '2018/05/11/[$LATEST]c9494122976b4ef3a4102628fafbd1ec',
ResourceType: 'Custom::Resource',
ResourceProperties: {
    ServiceToken: 'arn:aws:lambda:us-east-2:1234567890:function:stackname-resname-J0LWT56QSPIA',
    VpcId: 'vpc-35512e5d',
    SomeValue: '0'
}
}

我看到的唯一有趣的请求字段是物理资源ID不同,但是我不知道该与什么相关,以检测它是否是真正的删除。

The only interesting request field that I can see is the physical resource ID is different, but I don't know what to correlate that to, to detect if it is the real delete or not.

推荐答案

问题似乎成为样品 sendResponse()函数的实现,该函数用于将自定义资源完成事件发送回CloudFormation。此方法负责设置自定义资源的物理资源ID。据我了解,该值表示外部资源的全局唯一标识符,该标识符由支持CloudFormation自定义资源的Lambda函数管理。

The problem seems to be the sample implementation of the sendResponse() function that is used to send the custom resource completion event back to CloudFormation. This method is responsible for setting the custom resource's physical resource ID. As far as I understand, this value represents the globally unique identifier of the "external resource" that is managed by the Lambda function backing the CloudFormation custom resource.

CloudFormation的 Lambda支持的自定义资源示例代码,以及 cfn-响应 NPM模块 send() CloudFormation内置的 cfn -response 模块,此方法具有默认的行为,用于计算物理资源ID(如果未作为第5个参数提供),并且使用CloudWatc h正在处理正在处理的请求的日志的日志日志流:

As can be seen in the CloudFormation's "Lambda-backed Custom Resource" sample code, as well as in the cfn-response NPM module's send() and the CloudFormation's built-in cfn-response module, this method has a default behavior for calculating the physical resource ID, if not provided as a 5th parameter, and it uses the CloudWatch Logs' log stream that is handling logging for the request being processed:

var responseBody = JSON.stringify({
    ...
    PhysicalResourceId: context.logStreamName,
    ...
})

由于CloudFormation(或AWS Lambda运行时?)偶尔将日志流更改为新的日志流,因此 sendResponse()生成的物理资源ID正在更改

Because CloudFormation (or the AWS Lambda runtime?) occasionally changes the log stream to a new one, the physical resource ID generated by sendResponse() is changing unexpectedly from time to time, and confuses CloudFormation.

据我了解,有时在更新期间需要替换CloudFormation托管实体(一个很好的例子是 RDS :: DBInstance ,几乎所有更改都需要替换)。 CloudFormation策略是,如果需要替换资源,则在更新阶段创建新资源,而在清理阶段删除旧资源。

As I understand it, CloudFormation managed entities sometimes need to be replaced during an update (a good example is RDS::DBInstance that needs replacing for almost any change). CloudFormation policy is that if a resource needs replacing, the new resource is created during the "update stage" and the old resource is deleted during the "cleanup stage".

因此使用默认的 sendResponse()物理资源ID计算,该过程如下所示:

So using the default sendResponse() physical resource ID calculation, the process looks like this:


  1. 已创建堆栈。

  2. 已创建新的日志流以处理自定义资源日志记录。

  3. 调用了Lambda支持函数来创建资源和默认行为将其资源ID设置为日志流ID。

  4. 一些时间过去了

  5. 堆栈已使用新参数更新

  6. 将创建一个新的日志流来处理具有新ID的自定义资源日志。

  7. 称为后备Lambda函数更新资源,默认行为是将新资源ID设置为新的日志流ID。

  8. CloudFormation知道可以使用新资源创建的用于替换旧资源的s,并根据该策略应在清理阶段删除旧资源。

  9. CloudFormation到达清理阶段,并发送带有旧的物理资源ID。

  1. A stack is created.
  2. A new log stream is created to handle the custom resource logging.
  3. The backing Lambda function is called to create the resource and the default behavior set its resource ID to be the log stream ID.
  4. Some time passes
  5. The stack gets updated with new parameters for the custom resource.
  6. A new log stream is created to handle the custom resource logging, with a new ID.
  7. The backing Lambda function is called to update the resource and the default behavior set a new resource ID to the new log stream ID.
  8. CloudFormation understands that a new resource was created to replace the old resource and according to the policy it should delete the old resource during the "cleanup stage".
  9. CloudFormation reaches the "cleanup stage" and sends a delete request with the old physical resource ID.

解决方案,至少在我从不替换外部资源的情况下,是制造唯一的托管资源的标识符,将其作为发送响应例程的第五个参数,然后坚持使用-在更新响应中继续发送在更新请求中接收到的相同物理资源ID。然后,CloudFormation将永远不会在清理阶段期间发送删除请求。

The solution, at least in my case where I never "replace the external resource" is to fabricate a unique identifier for the managed resource, provide it as the 5th parameter to the send response routine, and then stick to it - keep sending the same physical resource ID received in the update request, in the update response. CloudFormation will then never send a delete request during the "cleanup stage".

我的实现(在JavaScript中)如下所示:

My implemenation (in JavaScript) looks something like this:

    var resID = event.ResourceProperties.PhysicalResourceId || uuid();
    ...
    sendResponse(event, context, status, resData, resID);

另一种选择-仅当您确实需要更换外部资源并想要更换时才有意义坚持在清除过程中删除旧资源的CloudFormation模型-将实际的外部资源ID用作物理资源ID,并在收到删除请求时-使用提供的物理资源ID删除旧的外部资源。最初,这就是CloudFormation设计人员的初衷,但他们的默认示例实现会引起很多混乱-可能是因为示例实现无法管理真实资源,也没有更新功能。 CloudFormation中也没有零文档来解释设计和推理。

Another alternative - which would probably only make sense if you actually need to replace the external resource and want to adhere to the CloudFormation model of removing the old resource during cleanup - is to use the actual external resource ID as the physical resource ID, and when receiving a delete request - to use the provided physical resource ID to delete the old external resource. That is what CloudFormation designers probably had in mind in the first place, but their default sample implementation causes a lot of confusion - probably because the sample implementation doesn't manage a real resource and has no update functionality. There is also zero documentation in CloudFormation to explain the design and reasoning.

这篇关于更新自定义资源会导致它们被删除吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆