使用 Lambda Layers + Cloud Formation 在 lambda 之间共享 node_modules 文件夹

Sharing node_modules folder between lambda using Lambda Layers + Cloud Formation

我有一个项目使用 serverless-framework (this) 来定义要使用的 AWS 资源。我有各种 .yml 文件来描述项目需要的每个资源 运行.

最近,我不得不为我的 lambda 安装几个 NPM 包,它们已经变得非常大(以兆字节为单位)(>3MB),因此无法再从控制台查看代码。

由于在每个 lambda 中包含 node_modules 不是最佳实践,而且它们以这种方式非常繁重,我想知道是否使用 Lambda 层在 lambda 之间共享 node_modules。

作为 .yml,我在它们之间有一个共享结构,称为 provider.yml,类似于:

name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
region: ${opt:region, "eu-central-1"}
stage: ${opt:stage, "dev"}
profile: ${self:custom.profiles.${self:provider.stage}}
deploymentBucket:
 name: avatar-${self:provider.stage}-deploymentbucket
 versioning: true
 blockPublicAccess: true
environment:
 EXAMPLE_ENV_VAR: ${self:custom.baseResource}-envvar
USERPOOL:
 'Fn::ImportValue': ${self:custom.baseResource}-userPoolId
APP_CLIENT_ID:
 'Fn::ImportValue': ${self:custom.baseResource}-userPoolClientId
iamRoleStatements:
 - Effect: Allow
 Action:
  - dynamodb:Query
  - ...
Resource: "*"

然后我有一个包含 provider.yml 和所有 lambda 的文件(称为 serverless.yml)并且是我用来部署的文件:

service: listOfLambdas
app: appname
frameworkVersion: '2'
projectDir: ../../

provider: ${file(../../resources/serverless-shared-config/provider.yml)}

package:
 individually: true
 exclude:
  - "**/*"

functions:
 - ${file(./serverless-functions.yml)}

最后,我有了包含 Lambdas 结构的无服务器-functions.yml:

lambdaName:
handler: src/handlers/auth/example.run
name: ${self:custom.base}lambdaName
description: Lambda description
events:
 - httpApi:
     method: POST
     path: /api/v1/example
package:
 include:
   - ../../node_modules/**

这包括 Lambda 中的 node_modules 文件夹。

如何使用由 Cloud Formation 管理的 YML 模板创建资源以创建 Lambda 层,我可以将我的所有 lambda 分配给该层,以便它们共享 node_modules 文件夹。我希望必须使用 CloudFormation YML 模板 在资源文件夹中创建一个新的 serveless.yml 来绑定我猜我的 lambdas。

我需要它由 CloudFormation 管理,这样我就可以拥有一个包含项目使用的所有资源的公共堆栈,这样我就可以在启动时部署它。

那么 node_modules 应该放在项目中的什么地方?现在项目是这样的:

Root
|_ lib
|_ node_modules
|_ resources
   |_serverless-shared-config
     |_provider.yml
   |_s3
     |_serverless.yml
   |_apigateay 
   |_ ... 
|_ services
   |_ lambda
      |_ src
         |_ index.js
         |_ ...
      |_ serverless.yml
      |_ serverless-functions.yml

在哪里可以找到解决这个问题的模板?或者在 Lambda 之间共享 node_modules 的最佳实践是什么?

一般来说,使用 Lambda 层是存储共享代码的好方法,因为您可以减少冗余并保持较小的部署包大小。 层也可以使用无服务器框架创建,因此您可以将它们包含到现有模板中并由 Serverless/CloudFormation 管理它们。这是一个 link 到 documentation 的配置示例和解释。这是一个如何向 serverless.yaml 文件添加图层的示例:

layers:
  NodeModules:
    path: layer
    package:
      artifact: layer.zip
    name: layer
    compatibleRuntimes:
      - nodejs12.x
      - nodejs14.x

functions:
 - ${file(./serverless-functions.yml)}

然后从您的 serverless-functions.yaml 文件中的每个 Lambda 函数,您可以按如下方式引用该层:

lambdaName:
  handler: src/handlers/auth/example.run
  name: ${self:custom.base}lambdaName
  layers:
    - { Ref: NodeModulesLambdaLayer }