SAM构建-它还会构建层吗?

时间:2019-10-15 20:44:48

标签: aws-lambda aws-lambda-layers

我对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文件中./dependenciesSkimageLayer中指定的图层没有任何构建。但是HelloWorldFunction仍然可以正确构建(当然现在没有任何包含的模块)

5 个答案:

答案 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构建目录。

See my post here on that.

对于现在扭曲SAM来为您构建图层,这种方法实际上似乎非常有效。

答案 3 :(得分:0)

我可以使用以下脚本。经过Ubuntu 18和CodeBuild的测试

它对.aws-sam/build/layername/python/的安装要求是该层的要求。然后,您可以正常运行sam packagesam 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 packagesam 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

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-layers.html