How to create a new version of a Lambda function using CloudFormation?

后端 未结 11 646
清歌不尽
清歌不尽 2020-12-08 03:44

I\'m trying to create a new version of a Lambda function using CloudFormation.

I want to have multiple versions of the same Lambda function so that I can (a) point a

相关标签:
11条回答
  • 2020-12-08 04:38

    Answer updated for February 2018

    You can use AWS SAM (Serverless Application Model), and its sam package and sam deploy commands to update Lambda. They are similar to aws cloudformation package and aws cloudformation deploy commands, but also let you update Lambda versions automatically.

    SAM can package your code (or take ZIP package you created otherwise), upload it to S3, and update the $LATEST Version of the Lambda from it. (If this is all you need, this can also be done with aws cloudformation, without SAM; code examples are same as below, but only use CloudFormation's standard declarations). Then, with SAM, if configured accordingly, you can also automatically publish a Version and update an Alias to point to it. It can also, optionally, use AWS CodeDeploy to gradually move traffic from previous Version to new one, and rollback in case of errors. All this is explained in Safe Lambda deployments.


    Technically, the idea is that every time you update the stack, you need your AWS::Lambda::Function's Code to point to the new package in S3. This will ensure that when you update the stack, Lambda's $LATEST version will be updated from the new package. Then, you can also automate the publishing of new Version and switch an Alias to it.

    For it, create a SAM template, which is similar to (a superset of) CloudFormation template. It may include SAM-specific declarations, like the one for AWS::Serverless::Function below. Point the Code to source code directory (or a prepackaged ZIP), and set the AutoPublishAlias property.

    ...
    
    MyFunction:
        Type: AWS::Serverless::Function
        Properties:
          ...  # all usual CloudFormation properties are accepted 
          AutoPublishAlias: dev  # will publish a Version and create/update Alias `dev` to point to it
          Code: ./my/lambda/src
    ...
    

    Run:

    $ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket my-bucket
    

    This packages source directory contents as a ZIP (if Code is not a ZIP already), uploads it to S3 under new autogenerated key, and generates final CloudFormation template to packaged.yaml, putting for you the proper Code reference into it; like this:

    ...
    MyFunction:
        Properties:
          Code:
            S3Bucket: my-bucket
            S3Key: ddeeaacc44ddee33ddaaee223344
    ...
    

    Now you can use generated packaged.yaml with SAM, to create function Version:

    sam deploy --template-file packaged.yaml --stack-name my-stack [--capabilities ...]
    

    This will update Lambda's $LATEST version, and, if AutoPublishAlias was defined, publish it as a new Version and update the Alias to point to the newly published Version.

    See the examples in SAM GitHub repo for a complete template code.

    0 讨论(0)
  • 2020-12-08 04:40
    1. We can make a Lambda deployment package;
    2. Pass the Lambda package with the version as one of Cloud Formation parameters, e.g. "LambdaPakcageNameWithVersion";
    3. Use "LambdaPakcageNameWithVersion" as the Lambda code s3 key;
    4. The new Lamdba package will be deployed when running the aws-cli command to update the cloudformation stack or running CI/CD pipeline.

      MyLambda:
        Type: AWS::Lambda::Function
        Properties:
          Role: LambdaRole
          Code:
            S3Bucket: LambdaPackageS3Bucket
            S3Key: !Sub "${LambdaPakcageNameWithVersion}"
          FunctionName: LambdaFunctionName
          Handler: lambda_function.lambda_handler
          Runtime: python3.6
          Timeout: 60

    0 讨论(0)
  • 2020-12-08 04:41

    Unfortunately, this is not possible to do using CloudFormation. You will need to add new AWS::Lambda::Version sections in your CloudFormation template for each version.

    The closest solution would be to create .erb templates and have it generate CloudFormation templates with all the versions.

    0 讨论(0)
  • 2020-12-08 04:42

    This is a bit of a hack, and depends on using gitlab-ci (or something similar), but I find passing the commit hash into a cloudformation template (via the template's parameters) very useful.

    (It's a bit like @Jerry 's answer, but using the commit hash.)

    In this case you could do something like:

    Have a parameter in your template for the commit hash, e.g.:

    AWSTemplateFormatVersion: '2010-09-09'
    Description: Template for Lambda Sample.
    Parameters:
      ciCommitSha:
        Type: String
      s3Bucket:
        Type: String
      ...
    

    You can then reference this in the lambda resource, like this:

      CFNLambda:
        Type: AWS::Lambda::Function
        Properties:
          FunctionName: cfn_trigger_fn
          Description: lambda which gets triggered by cloudformation
          Runtime: python3.7
          Code:
            S3Bucket: !Ref s3Bucket
            S3Key: !Join [ ".", [ !Ref ciCommitSha, "zip"]]
          Handler: function.handler
          ...
    

    Your ci pipeline then needs to look something like (assuming you call your cloudformation template stack-template.yaml):

    variables:
      REGION: us-east-1
      S3_BUCKET_NAME: my-bucket
    
    stages:
     - build
     - push
     - deploy
    
    build-package:
      stage: build
      script:
        - some code to produce a deployment package called function.zip
      artifacts:
        name: deployment_package
        paths:
          - function.zip
    
    
    push-code:
      stage: push
      script:
        - aws s3 cp function.zip s3://$S3_BUCKET_NAME/$CI_COMMIT_SHA.zip
    
    deploy-trigger-stack:
      stage: deploy
      script: 
          - aws cloudformation deploy
                --template-file stack-template.yaml
                --stack-name my-stack
                --region $REGION
                --no-fail-on-empty-changeset
                --capabilities CAPABILITY_NAMED_IAM
                --parameter-overrides
                ciCommitSha=$CI_COMMIT_SHA
                s3Bucket=$S3_BUCKET_NAME
    

    You can use this technique for triggering cfn-init on EC2 metadata as well..

    0 讨论(0)
  • 2020-12-08 04:44

    This post is out-of-date. I am updating it here so others can see the correct solution for versioning Lambdas as of 06-09-2020, without the need for extra custom versioning Lambdas.

    This:

    Description: Lambda Example
    Resources:
      Function:
        Type: AWS::Lambda::Function
        Properties:
          Handler: index.handler
          Code:
            ZipFile: |
              'Example Code';
          Runtime: nodejs12.x
          Timeout: 5
    

    Becomes this:

    Description: Lambda Example
    Transform: AWS::Serverless-2016-10-31
    Resources:
      Function:
        Type: AWS::Serverless::Function
        Properties:
          AutoPublishAlias: live
          Handler: index.handler
          InlineCode: |
            'Example Code';
          Runtime: nodejs12.x
          Timeout: 5
    

    The Transform: allows AWS::Serverless::Function inside of a CloudFormation template which in turn supports lambda versioning.

    Don't let the dated "Best Answer" above - built for that persons book - throw you down a rabbit hole like I did.

    You're welcome.

    0 讨论(0)
提交回复
热议问题