AWS and other interesting stuff

AWS Lambda And Serverless - Part 1

· by Steve Hogg · Read in about 4 min · (807 Words)
AWS AWS Lambda Serverless Blue/Green Deployment AB Testing Feature Flags

Lambda Versions And Aliases With Blue/Green Deployment And AB Testing

This blog post is my attempt to understand how Lambda Versions and Aliases can be used for Blue/Green Deployment or AB Testing.

  • Versions
    • New versions of functions can be created. This makes a copy of the $LATEST version with an incremented version number.
  • Aliases
    • Can be set for versions, and moved between versions
  • Both Versions and Aliases can be used as qualifiers when invoking functions (see cli commands below)

For Blue / Green deployments, or AB Testing code can be set to invoke qualified functions: e.g.

  • Blue / Green
    • Switch a blue (production) alias and green (pre-production) alias between function versions
    • Rollback by changing the alias back
  • AB Testing
    • Have different groups of users use different aliases

This slideshow has an overview of how aliases can be used to release versions:

Feature Flags

Modern best practice is to separate code deployment from feature release. This is done using “Feature Flags”.

When code and feature deployment happen at the same time, you deploy new code that has new features enabled. If new features cause problems in production, you need a quick way to roll them back. When code and features are tightly coupled blue/green deployment allows you to rollback quickly.

Instead, you can deploy code that has new features disabled by default in the configuration. You can then enable/disable features independently of the code by updating the configuration; you can rollback changes without reverting back to the old code deployment. This architecture also allows for AB Testing of features by enabling features for a subset of users.

Google’s Firebase Remote Config is an good example of a system for Feature Flags and AB Testing.

Using Blue/Green deployment is still a good idea in this situation as their may be problems with the deployed code e.g. updates to existing feature code.

Lambda Version And Alias CLI Examples

$ aws lambda publish-version --function-name myHelloWorld
$ aws lambda list-versions-by-function --function-name myHelloWorld --query 'Versions[*].{Version:Version,FunctionName:FunctionName}'
 [
     {
         "Version": "$LATEST",
         "FunctionName": "myHelloWorld"
     },
     {
         "Version": "1",
         "FunctionName": "myHelloWorld"
     }
 ]

Invoke Different Versions

$ aws lambda invoke --function-name myHelloWorld --qualifier '$LATEST' out.txt && cat out.txt && echo
{
    "StatusCode": 200
}
"Hello World 2!"
$ aws lambda invoke --function-name myHelloWorld --qualifier 1 out.txt && cat out.txt && echo
{
    "StatusCode": 200
}
"Hello World!"

Create Aliases

$ aws lambda create-alias --function-name myHelloWorld --function-version 1 --name v1-0
{
    "AliasArn": "arn:aws:lambda:ap-southeast-2:798269391015:function:myHelloWorld:v1-0",
    "FunctionVersion": "1",
    "Name": "v1-0",
    "Description": ""
}
$ aws lambda create-alias --function-name myHelloWorld --function-version '$LATEST' --name v1-1
{
    "AliasArn": "arn:aws:lambda:ap-southeast-2:798269391015:function:myHelloWorld:v1-1",
    "FunctionVersion": "$LATEST",
    "Name": "v1-1",
    "Description": ""
}

Invoke Functions Using Aliases

$ aws lambda invoke --function-name myHelloWorld --qualifier v1-0 out.txt && cat out.txt && echo
{
    "StatusCode": 200
}
"Hello World!"
$ aws lambda invoke --function-name myHelloWorld --qualifier v1-1 out.txt && cat out.txt && echo
{
    "StatusCode": 200
}
"Hello World 2!"

Versions And Aliases With Serverless

Serverless has an alias plugin that allow you to have multiple aliases per stage: https://github.com/HyperBrain/serverless-aws-alias

Deploy the “master alias”

$ serverless deploy

This creates the function with the Serverless stage name as the alias e.g. prod

You can deploy an alias as follows: $ serverless deploy --alias 1v0v0

I changed the message in the code (adding !!!), and deployed it as a new alias: $ serverless deploy --alias 1v0v1

Both functions are now accessible via the API Gateway:

$ curl -s https://db2gybzoij.execute-api.ap-southeast-2.amazonaws.com/1v0v0/hello | jq '. | {message}'
{
  "message": "Hello version 1v0v0"
}
$ curl -s https://db2gybzoij.execute-api.ap-southeast-2.amazonaws.com/1v0v1/hello | jq '. | {message}'
{
  "message": "Hello version 1v0v1!!!"
}

Notes:

  • The second message has exclamation marks as expected
  • Serverless has the concept of “stages” e.g. test, dev, prod
  • API Gateway also has a “stages” concept. In this case, it is being used to indicate the Serverless alias being used. It is a bit confusing, but APIG “stage” means “version”.

Setup Initial Blue / Green Aliases

$ version1v0v0=$(aws lambda list-aliases --function-name my-service-prod-hello --query 'Aliases[?Name==`1v0v0`].FunctionVersion' --output text)
$ aws lambda create-alias --function-name my-service-prod-hello --function-version=$version1v0v0 --name blue
$ version1v0v1=$(aws lambda list-aliases --function-name my-service-prod-hello --query 'Aliases[?Name==`1v0v1`].FunctionVersion' --output text)
$ aws lambda create-alias --function-name my-service-prod-hello --function-version=$version1v0v1 --name green
$ aws lambda invoke --function-name my-service-prod-hello --qualifier blue out.txt ; cat out.txt; echo; rm -f out.txt
{
    "StatusCode": 200
}
{"statusCode":200,"body":"{\"message\":\"Hello version 1v0v0\",\"input\":{}}"}
$ aws lambda invoke --function-name my-service-prod-hello --qualifier green out.txt ; cat out.txt; echo; rm -f out.txt
{
    "StatusCode": 200
}
{"statusCode":200,"body":"{\"message\":\"Hello version 1v0v1!!!\",\"input\":{}}"}

Switch To New Blue

$ aws lambda update-alias --function-name my-service-prod-hello --function-version=$version1v0v1 --name blue
$ aws lambda invoke --function-name my-service-prod-hello --qualifier blue out.txt ; cat out.txt; echo; rm -f out.txt
{
    "StatusCode": 200
}
{"statusCode":200,"body":"{\"message\":\"Hello version 1v0v1!!!\",\"input\":{}}"}

You can then also update the green alias

Revert To Old Blue

$ aws lambda update-alias --function-name my-service-prod-hello --function-version=$version1v0v0 --name blue
$ aws lambda invoke --function-name my-service-prod-hello --qualifier blue out.txt ; cat out.txt; echo; rm -f out.txt
{
    "StatusCode": 200
}
{"statusCode":200,"body":"{\"message\":\"Hello version 1v0v0\",\"input\":{}}"}

Comments