Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SAM build - does it also build layers?

I'm new to both lambda's and also SAM - so if I've screwed anything simple up don't yell :D.

Summary: I can't get sam build to build a layer specified in template.yaml, it only builds the lambda function.

Background: I'm trying to build a lambda function in python3.7 that uses the skimage (scikit-image) module. To do that, I'm trying to use SAM to build and deploy it all. ...this is working

I'm trying to deploy the scikit-image module as a layer (and also build with SAM), rather than having it included in the lambda function direction ...this isn't working


As a start, I'm simply extending the standard SAM Hello World app.

I've got skimage working by simply add it to requirements.txt , then using sam build -u, then manually removing the numpy/scipy dependencies from the built package directory (I've got the AWS scipy/numpy layer included).

(I added import numpy, scipy.ndimage and skimage.draw to the standard hello world app, and included some test function calls to each)

requirements.txt:

requests
scikit-image

After that, everything works fine (running locally and/or on AWS).


However, I'd now like to move the skimage module out of my app and into a new custom layer (I'd like to have skimage in a layer to re-use for a few functions)

To set that up, I've created a dependencies directory and moved requirements.txt into there (leaving empty requirements.txt in the app directory). I then updated template.yaml to also specify the new layer:

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

directory structure:

▾ dependencies/                
    requirements.txt (responses and scikit-image)          
▸ events/                      
▾ hello_world/                 
    __init__.py                
    app.py                     
    requirements.txt (now empty)          
▸ tests/                       
  README.md                    
  template.yaml                 

However, when I run sam build -u with that template file, nothing gets built for the layer specified in ./dependencies: SkimageLayer in the template.yml file. However the HelloWorldFunction still gets built correctly (now of course without any included modules)

like image 930
Richard Avatar asked Oct 15 '19 20:10

Richard


People also ask

What does AWS Sam build do?

AWS SAM CLI lets you locally build, test, and debug serverless applications defined by SAM templates. Using the sam build command, you can easily create deployment artifacts that target AWS Lambda's execution environment. This enables the functions you build locally to run in a similar environment in the cloud.

Does Sam deploy build?

Builds a serverless application and prepares it for subsequent steps in your workflow, like locally testing the application or deploying it to the AWS Cloud.

What does Sam package do?

Packages an AWS SAM application. This command creates a . zip file of your code and dependencies, and uploads the file to Amazon Simple Storage Service (Amazon S3). AWS SAM enables encryption for all files stored in Amazon S3.


2 Answers

Since SAM Cli version v0.50.0, it is building layers as part of sam build.

Design document could be a good starting point to understand how it works.

Basically you have to set a custom BuildMethod with your lambda's target runtime:

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

Warning: For compiled language as Java, it 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).

like image 143
gustahrodrigues Avatar answered Nov 03 '22 15:11

gustahrodrigues


Quick answer - No, currently SAM does not build layers you define in a SAM template.yaml file.

It will only build any functions you define.

However (curiously) it will package (upload to S3) and deploy (setup within AWS, assign ARN so it can be used etc) any layers you define.


There is a feature request on the SAM github issues to implement layer building with SAM.


This can actually be hacked right now to get SAM to build your layers as well, by creating a dummy function in your SAM template file, as well as a layer entry, and having the layer ContentUri entry point to the .aws-sam build directory that gets created for the function.

See my post here on that.

That approach actually seems to work pretty well for twisting SAM right now to build your layers for you.

like image 42
Richard Avatar answered Nov 03 '22 14:11

Richard