SAM doesn't package dependencies

0

Hi,

I am new to SAM and perhaps I am asking something obvious here. I need to deploy Py lambda. When I am trying to use SAM from command line with "sam build", it creates a .aws-sam/build with the code in it, and also .aws-sam/deps/900e2021-84ce-4093-a603-5ef231a0f4d3 with all dependencies in it as well. Now, when I use "sam package", it packages only the code from the build directory and dependencies from 900e2021-84ce-4093-a603-5ef231a0f4d3 separately. Both files are being uploaded then into the S3, but only one with the code is deployed. However, if I do it through the the PyCharm, it doesn't separate them - all tree is packaged and deployed as one, hence the lambda is functional. It seems that with two packages Lambda is installation is prepped for layered approach where the second 900e2021-84ce-4093-a603-5ef231a0f4d3 part is a virtual environment deployed separately, but in my case it is redundant approach as, for now, I only have one lambda and will not have a mass deployment. Also, isn't it more expensive to run in layers and not as one code because your executing twice + have cross-layer execution time added up? Did anyone see this before?

Thanks in advance, Best regards Matvey Teplov

asked 8 months ago743 views
4 Answers
0

Hi Matvey,

I understand that when you deploy Py lambda using SAM from command line with "sam build" it creates a .aws-sam/build with the code in it, and also .aws-sam/deps/900e2021-84ce-4093-a603-5ef231a0f4d3 with all dependencies in it as well. When using "sam package", it packages only the code from the build directory and dependencies from [1] separately. Both files are then being uploaded into S3 but only once the code is deployed. When doing the same action in PyCharm it does not seperate them i.e. all tree is packaged and deployed as one hence the Lambda is functional. This seems that the the two packages Lambda is installation is geared towards a layered approach whereas in the second part is a virtual environment deployed separately. Also you would essentially like to understand the cost of using Lambda layer as an approach both from a monetary perspective as well as a runtime execution level. Please feel free to correct if there is any misunderstanding.

Let us first have a look at the cost of using Lambda from both monetary and runtime execution level. From a cost level. "There is no cost for storing the layer -- or using the layer. However, the layer storage does take up space in your total Lambda storage" [2]. In terms of performance let us take two identical lambda functions written in python3.8 using one without layer (directly packaging the function with its dependencies) and one without packaging it dependencies meaning using a layer instead. This test will use the requests library version "2.22.0". [3] and the code [4] will be in Python3.8 both tests will be conducted with cold starts. [5] The code is designed to ping 2 websites at random and get a response. Please note Lambda is a highly distributed system with various components so test results may change when testing on your side.

TEST 1 - Lambda function without layer

Duration: 78.77 ms Memory Size: 128 MB Max Memory Used: 49 MB Init Duration: 404.33 ms

TEST 2 - Lambda function with layer

Duration: 448.31 ms Memory Size: 128 MB Max Memory Used: 49 MB Init Duration: 207.40 ms

It is quite evident that TEST 1 produced the less duration time so that can conclude using the above experiment that yes adding a layer does give a trade off in duration. However there are advantages to using Lambda layers as outlined here. [6]

As for the part about "Now, when I use "sam package", it packages only the code from the build directory and dependencies from 900e2021-84ce-4093-a603-5ef231a0f4d3 separately." I tested this using SAM but keeping my directory structure as the image below. I ran the following command inside the package "sam-app-sam-test":

Enter image description here

a. sam package --s3-bucket<bucket_name> --output-template-file packaged-template.yaml b. sam deploy --template-file packaged-template.yaml --stack-name <stack_name> --capabilities CAPABILITY_IAM (stack name came from using helloworldexample when running "sam init" and choosing helloworld example in ZIP format)

The above gave me a single packge in S3 named a2457d556ccffadd639b45c7604684f2. When I uploaded it in Lambda I got the following (refer to image below).

Enter image description here

Hence, I am not sure how the original package looked for you when using "sam build" and "sam package". Additionally, as I don't have access and knowledge of how the PyCharm IDE works under the hood with SAM I am unable to comment on why PyCharm doesn't seperate the packages. Hence, I kindly request that you please create a case to AWS in order to facilitate a detailed response. This will allow us to understand the PyCharm directory structure and how it works with SAM as well as how the directory structure looks from the command line. I you want SAM to use a layer here is structure. [7] The structure I am using is as follow. [8]

As always, you are welcome to add any questions related to this re:Post.

References:

[1] 900e2021-84ce-4093-a603-5ef231a0f4d3

[2] https://repost.aws/questions/QUoSWSKhamS1-ZvDWao3drKQ/lambda-layer-costs

[3] https://pypi.org/project/requests/2.22.0/

[4]

import random
import requests
def lambda_handler(event, context):
    websites = [
        "http://example.com  ",
        "http://amazon.com  ",
        # Add more websites as needed
    ]
    random_website = random.choice(websites)
    try:
        response = requests.get(random_website)
        return {
            'statusCode': response.status_code,
            'body': f'Response from {random_website}: {response.text}'
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': f'Error pinging {random_website}: {str(e)}'
        }

[5] https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/

[6] https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html

[7] https://docs.aws.amazon.com/lambda/latest/dg/layers-sam.html

[8]

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: 'sam-app-sam-test

Sample SAM Template for sam-app-sam-test

' Globals: Function: Timeout: 3 MemorySize: 128 Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: s3://sampacakgeapptest/a2457d556ccffadd639b45c7604684f2 Handler: app.lambda_handler Runtime: python3.7 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get Metadata: SamResourceId: HelloWorldFunction Outputs: HelloWorldApi: Description: API Gateway endpoint URL for Prod stage for Hello World function Value: Fn::Sub: https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/ HelloWorldFunction: Description: Hello World Lambda Function ARN Value: Fn::GetAtt: - HelloWorldFunction - Arn HelloWorldFunctionIamRole: Description: Implicit IAM Role created for Hello World function Value: Fn::GetAtt: - HelloWorldFunctionRole - Arn

AWS
answered 8 months ago
0

You have the deps folder because you probably used sam sync. When using it, sam packages all dependencies in a layer so that function changes will be faster as the dependencies are packages in a different place.

You do not need to use sam package, sam deploy does it automatically as part of the deployment process.

profile pictureAWS
EXPERT
Uri
answered 8 months ago
0

Hi,

I have tried to package and deploy the way you described with the majority of my parameters coming from the samconfig.toml file and also from the command line after. It ended up with incomplete installation and lambda not being able to run. Here is my config:

version = 0.1

[default]
[default.global.parameters]
stack_name = "jwt-auth-20-1"
profile = "abcd"
region="eu-west-1"
s3_bucket = "abcd"
capabilities = "CAPABILITY_IAM"
template_file = "#####/JTW-authorizer/template.yaml"
# resolve_s3 = true

[default.build.parameters]
cached = false
parallel = true

[default.validate.parameters]
lint = true

[default.deploy.parameters]
confirm_changeset = false

[default.package.parameters]

[default.sync.parameters]
watch = false

[default.local_start_api.parameters]
warm_containers = "EAGER"

[default.local_start_lambda.parameters]
warm_containers = "EAGER"

Resulted in the following YAML:


AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'JTW-authorizer
Globals:
  Function:
    Timeout: 3
    MemorySize: 128
Resources:
  JWTFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://abcd/e6b2c55e2d49e6608e98515aff35fbdf
      Handler: lambda_function.lambda_handler
      Runtime: python3.8
      Architectures:
      - x86_64
      Environment:
        Variables:
          PRINCIPAL: 12345678
          SECRET_KEY: 12323434534
    Metadata:
      SamResourceId: JWTFunction
Outputs:
  LambdaAuthFunction:
    Description: JWT Lambda Function ARN
    Value:
      Fn::GetAtt:
      - JWTFunction
      - Arn

Enter image description here

The log:

mteplov@scorpio:~/PycharmProjects/JTW-authorizer$ sam package --force-upload --debug
2023-08-21 15:17:08,517 | Config file location: JTW-authorizer/samconfig.toml                                                                                                                                              
2023-08-21 15:17:08,519 | Loading configuration values from [default.['package'].parameters] (env.command_name.section) in config file at 'JTW-authorizer/samconfig.toml'...                                               
2023-08-21 15:17:08,519 | Configuration values successfully loaded.                                                                                                                                                                                      
2023-08-21 15:17:08,520 | Configuration values are: {'stack_name': 'jwt-auth-20-1', 'profile': 's3-cloudformation-push', 'region': 'eu-west-1', 's3_bucket': 'abcd', 'capabilities': 'CAPABILITY_IAM', 'template_file': 'JTW-authorizer/template.yaml'}                                                                                                                                                 
2023-08-21 15:17:08,522 | Using SAM Template at JTW-authorizer/template.yaml                                                                                                                                               
2023-08-21 15:17:08,550 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                                                                                                                     
2023-08-21 15:17:08,552 | Using config file: samconfig.toml, config environment: default                                                                                                                                                                 
2023-08-21 15:17:08,552 | Expand command line arguments to:                                                                                                                                                                                              
2023-08-21 15:17:08,553 | --template_file=JTW-authorizer/template.yaml --force_upload --s3_bucket=abcd                                                                                                
2023-08-21 15:17:08,567 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:17:08,583 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:17:08,584 | 0 stacks found in the template                                                                                                                                                                                                 
2023-08-21 15:17:08,584 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:17:08,592 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:17:08,743 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:17:08,744 | Sam customer defined id is more priority than other IDs. Customer defined id for resource JWTFunction is JWTFunction                                                                                                           
	Uploading to e6b2c55e2d49e6608e98515aff35fbdf  3003 / 3003  (100.00%)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'JTW-authorizer

  '
Globals:
  Function:
    Timeout: 3
    MemorySize: 128
Resources:
  JWTFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://abcd/e6b2c55e2d49e6608e98515aff35fbdf
      Handler: lambda_function.lambda_handler
      Runtime: python3.8
      Architectures:
      - x86_64
      Environment:
        Variables:
          PRINCIPAL: 12345678
    Metadata:
      SamResourceId: JWTFunction
Outputs:
  LambdaAuthFunction:
    Description: JWT Lambda Function ARN
    Value:
      Fn::GetAtt:
      - JWTFunction
      - Arn

2023-08-21 15:17:09,007 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                                                                                                                     
2023-08-21 15:17:09,010 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                                                                                                                     
2023-08-21 15:17:09,012 | Unable to find Click Context for getting session_id.                                                                                                                                                                           
mteplov@scorpio:~/PycharmProjects/JTW-authorizer$ sam deploy --debug
2023-08-21 15:21:51,513 | Config file location: /JTW-authorizer/samconfig.toml                                                                                                                                              
2023-08-21 15:21:51,515 | Loading configuration values from [default.['deploy'].parameters] (env.command_name.section) in config file at '/JTW-authorizer/samconfig.toml'...                                                
2023-08-21 15:21:51,515 | Configuration values successfully loaded.                                                                                                                                                                                      
2023-08-21 15:21:51,516 | Configuration values are: {'stack_name': 'jwt-auth-20-1', 'profile': 'abcd, 'region': 'eu-west-1', 's3_bucket': 'abcd, 'capabilities': 'CAPABILITY_IAM', , 'template_file': 'JTW-authorizer/template.yaml', 'confirm_changeset': False}                                                                                                                     
2023-08-21 15:21:51,518 | Using SAM Template at JTW-authorizer/template.yaml                                                                                                                                               
2023-08-21 15:21:51,535 | Using config file: samconfig.toml, config environment: default                                                                                                                                                                 
2023-08-21 15:21:51,536 | Expand command line arguments to:                                                                                                                                                                                              
2023-08-21 15:21:51,536 | --template_file=/JTW-authorizer/template.yaml --fail_on_empty_changeset --on_failure=ROLLBACK --stack_name=jwt-auth-20-1 --s3_bucket=abcd --capabilities=['CAPABILITY_IAM']                                                                                                                                                                                           
2023-08-21 15:21:51,668 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:21:51,677 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:21:51,678 | 0 stacks found in the template                                                                                                                                                                                                 
2023-08-21 15:21:51,678 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:21:51,686 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:21:51,755 | There is no customer defined id or cdk path defined for resource JWTFunction, so we will use the resource logical id as the resource id                                                                                        
2023-08-21 15:21:51,756 | Sam customer defined id is more priority than other IDs. Customer defined id for resource JWTFunction is JWTFunction                                                                                                           
2023-08-21 15:21:51,961 | File with same data already exists at e6b2c55e2d49e6608e98515aff35fbdf, skipping upload                                                                                                                                        

	Deploying with following values
	===============================
	Stack name                   : jwt-auth-20-1
	Region                       : eu-west-1
	Confirm changeset            : False
	Disable rollback             : False
	Deployment s3 bucket         : abcd
	Capabilities                 : ["CAPABILITY_IAM"]
	Parameter overrides          : {}
	Signing Profiles             : {}

Initiating deployment
=====================

2023-08-21 15:21:51,986 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:21:51,993 | Sam customer defined id is more priority than other IDs. Customer defined id for resource JWTFunction is JWTFunction                                                                                                           
2023-08-21 15:21:51,994 | 0 stacks found in the template                                                                                                                                                                                                 
2023-08-21 15:21:51,994 | No Parameters detected in the template                                                                                                                                                                                         
2023-08-21 15:21:52,001 | Sam customer defined id is more priority than other IDs. Customer defined id for resource JWTFunction is JWTFunction                                                                                                           
2023-08-21 15:21:52,002 | 1 resources found in the stack                                                                                                                                                                                                 
	Uploading to d595a846bbc48202695c19e4edc7a209.template  726 / 726  (100.00%)


Waiting for changeset to be created..

CloudFormation stack changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                                                     LogicalResourceId                                             ResourceType                                                  Replacement                                                 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Also, I don't see any layer with the dependencies being created - only insights and code guru code are in.

Any ideas?

Regards

answered 8 months ago
0

Interestingly enough, via PyCharm, deployment also has stopped with the new template.yaml generated - also it only deployed the code. I recovered from the GIT, and from what I see, there is one line real difference: via SAM CLI from the generated template, it was: Properties: CodeUri: s3://abcd/e6b2c55e2d49e6608e98515aff35fbdf in Pycharm it is: Properties: CodeUri: jwt_handler/

I guess, somehow it actually deploys directly and not via S3. Can this be?

answered 8 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions