使用Serverless Framework在Lambda中创建Layer
首先
这篇文章是《开放流媒体Advent Calendar 2018》的第14天内容。虽然是根据直觉选择的日期,但无意中与去年的同一天重合了。
最近在re:Invent上宣布和实施的AWS Lambda的Layer功能,由于Serverless Framework已经与之兼容,所以我立刻尝试了一下。执行环境是在VirtualBox上安装的CentOS7,但只要能使用Node.js(npm),环境差异应该并不大。
引入
确认 Node.js 版本是 6.5.0 或以上。
node --version
如果是旧版本,可以使用nvm或yum进行安装。
请确认您正在使用的 Serverless Framework 版本是 1.34.0 或更高版本。
sls --version
如果是旧版本(包括未安装的情况),则执行相同的命令。
npm i -g serverless
使用aws-nodejs模板创建服务。
sls create --template aws-nodejs --path my-service
确认AWS凭据已设置
aws configure list
Layer的实现
我们已经成功地按照上述步骤部署了一个简单的Lambda函数。现在我们要添加一个Layer。
模块的源代码
根据第一份文档的指示,我们创建一个模块,它是一个简单的将参数平方的函数,并且命名为pow。
.
├── handler.js
├── my-layer ← 任意の名称のディレクトリ(serverless.ymlに記述する)
│ └── nodejs
│ └── node_modules
│ └── pow
│ └── index.js
└── serverless.yml
我-层/寿辰/节点_模块/效能/索引.js是一个普通函数,没有什么值得特别注意的。
module.exports = i => i * i;
设定文件的描述
在serverless.yml文件中编写定义Layer的内容。
service:
provider:
name: aws
runtime: nodejs8.10
functions:
hello:
handler: handler.hello
# ここから↓を追加
layers:
mylayer:
path: my-layer
关于将Layer的名称更改为“mylayer”而不是“my-layer”的原因将在后文中提到。
部署
部署的程序与以往一样。
sls deploy
我会确认 Layer 是否已经创建。
aws lambda list-layers
{
"Layers": [
{
"LayerName": "mylayer",
"LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:mylayer",
"LatestMatchingVersion": {
"LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:mylayer:1",
"Version": 1,
"CreatedDate": "2018-12-13T23:59:59.999+0000"
}
}
]
}
使用Layer
目前的情况下,已创建了 Layer,但它是一个孤独的存在,无法从任何地方调用。
接下来,我们将添加调用 Lambda 函数的 Layer 处理过程。
設置檔案的描述
在函数的定义中添加一个名为layers的参数。
service:
provider:
name: aws
runtime: nodejs8.10
functions:
hello:
handler: handler.hello
# ここから
layers:
- {Ref: MylayerLambdaLayer}
# ここまで追加
layers:
mylayer:
path: my-layer
以下は、チャイニーズ語での同義表現です:
這裡出現了將其稱為「mylayer」的原因。文件2包含了這個原因。
你在CloudFormation模板中的层名称将是你的层名称(首字母大写,去除空格)并在末尾添加LambdaLayer。
有件事需要说一下,但是并没有进行预期的转换。
-
- my-layer → MyDashlayerLambdaLayer
- my_layer → MyUnderscorelayerLambdaLayer
我觉得可以根据个人喜好和政策来决定命名规则,如果称为「MyLayer」,就变成了「MyLayerLambdaLayer」。
修改Lambda函数
将使用由模板生成的Lambda函数(handler.js)更改为使用在Layer中定义的模块(pow)。
'use strict';
const pow = require('pow');
module.exports.hello = async (event, context) => {
return pow(event.value);
};
我决定不使用REST API,改为一个简单的函数只返回值。
重新部署
修改已经完成。请再次部署。步骤不变。
sls deploy
一旦部署完成后,我们将检查Lambda函数的定义。
aws lambda get-function-configuration --function-name my-service-dev-hello
可以看出,在Layers中注册了创建的Layer。
{
"Layers": [
{
"CodeSize": 206,
"Arn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:mylayer:2"
}
],
"FunctionName": "my-service-dev-hello",
"LastModified": "2018-12-13T23:59:59.999+0000",
"RevisionId": "00000000-1111-2222-3333-444444444444",
"MemorySize": 1024,
"Version": "$LATEST",
"Role": "arn:aws:iam::123456789012:role/my-service-dev-ap-northeast-1-lambdaRole",
"Timeout": 6,
"Runtime": "nodejs8.10",
"TracingConfig": {
"Mode": "PassThrough"
},
"CodeSha256": "XXXXXXXXXXXXXXXXXXXXX/YYYYYYYYYYYYYYYYYYYYY=",
"Description": "",
"VpcConfig": {
"SubnetIds": [],
"VpcId": "",
"SecurityGroupIds": []
},
"CodeSize": 387,
"FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:my-service-dev-hello",
"Handler": "handler.hello"
}
每个Layer的ARN末尾的数字代表版本号,每次部署时会进行递增。
执行
现在环境已经准备好了。让我们执行一个使用Layer的Lambda函数试试看。
sls invoke --function hello --data '{"value": 2}'
4
返回了乘以自身的数值。pow函数可以正常使用。
总结
最近,AWS SAM有一种压迫感,对Serverless Framework形成竞争压力,但是能省去创建Layer存档的麻烦,我觉得还是有使用场景的。无论何事都应该恰当地使用合适的工具和方法。
额外物品
当我按下述方式放置package.json文件时,期望自动安装其中的dependencies模块,但是结果却不如期望。
.
├── handler.js
├── my-layer
│ └── nodejs
│ ├── node_modules
│ │ └── pow
│ │ └── index.js
│ └── package.json
└── serverless.yml
https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-pathhttps://serverless.com/framework/docs/providers/aws/guide/layers#using-your-layers主观的。