SAM 构建 - 它也构建层吗?

SAM build - does it also build 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 依赖项(我有包含 AWS scipy/numpy 层)。

(我在标准的 hello world 应用程序中添加了 import numpy、scipy.ndimage 和 skimage.draw,并包含了对每个应用程序的一些测试函数调用)

requirements.txt:

requests
scikit-image

在那之后,一切正常(运行在本地 and/or 在 AWS 上)。


但是,我现在想将 skimage 模块从我的应用程序中移出并移到一个新的自定义层中(我想在一个层中使用 skimage 以重复使用一些功能)

为了设置它,我创建了一个依赖项目录并将 requirements.txt 移到那里(在 app 目录中留下空的 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 使用该模板文件时,没有为 ./dependencies 中指定的图层构建任何内容:template.yml 中的 SkimageLayer文件。但是 HelloWorldFunction 仍然可以正确构建(现在当然没有任何包含的模块)

快速回答 - ,当前 SAM 构建 您在SAM template.yaml 文件。

它将构建您定义的任何函数

然而(奇怪的是)它 打包(上传到 S3)并部署(在 AWS 中设置,分配 ARN 以便它可以使用等)您定义的任何层。


有一个关于 SAM 的功能请求 github 问题以使用 SAM 实现层构建。


T实际上现在可以通过在 SAM 模板文件中创建一个虚拟函数以及一个层条目来让 SAM 也构建您的层,从而对其进行黑客攻击,并使层 ContentUri 入口指向为函数创建的 .aws-sam 构建目录。

这种方法实际上似乎非常适合现在扭曲 SAM 来为您构建图层。

我不确定最近是否发生了变化,但我可以毫无问题地执行此操作。我的模板文件和结构与 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

我让它与以下脚本一起工作。使用 Ubuntu 18 和 CodeBuild

进行测试

它 pip 安装层的要求 .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 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

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 which it tries to build layers before functions. It's expected to have it fixed on the next release (PR opened already).

相对于这些较旧的答案,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