背景
我觉得我需要提供很多背景信息,才能全面理解问题的范围,所以如果这篇文章有点长或者提供了太多信息,我提前道歉,我只是想尽可能地避免后续的问题和澄清请求。
我有一个技术交接项目。它曾经在另一个 AWS 帐户的不同所有者名下生产过。我正在尝试在我控制的 AWS 帐户中重新启动它,其中一个包对我造成了一些问题。
它使用 Serverless 来配置一些 S3 存储桶及其访问策略、一些 IAM 角色和一堆 ApiGateway 方法。该软件包依赖于 nested stacks 以避免像 here 描述的 200 资源限制。
最后,CircleCI 连接的 IAM 用户附有 AdministratorAccess
策略。
问题
在构建的这个步骤中,我一直在收到来自 CircleCI 的失败消息。
node_modules/.bin/serverless deploy --verbose --stage develop --region us-east-1 --package ./.serverless
具体故障的性质似乎是不一致的,即它并不总是在同一个位置失败。有时候资源创建失败,整个过程就会回滚。以下是日志中几个运行失败的示例(前后大约5行),接着是Serverless报告的实际错误信息。
运行1
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod001VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod002VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod003VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod004VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod006Options
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncAbcNestedStack
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncDefNestedStack
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncGhiNestedStack
CloudFormation - UPDATE_ROLLBACK_IN_PROGRESS - AWS::CloudFormation::Stack - org-package-develop
CloudFormation - UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - org-package-develop
CloudFormation - DELETE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethod006Options
Serverless Error ---------------------------------------
An error occurred: FuncAbcNestedStack - Embedded stack arn:aws:cloudformation:us-east-1:ACCOUNT_ID:stack/org-package-develop-FuncAbcNestedStack/RESOURCE-ID-001 was not successfully created: The following resource(s) failed to create: [AbcLambdaFunction]. .
运行 2
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod001VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod002VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod005VarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod006Options
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethod004VarOptions
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncDefNestedStack
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncGhiNestedStack
CloudFormation - CREATE_FAILED - AWS::CloudFormation::Stack - FuncAbcNestedStack
CloudFormation - UPDATE_ROLLBACK_IN_PROGRESS - AWS::CloudFormation::Stack - org-package-develop
CloudFormation - UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - org-package-develop
CloudFormation - DELETE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethod001VarOptions
Serverless Error ---------------------------------------
An error occurred: FuncDefNestedStack - Embedded stack arn:aws:cloudformation:us-east-1:ACCOUNT_ID:stack/org-package-develop-FuncDefNestedStack/RESOURCE-ID-002 was not successfully created: The following resource(s) failed to create: [DefLambdaFunction]. .
注意:上述日志中的所有唯一标识符都已被替换/混淆为新的标识符,这些标识符在两个日志中都是唯一的,而不是每个日志都是唯一的,即“FuncAbcNestedStack”出现在两个日志中,因为它在配置中是完全相同的资源。
问题
鉴于上述情况,我现在的问题是如何调试?这代表了我认为可用的所有细节,因为我无法深入挖掘以找出为什么资源创建失败。我已经阅读了一些关于故障排除错误的指南,但由于我实际上没有直接使用EC2,所以那里的内容并没有太大帮助。
4月4日更新
我已经做了大量的工作来尝试调试模板。请注意,我通常不直接使用模板,Serverless会生成它们并将它们转储到S3存储桶中,然后应用它们。
以下是我采取的一些步骤。
- 更新至最新版本的Serverless (
1.67.0
, 从1.30.3
) - 删除现有堆栈
- 删除相关的S3存储桶
- 更新node运行时环境 (
12.16.1
, 从8.10.0
) - 下载并检查包含失败Lambda的CFN模板 - 未发现问题
我仍然得到相同的结果。当我重新运行构建并检查CloudFormation事件日志时,我发现一个堆栈创建失败,因为其中一个Lambda函数创建失败。这个函数没有什么特别之处(其他Lambda在运行的早期成功创建),除了它是API中每个其他函数的授权者,这可能重要也可能不重要。我仍然无法找到更多关于为什么Lambda函数创建失败的详细信息。
4月6日更新
好的,现在我理解了CloudFormation控制台的工作方式,这里是我认为的最底层的错误消息
Unzipped size must be smaller than 262144000 bytes (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: 0507722d-46e7-4340-bc68-fdba1ed469d6)
看着这个嵌套栈的CFN模板,我现在明白了正在发生什么。每个Lambda都有自己的堆栈,并且整个包中的每个堆栈都被编译成一个单独的ZIP文件,其大小最终约为270MB或比上面指定的限制大20MB。从这一点出发,似乎我有两条前进的可能路径:
- 找出如何将函数分散到多个ZIP文件中
- 更改webpack配置,使编译后的文件不那么臃肿(我真的不知道这里发生了什么 - 在webpack之后,1k TypeScript文件变成了6.5MB)