自定义资源未 运行 正确部署

Custom resource not running properly on deployment

两天多来,我一直在尝试使用无服务器框架部署 CloudFormation 堆栈。问题是,作为堆栈的一部分,我有一个 RDS 集群以及一个自定义资源,它依赖于 Lambda 函数(用 Python 编写)用于 初始化 一些数据库表。

serverless.yml 文件中此自定义资源的详细信息如下:

rdsMigration:
  Type: Custom::DatabaseMigration
  DependsOn: rdsCluster
  Properties:
    ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn
    Version: 1.0

使用 sls deploy 部署时,集群和 lambda 函数创建正确,但进程卡在创建 rdsMigration 资源上。

在 Lambda 代码中,我一直小心翼翼地在所有可能的情况下生成响应,包括异常。但是,这似乎不是问题所在。

显然,函数没有被调用...有点,因为即使图表看起来也很奇怪:

您可以看到没有调用,但是 "Error count and success rate" 中有一个红点大约 5:15 PM,这是资源创建开始的时间。此外,没有绿点,您可以在图例中看到下面的警告,它声称 "One or more data-points have been dropped due to non-numeric values (NaN, -Infinite, +Infinite)"。这怎么可能?我认为这不是标准行为,因为其他 Lambda 函数(必须使用 API 网关端点调用)不会显示这个奇怪的图表。

此外,CloudWatch 中没有日志流。它完全是空的,就好像函数从未被调用过一样(看起来是这样,除了在创建资源的那一刻奇怪的"red dot")。

最后,如果我 运行 使用 "AWS CloudFormation Create Request" 模板的测试用例,函数 运行s 正确,它会创建我期望的数据库初始表(不总是,但这是另一回事)和 returns 响应。

你知道这里发生了什么吗?最糟糕的是,我需要在测试之间等待两个小时,因为 CFN 堆栈在创建和销毁步骤期间卡住,直到发生超时。

谢谢!

问题出在您的 lambda 函数上。您必须将 SUCCESS 或 FAILURE 信号发送回 CFN。由于您的 lambda 函数未发送任何信号,因此等待超时(2 小时)并且 Cloudformation 失败

1.The custom resource provider processes the AWS CloudFormation request and 
  returns a response of SUCCESS or FAILED to the pre-signed URL. AWS 
  CloudFormation waits and listens for a response in the pre-signed URL location. 

2.After getting a SUCCESS response, AWS CloudFormation proceeds with the stack 
  operation. If a FAILURE or no response is returned, the operation fails.

请在您的 lambda 函数中使用 cfnresponse 模块将 SUCCESS/FAILURE 信号发送回您的 Cloudformation

更多详情: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html

我终于设法找到了问题的解决方案,尽管它没有用我在问题中解释的图表来解释奇怪的行为。

我的问题与 Abhinaya 在她的回复中提出的问题类似。由于编程错误,Lambda 函数未正确发送信号。本质上,我从 the documentation 中提取了代码(Python 3 的代码,第二个片段从末尾开始),显然我错误地删除了检索 ResponseURL 的行。当然,那是失败的。

关于此的旁注:使用 Python 的 cfnresponse 库或什至我在文档中链接的代码片段时要小心。它依赖于已弃用的 botocore.vendored,并且在最新的 botocore 版本中不再存在。因此,如果您的代码依赖于该库的新版本(如我的情况),它将失败。一个简单的解决方案是用 requests 库替换 botocore.vendored.requests

不过,还是有一些我无法理解的奇怪行为。在创建时,Lambda 函数没有向 CloudWatch 记录任何内容,并且我在问题中解释的图表中存在这种奇怪的行为。但是,这只发生在创建时。如果该函数是手动调用的,或者是作为删除过程的一部分调用的(当删除 CFN 堆栈时),那么它会写入 CloudWatch。因此,问题显然只出现在第一次调用中。

最佳。