使用 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 }
我有一个项目使用 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 }