7

我对 lambda 和 SAM 都是新手 - 所以如果我搞砸了任何简单的事情,请不要大喊:D。

摘要:我无法sam build构建中指定的层template.yaml,它只构建 lambda 函数。

背景:我正在尝试在 python3.7 中构建一个使用 skimage ( scikit-image) 模块的 lambda 函数。为此,我正在尝试使用 SAM 来构建和部署它。 ...这是工作

我正在尝试将 scikit-image 模块部署为一个层(并且还使用 SAM 构建),而不是将其包含在 lambda 函数方向 中......这不起作用


首先,我只是扩展了标准的 SAMHello World应用程序。

我只需将 skimage 添加到requirements.txt,然后使用sam build -u,然后从构建的包目录中手动删除 numpy/scipy 依赖项(我已经包含了 AWS scipy/numpy 层),就可以让 skimage 正常工作。

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

要求.txt:

requests
scikit-image

之后,一切正常(在本地和/或 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                 

但是,当我使用该模板文件运行时,不会为 template.yml 文件中:中sam build -u指定的层构建任何内容。但是仍然可以正确构建(现在当然没有任何包含的模块)./dependenciesSkimageLayerHelloWorldFunction

4

5 回答 5

5

由于SAM Cli 版本 v0.50.0,它正在构建层作为sam build.

设计文档可能是了解其工作原理的良好起点。

基本上,您必须BuildMethod使用 lambda 的目标运行时设置自定义:

MyLayer:
Type: AWS::Serverless::LayerVersion
Properties:
  ContentUri: my_layer
  CompatibleRuntimes:
    - python3.8
Metadata:
  BuildMethod: python3.8 (or nodejs8.10 etc..)

警告:对于像 Java 这样的编译语言,它有一个问题是它试图在函数之前构建层。预计将在下一个版本中修复(PR 已打开)。

于 2020-06-12T11:44:46.653 回答
2

快速回答 -,目前 SAM 不构建 在 SAMtemplate.yaml文件中定义的层。

只会构建您定义的任何功能

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


在 SAM github 问题上有一个功能请求,以使用 SAM 实现层构建。


实际上,现在可以通过在 SAM 模板文件中创建一个虚拟函数以及一个层条目,并将层 ContentUri 入口点指向 .aws-sam 构建来让 SAM 构建您的层。为函数创建的目录。

请参阅我的帖子。

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

于 2019-10-16T07:46:30.200 回答
1

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

于 2020-11-16T15:22:11.050 回答
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
于 2020-01-07T21:05:29.013 回答
0

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

它 pip install 的层对.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
于 2020-02-18T00:47:03.403 回答