AWS CDK整合Chalice项目时SAM模板出现重复Lambda资源报错
背景
原本将所有API及Lambda(含CloudWatch事件、触发器等)放在单个Chalice项目中,随着项目规模扩大,Lambda体积日益庞大,因此决定拆分为多个Chalice项目,在自定义域名下合并为单个API,并通过AWS CDK进行统一管理与部署。
实现方案
在component_with_stack_declaration.py中创建包含所有Chalice构造的RestApi栈:
class RestApi(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) ... code_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "src") app1 = Chalice(self, "App1", source_dir=os.path.join(code_dir, "app1")) app2= Chalice(self, "App2", source_dir=os.path.join(code_dir, "app2")) ...
报错现象
执行cdk synth时触发资源重复声明错误:
Creating deployment package. Creating deployment package. jsii.errors.JavaScriptError: @jsii/kernel.RuntimeError: Error: section 'Resources' already contains 'Lambda1LogicalID' at Kernel._ensureSync (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:10364:27) at Kernel.invoke (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:9764:34) at KernelHost.processRequest (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:11539:36) at KernelHost.run (C:\Users\....\Local\Temp\tmpgg97w2wj\lib\program.js:11499:22) at Immediate._onImmediate (C:\....\AppData\Local\Temp\tmpgg97w2wj\lib\program.js:11500:46) at processImmediate (node:internal/timers:466:21) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "B:\...\cdk_app\app.py", line 15, in <module> app.synth() File "B:\....\cdk_app\venv\lib\site-packages\aws_cdk\__init__.py", line 20043, in synth return typing.cast(_CloudAssembly_c693643e, jsii.invoke(self, "synth", [options])) File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\__init__.py", line 149, in wrapped return _recursize_dereference(kernel, fn(kernel, *args, **kwargs)) File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\__init__.py", line 399, in invoke response = self.provider.invoke( File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\providers\process.py", line 377, in invoke return self._process.send(request, InvokeResponse) File "B:\....\cdk_app\venv\lib\site-packages\jsii\_kernel\providers\process.py", line 339, in send raise RuntimeError(resp.error) from JavaScriptError(resp.stack) RuntimeError: Error: section 'Resources' already contains 'Lambda1LogicalID'
问题排查
查看cdk.out和chalice.out中的生成模板,发现Lambda资源被重复声明。chalice.out文件夹下的.sam_with_assets.json文件显示:
- app1的模板包含
Lambda1LogicalID,Handler为chalicelib.app1.handler.lambda1 - app2的模板同样包含
Lambda1LogicalID,Handler却也是chalicelib.app1.handler.lambda1,仅aws-chalice标签和CodeUri的Key不同
尽管两个项目的资源包代码正确,但app2的模板未包含自身代码中声明的Lambda,反而复用了app1的Lambda定义。
项目代码目录结构:
cdk_app | - app.py | - restapi_stack | - component_with_stack_declaration.py | - src | - app1 | | - .chalice | chalicelib | app.py | - app2 | - .chalice chalicelib app.py
尝试将Chalice构造放在RestApi栈的独立内部栈中,结果一致:资源包代码正确,但模板仍重复相同的Lambda资源(仅标签不同)。
2023年3月19日更新
问题根源在于希望为所有Chalice构造保留相同的stage名称,因此将它们的作用域设置为同一个栈,看起来每个栈中只能存在一个Chalice构造。
当前Chalice构造无法从配置文件中指定stage名称,只能基于栈全名生成,比如场景中stage名称路径为dev/RestApi/App1,这种方式对现有应用迁移到CDK不够友好,已计划在项目仓库提交该问题。
此外测试发现异常:即使成功部署不同的Lambda,使用--all参数一次性部署所有栈时,CDK会创建多个路径和方法结构完全相同的API(与第一个Chalice构造一致),并将这些不同的APIGateway映射到不同Lambda,所有Chalice项目的API端点定义都复用了第一个项目的内容。
寻求相关解决建议。
内容的提问来源于stack exchange,提问作者wteviakh

