How to Perform Serverless Canary Release on Lambda via Terraform?

Working as serverless is the fashion these days. However some problems are still there. Deployment!

Amazon Web Services has introduced canary release for Lambda functions. So, we will be able to rolling out new software versions in production by slowly.

Let’s get started!

exports.handler = async(event) => {
const response = {
statusCode: 200,
body: JSON.stringify("V1")
};
return response;
};

Terraform configuration for the Lambda function:


data "archive_file" "blog_endpoint_zip" {
type = "zip"
source_file = "index.js"
output_path = "blog_endpoint.zip"
}
resource "aws_lambda_function" "blog_endpoint" {
filename = "blog_endpoint.zip"
function_name = "blog_endpoint"
role = "${data.aws_iam_role.the_role.arn}"
handler = "index.handler"
source_code_hash = "${data.archive_file.blog_endpoint_zip.output_base64sha256}"
runtime = "nodejs8.10"
publish = true
}
data "aws_iam_role" "the_role" {
name = "your_role_name_here"
}
output "version number" {
value = "${aws_lambda_function.blog_endpoint.version}"
}

I didn’t write role adding and VPC configurations for the sake of simplicity.

When you run the Terraform then you will get an output like this:

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
version number = 1

publish = true will increase the version number by automatically. It is best option for production deployments. If you don’t want to increase the version number by automatically then remove it. You can publish new version whenever you want through AWS CLI.

The Lambda function, “blog_endpoint” was created with version number 1.

The second version of the Lambda function (index.js):

exports.handler = async(event) => {
const response = {
statusCode: 200,
body: JSON.stringify("V2")
};
return response;
};

When you run the Terraform again then you will get an output like this:

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
Outputs:
version number = 2

You have 2 versions.

To enable traffic shifting deployments for the Lambda function, you will need to create an alias via AWS CLI:

aws lambda create-alias --function-name blog_endpoint --name production --function-version 2 --routing-config "AdditionalVersionWeights={1=0.5}"

You can create the alias via Terraform as well.

The alias name is “production”. So, you should call the Lambda function with the “production” keyword.

Let’s test it!

root@terraform:~# aws lambda invoke --invocation-type RequestResponse --function-name blog_endpoint:production --region eu-central-1 --log-type None out.txtroot@terraform:~# cat out.txt
{"statusCode":200,"body":"\"V2\""}

Let’s invoke the Lambda function over again:

root@terraform:~# aws lambda invoke --invocation-type RequestResponse --function-name blog_endpoint:production --region eu-central-1 --log-type None out.txtroot@terraform:~# cat out.txt
{"statusCode":200,"body":"\"V1\""}

Hey, Wait! I’m using API Gateway!

Don’t forget to append the alias to the Lambda function name

P.S.: Don’t forget to deploy the API Gateway

That’s it!