在 typescript 中将 CDK 与多个堆栈一起使用时,如何阻止 cdk deploy 命令捆绑所有 lambda 函数?

When using CDK with multiple stacks in typescript, how can I stop the cdk deploy command from bundling all lambda functions?

提问人:ricardosmg 提问时间:11/10/2023 最后编辑:ricardosmg 更新时间:11/11/2023 访问量:47

问:

我为 2 个单独的 lambda 函数定义了 2 个堆栈。每个都有单独的 package.json 及其依赖项。当我在本地构建它们时,我可以成功运行命令。但在后台,它会构建 Stack1 和 Stack2。当在设置了所有模块的本地运行时,这是可以的。但是,当尝试通过 CI 运行时,我只运行要部署的所需模块的命令。cdk deploy Stack1npm install

这会导致构建失败,因为另一个堆栈正在尝试捆绑尚未安装任何依赖项的函数。

除了为每个函数设置单独的 CDK 实例或咬紧牙关并为每个函数安装依赖项之外,还有什么方法可以解决这个问题吗?

我已经进行了检查以检测是否存在 dist 文件夹,并使用它来防止运行 lambda 堆栈 lambda 特定的创建函数。但这仅在 cdk 之外通过 esbuild 手动创建捆绑包时才有效。我不会对所有功能都这样做,只对层这样做。

更新进一步调查,这似乎是有意构建 CDK 的方式。如果您在部署中指定堆栈名称,CDK 仍将运行代码以准备代码中的所有堆栈。只是如果它不在命名堆栈中,它实际上不会部署准备好的代码的输出。

当 CDK 用于编译代码而不是管理基础结构时,这会带来问题。我想这是一个迹象,表明 CDK 不应该真正用于部署代码,因为它是一个平台编排器,但对于 lambda 最佳实践来说,界限确实很模糊。因此,隐藏:

const function1 = new NodejsFunction(this, 'lambda-function-1, {
  ...commonProps,
  entry: `${resolve(__dirname)}/../../functions/lambda1.ts`,
  handler: 'main',
  functionName: 'Lambda1Main',
  description: 'Function 1 Main method',
  environment,
  layers: [
    LayerVersion.fromLayerVersionArn(
      this,
      `ALayer-lambda-function-1`,
       Fn.importValue('ALayer-layer-latest'),
    ),
  ],
});

在检查中是不够的,因为在我运行的堆栈中,由于 function1 未定义而失败。existsSync('node_modules')function1.functionArn

那么,这是否意味着整个堆栈每次都需要同步和验证,而不管部署的是哪个堆栈?

打字稿 lambda aws-cdk

评论

0赞 brushtakopo 11/10/2023
如果堆栈 1 和 2 之间没有依赖关系,为什么还要构建它们?
0赞 ricardosmg 11/11/2023
这是令人困惑的部分,如果我指定 stack1,那么它只部署 stack1。但是,无论我指定哪个堆栈,每个堆栈中的实例似乎都在运行。它不部署它们,只是创建捆绑包new NodejsFunction
0赞 gshpychka 11/12/2023
你试过国旗吗?--exclusively
0赞 ricardosmg 11/19/2023
@gshpychka我确实尝试了排他性标志,但问题似乎是因为打字稿方面确实按原样执行代码。代码中没有用于确定应运行哪些步骤的逻辑。然后,一旦它全部准备好作为 cloudformation 模板,这些模板就会以所需的逻辑应用。这是有道理的,而且考虑起来非常明显,但是在编译源代码的过程中会产生一些不良后果,并且可能表明它不适合将基础架构和应用程序代码步骤组合在一个地方。
0赞 gshpychka 11/21/2023
该标志应导致其他堆栈的资产未被捆绑 - 如果那样,请打开 github 问题;情况并非如此(会帮助我们所有人)

答:

1赞 ricardosmg 11/11/2023 #1

我觉得这应该被记录下来,或者可能作为一个问题被删除。但是我发现有一种解决方法。此票证的答案:https://github.com/aws/aws-cdk/issues/11625 突出显示了获取当前定义的堆栈的方法:https://github.com/aws/aws-cdk/issues/11625#issuecomment-1470867494。更新堆栈以检查它们是否成为目标可防止它们每次都初始化。从根本上说,这对我来说就像应该在父类中发生的事情。app.tsStack

的代码示例:app.ts

const app = new App();
const bundlingStacks = app.node.tryGetContext("aws:cdk:bundling-stacks") as Array<string>;
const buildAllStacks = bundlingStacks.includes("**");

const stacks: string[] = ['Stack1', 'Stack2'];

if (buildAllStacks || bundlingStacks.includes(stacks[0])) {
    new Stack1(app, stacks[0], {});
}

if (buildAllStacks || bundlingStacks.includes(stacks[1])) {
    new Stack2(app, stacks[1], {});
}