简体   繁体   中英

AWS multiple lambdas with same CodeUri

I have multiple lambdas in my AWS serverless project and they all have the same CodeUri which is a folder in my project. For example, they all point to src/ .

In the basic usage, or at least how I use it, the sam build option create a folder for each lambda. All of the folders contain the same code. Then, when running sam deploy each zip is uploaded to S3. The zips are all the same and it takes a lot of redundent time to upload them all.

Is there an option "to tell" sam to upload it only once?

I saw that I can build the zip manually, then uploading it to S3. How can I then set the uri in the CodeUri of the lambdas? Should I do it using external parameter or there is dedicated way to signal it?

Thank you

After hard effort, using David Conde's idea, I managed to find some solution for it. What we want to achieve is uploading the lambda's zip (with all of it's dependencies) once and point all the lambdas to use this zip.

This process is seperated into couple of steps which I'll try to describe in much details as I can. Some of them might not be relevant exactly for your case.

General idea

The general idea is to create a layer which contains the code we want to upload once. Then, for each lambda, specify it uses this layer. Each lambda will have it handler points to somewhere in the source directory. Hence, running code "from the layer". But. we must specify code for the lambda to run/attach a zip - even if it's not what going to run, To skip that. we are going to attach it an "empty" code.

Build folder

First, create a build folder where we are going to work, for example: mkdir -p.build/

In addition, define the following variables:

  • s3_bucket="aaaaaaaa"
  • s3_prefix="aaaaaaaa"
  • s3_lambda_zip_suffix="$s3_prefix/lambda.zip"
  • s3_lambda_zip="s3://$s3_bucket/$s3_lambda_zip_suffix"

Creating the source zip

When lambda is unzipped, it's content is written to the working directory. When a layer is unzipped, it is unzipped into /opt as documented in AWS. Because our lambda needs to find our source code, which is "a depndencie" it needs to find it under /opt . To achieve it, we need it to be unzipped into /opt/python . We can do that by zipping python/... into a zip file.

First, we create the folder we will install the dependencies into the python folder:

  • mkdir -p.build/lambda_zip/python
  • pip3 install -q --target.build/lambda_zip/python -r requirements.txt

Then we zip it:

  • pushd.build/lambda_zip/ > /dev/null
  • zip --quiet -r./lambda.zip./python
  • popd > /dev/null

Now, you probably want to add your src direcory:

  • zip --quiet -r.build/lambda_zip/lambda.zip src

#Uploading to S3 Now, we have to upload the zip into S3 for our lambdas to load it.

  • aws s3 cp ".build/lambda_zip/lambda.zip" $s3_lambda_zip_path

Adding layer to template.yaml

Now, we need to add the layer into our template.yaml file, you can copy the following code after you read at AWS documentation:

Parameters:
  LambdaCodeUriBucket:
    Type: String
  LambdaCodeUriKey:
    Type: String

Resources:

  OnUpHealthLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      CompatibleRuntimes:
      - python3.8
      Content:
        S3Bucket: !Sub '${LambdaCodeUriBucket}'
        S3Key: !Sub '${LambdaCodeUriKey}'

Create empty zip for the lambdas

Cloudformation must upload zip for lambdas, so we want it to create an empty zip. But it scans the dependencies from the requirements.txt file in the directory the same as the one of template.yaml . And we want it to upload something empty. Hence it must be in another folder. To solve it, I copy the template.yaml to an empty directory and add empty requirements.txt file. After that, we can run sam build and sam deploy as usuall. Notice that we must pass it LambdaCodeUriBucket and LambdaCodeUriKey :

#create "empty" environment for the template to be built in
mkdir -p .build/empty_template
cp template.yaml .build/empty_template
pushd .build/empty_template > /dev/null
touch requirements.txt
sam build --template template.yaml
sam deploy \
    --template-file .aws-sam/build/template.yaml \
    --capabilities "CAPABILITY_IAM" \
    --region $region \
    --s3-bucket $s3_bucket \
    --s3-prefix $s3_prefix \
    --stack-name $stack_name \
    --parameter-overrides LambdaCodeUriBucket=$s3_bucket LambdaCodeUriKey=$s3_lambda_zip_suffix
popd > /dev/null

Notice that although we copied the template.yaml and called sam build on the new one, we already uploaded to s3 the zip file.

Important thing you must do is specify . as the CodeUri for your lambdas. Because they now use the "empty zip".

In the future, we will be able to do:

InlineCode: |
    def handler(event, context):
        pass

And not specify folder . .

But, currently sam doesn't support inline code for python3.8 hence we use . . Anyway you will have to move it to seperate folder to remove it's dependencies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM