Lab: Implementing Serverless Canary Deployments with AWS CodeDeploy
Implement deployment strategies for instance, container, and serverless environments
Lab: Implementing Serverless Canary Deployments with AWS CodeDeploy
This lab demonstrates how to implement an immutable deployment strategy (Canary) for serverless environments using AWS CodeDeploy. You will learn how to shift traffic between Lambda versions and use AppSpec files to manage lifecycle events.
[!WARNING] Remember to run the teardown commands at the end of this lab to avoid ongoing charges for provisioned resources.
Prerequisites
- AWS CLI: Installed and configured with
AdministratorAccess. - IAM Permissions: Ability to create IAM Roles, Lambda functions, and CodeDeploy applications.
- Region: Use
us-east-1for consistency. - Tools: A terminal and a text editor.
Learning Objectives
- Configure an AWS Lambda function with versioning and aliases.
- Create a CodeDeploy Application and Deployment Group for a Lambda compute platform.
- Execute a Canary deployment (Linear10PercentEvery1Minute).
- Verify traffic shifting via the AWS CLI and Management Console.
Architecture Overview
Step-by-Step Instructions
Step 1: Create the Execution Role and Initial Lambda
First, we need a service role for the Lambda and the initial code version.
# 1. Create trust policy file
echo '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"},"Action": "sts:AssumeRole"}]}' > trust-policy.json
# 2. Create IAM Role
aws iam create-role --role-name brainybee-lambda-role --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name brainybee-lambda-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
# 3. Create initial code
echo 'exports.handler = async (event) => { return "Version 1.0"; };' > index.js
zip function.zip index.js
# 4. Create Function
aws lambda create-function --function-name MyCanaryFunction --runtime nodejs18.x --handler index.handler --role $(aws iam get-role --role-name brainybee-lambda-role --query 'Role.Arn' --output text) --zip-file fileb://function.zip --publish▶Console alternative
Navigate to Lambda > Create Function. Name it 'MyCanaryFunction'. Use Node.js 18.x. Create a new role with basic Lambda permissions. Once created, click 'Publish new version' under the Versions tab.
Step 2: Create the Alias and CodeDeploy Application
CodeDeploy requires an Alias to manage the traffic shifting between versions.
# 1. Create Alias pointing to Version 1
aws lambda create-alias --function-name MyCanaryFunction --name live --function-version 1
# 2. Create CodeDeploy App
aws deploy create-application --application-name MyServerlessApp --compute-platform Lambda
# 3. Create Deployment Group
# Note: Requires a CodeDeploy Service Role. For brevity, ensure your user has permissions.
aws deploy create-deployment-group --application-name MyServerlessApp --deployment-group-name MyCanaryGroup --deployment-config-name CodeDeployDefault.LambdaCanary10Percent5Minutes --service-role-arn <YOUR_CODEDEPLOY_ROLE_ARN>[!IMPORTANT] You must replace
<YOUR_CODEDEPLOY_ROLE_ARN>with an IAM role that has theAWSCodeDeployRoleForLambdamanaged policy.
Step 3: Trigger a Canary Deployment
Now, update the function code and trigger CodeDeploy to shift traffic.
# 1. Update code for Version 2
echo 'exports.handler = async (event) => { return "Version 2.0 - New Features!"; };' > index.js
zip function.zip index.js
aws lambda update-function-code --function-name MyCanaryFunction --zip-file fileb://function.zip --publish
# 2. Create appspec.yaml
cat <<EOF > appspec.yaml
version: 0.0
Resources:
- MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: "MyCanaryFunction"
Alias: "live"
CurrentVersion: "1"
TargetVersion: "2"
EOF
# 3. Deploy
aws deploy create-deployment --application-name MyServerlessApp --deployment-group-name MyCanaryGroup --revision '{"revisionType": "AppSpecContent", "appSpecContent": {"content": "'$(cat appspec.yaml | sed 's/"/\\"/g')'"}}'Checkpoints
- Verify Deployment Status: Run
aws deploy get-deployment --deployment-id <ID>. Look forStatus: InProgress. - Check Alias Weights: Run
aws lambda get-alias --function-name MyCanaryFunction --name live. You should seeRoutingConfigshowing a percentage weight for Version 2. - Test Output: Invoke the alias multiple times:
You should see "Version 1.0" 90% of the time and "Version 2.0" 10% of the time initially.bash
aws lambda invoke --function-name MyCanaryFunction --qualifier live out.txt && cat out.txt
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
Invalid Revision | Syntax error in appspec.yaml | Ensure YAML is valid and indentation is correct. |
AccessDenied | CodeDeploy lacks permission | Attach AWSCodeDeployRoleForLambda to the service role. |
Alias already exists | Re-running setup | Use update-alias instead of create-alias. |
Clean-Up / Teardown
aws deploy delete-application --application-name MyServerlessApp
aws lambda delete-function --function-name MyCanaryFunction
aws iam detach-role-policy --role-name brainybee-lambda-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam delete-role --role-name brainybee-lambda-role
rm trust-policy.json index.js function.zip appspec.yaml out.txtStretch Challenge
Modify the appspec.yaml to include a BeforeAllowTraffic hook. This hook should trigger a separate "Validation" Lambda function. If the validation function fails (returns an error), CodeDeploy should automatically roll back the deployment to Version 1.
Cost Estimate
- AWS Lambda: Free Tier (1M requests/month).
- AWS CodeDeploy: No additional charge for code deployments to AWS Lambda.
- IAM/S3: Negligible costs.
- Total Estimated Spend: $0.00 (within Free Tier).
Concept Review
| Feature | Instance (EC2) | Container (ECS) | Serverless (Lambda) |
|---|---|---|---|
| Agent | CodeDeploy Agent required | No agent (managed by ECS) | No agent (managed by Lambda) |
| Strategy | In-place or Blue/Green | Blue/Green (Canary/Linear) | Blue/Green (Canary/Linear) |
| Configuration | appspec.yml in root | appspec.yaml in deployment | appspec.yaml in deployment |
| Traffic Control | ELB/Target Groups | ALB/Target Groups | Lambda Aliases |