我对lambda和SAM都是陌生的-因此,如果我搞砸了任何简单的事情,请不要大喊:D。
摘要::我无法sam build
来构建template.yaml
中指定的图层,它只能构建lambda函数。
背景:我正在尝试在python3.7中使用skimage(scikit-image
)模块构建一个lambda函数。为此,我正在尝试使用SAM来构建和部署所有组件。 ...这正在起作用
我正在尝试将scikit-image模块部署为一层(并使用SAM进行构建),而不是将其包含在lambda函数方向上 ...这不起作用
首先,我只是扩展标准的SAM Hello World
应用。
我通过将skimage添加到requirements.txt
,然后使用sam build -u
,然后从构建的包目录中手动删除numpy / scipy依赖项来使skimage工作(我有AWS scipy /包括numpy层。
(我将import numpy,scipy.ndimage和skimage.draw添加到了标准的hello world应用程序中,并对每个应用程序都包含了一些测试函数调用)
requirements.txt:
requests
scikit-image
之后,一切正常(在本地和/或在AWS上运行)。
但是,我现在想将skimage模块移出我的应用程序,并移到新的自定义层中(我希望将skimage放在一个层中,以重复使用某些功能)
要进行设置,我创建了一个依赖关系目录,并将Requirements.txt移至该目录(在应用程序目录中保留了空的Requirements.txt)。 然后,我更新了template.yaml以也指定新层:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.7
Layers:
- arn:aws:lambda:us-west-2:420165488524:layer:AWSLambda-Python37-SciPy1x:2
- !Ref SkimageLayer
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
SkimageLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: Skimage
Description: Skimage module layer
ContentUri: dependencies/
CompatibleRuntimes:
- python3.7
RetentionPolicy: Retain
DependsOn:
- Skimage
目录结构:
▾ dependencies/
requirements.txt (responses and scikit-image)
▸ events/
▾ hello_world/
__init__.py
app.py
requirements.txt (now empty)
▸ tests/
README.md
template.yaml
但是,当我使用该模板文件运行sam build -u
时,对于template.yml文件中./dependencies
:SkimageLayer
中指定的图层没有任何构建。但是HelloWorldFunction
仍然可以正确构建(当然现在没有任何包含的模块)
答案 0 :(得分:2)
自SAM Cli version v0.50.0起,它就作为sam build
的一部分来构建图层。
Design document可能是了解其工作原理的一个很好的起点。
基本上,您必须为lambda的目标运行时设置自定义BuildMethod
:
MyLayer:
Type: AWS::Serverless::LayerVersion
Properties:
ContentUri: my_layer
CompatibleRuntimes:
- python3.8
Metadata:
BuildMethod: python3.8 (or nodejs8.10 etc..)
警告:对于Java编译语言,它has a issue会尝试在函数之前构建图层。预计将在下一个版本(PR opened already)中进行修复。
答案 1 :(得分:1)
我不确定最近是否有所更改,但是我能够做到这一点而没有问题。我的模板文件和结构与OP非常相似,只不过我已将所有通用代码放入...
/dependencies/python/lib/python3.7/site-packages/
我没有在该目录中包含requirements.txt文件...只是__init__.py
文件和需要导入到函数中的各种.py
文件。
然后,SAM找到代码并构建该层。您甚至不需要压缩目录的内容,就像一些教程告诉您的那样。
最好的部分是Layers:
可以放在模板文件的Globals:
部分中,以便该图层可用于所有功能!
Globals:
Function:
Handler: main.lambda_handler
Timeout: 10
Runtime: python3.7
Layers:
- !Ref HelperFunctions
Resources:
HelperFunctions:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: MyHelperFunctions
Description: My Lambda Layer with Helper Functions for accessing RDS, Logging, and other utilities.
ContentUri: dependencies/
CompatibleRuntimes:
- python3.6
- python3.7
LicenseInfo: MIT
RetentionPolicy: Delete
答案 2 :(得分:0)
快速解答-否,当前SAM不不 构建您在SAM template.yaml
文件中定义的层。
它将仅构建您定义的所有功能。
但是(奇怪的是)它会打包(上传到S3)并部署(在AWS中设置,分配ARN以使其可以使用等)您定义的任何层。
在SAM github问题上有一个功能请求,以实现使用SAM进行图层构建。
T 实际上,现在可以通过在SAM模板文件中创建虚拟函数以及图层条目并拥有该图层来立即入侵他,以使SAM也可以构建您的图层 ContentUri入口指向为该函数创建的.aws-sam构建目录。
对于现在扭曲SAM来为您构建图层,这种方法实际上似乎非常有效。
答案 3 :(得分:0)
我可以使用以下脚本。经过Ubuntu 18和CodeBuild的测试
它对.aws-sam/build/layername/python/
的安装要求是该层的要求。然后,您可以正常运行sam package
和sam deploy
build-layers.py
:
import yaml
import subprocess
import sys
import shutil
SAM_BUILD_PATH = ".aws-sam/build"
with open("template.yaml", "r") as f:
template = yaml.safe_load(f)
for key, resource in template["Resources"].items():
if resource["Type"] not in ["AWS::Serverless::LayerVersion", "AWS::Lambda::LayerVersion"]:
continue
properties = resource["Properties"]
content_uri = properties["ContentUri"]
layer_name = properties["LayerName"]
requirements_path = f"{content_uri}/requirements.txt"
subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", requirements_path, "-t", f"{SAM_BUILD_PATH}/{layer_name}/python"])
shutil.copyfile("template.yaml", f"{SAM_BUILD_PATH}/template.yaml")
template.yaml
:
Transform: AWS::Serverless-2016-10-31
Resources:
pandas:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: pandas
ContentUri: pandas
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
sqlparse:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: sqlparse
ContentUri: sqlparse
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
因此先致电python build-layers.py
,然后依次致电sam package
和sam deploy
我的目录如下:
lambda
layers
pandas
requirements.txt (content = pandas)
sqlparse
requirements.txt (content = sqlparse)
template.yaml
build-layers.py
buildspec.yml
:
--- # build spec for AWS CodeBuild
version: 0.2
phases:
install:
runtime-versions:
python: 3.8
commands:
- pip install aws-sam-cli
build:
commands:
- cd lambda/layers
- python build-layers.py
- sam package --s3-bucket foo --s3-prefix sam/lambda/layers | sam deploy --capabilities CAPABILITY_IAM -t /dev/stdin --stack-name LAYERS
答案 4 :(得分:0)
相对于这些较早的答案,AWS团队必须使事情变得更轻松。从当前文档中,您要做的就是在模板中将图层作为属性列出(2020年11月):
ServerlessFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: .
Handler: my_handler
Runtime: Python3.7
Layers:
- arn:aws:lambda:us-west-2:111111111111:layer:myLayer:1
- arn:aws:lambda:us-west-2:111111111111:layer:mySecondLayer:1