© 2020, Amazon Web Services, Inc. or its affiliates. All rights reserved.
Getting started with CI/CD for serverless applications
Marcia Villalba
Senior Developer Advocate AWS
@mavi888uy
About me
AWS Developer Advocate
Working with serverless since 2015 Host of FooBar YouTube Channel https://youtube.com/foobar_codes
@mavi888uy
Stages of the software release process
Source Build Test Production
Stages of the software release process
Source Build Test Production
Developers version,
review and commit
code changes
Stages of the software release process
Source Build Test Production
Build tasks and unit testing
Developers version,
review and commit
code changes
Stages of the software release process
Source Build Test Production
Deploy to testing environments and run integration tests Developers version,
review and commit code changes
Build tasks and unit
testing
Stages of the software release process
Source Build Test Production
Deploy to production environment Developers version,
review and commit code changes
Build tasks and unit
testing Deploy to testing
environments and
run integration tests
Stages of the software release process
Source Build Test Production
Stages of the software release process
Source Build Test Production
Approved deploy
Stages of the software release process
Source Build Test Production
Automated deploy Approved deploy
© 2020, Amazon Web Services, Inc. or its affiliates. All rights reserved.
The orchestrator
AWS CodePipeline
• Continuous delivery service for fast and reliable application updates
• Model and visualize your software release process
• Builds, tests, and deploys your code every time there is a code change
• Integrates with third-party tools and AWS
• https://aws.amazon.com/codepipeline/
Example of minimal developer’s pipeline
This pipeline:
• Three stages
• Builds code artifact
• One development environment
• Uses AWS SAM/AWS CloudFormation to deploy artifact and other AWS resources
• Has Lambda custom actions for testing functions
MyBranch-Source
Source
CodeCommit i
Build
test-build-source
CodeBuild i
MyDev-Deploy
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i Run-stubs
Example of full pipeline
This pipeline:
• Five stages
• Builds code artifact
• Three deployed to “environments”
• Uses AWS SAM/AWS CloudFormation to deploy artifact and other AWS resources
• Has Lambda custom actions for testing functions
• Integrates with a third-party tool/service
• Has a manual approval before deploying to production
Source
Source
GitHub i
Build
test-build-source
CodeBuild i
Deploy-Testing
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
Run-stubs
Lambda i
Deploy-Staging
Deploy-Prod
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
Post-Deploy-Stack
Lambda i
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
QA-Sign-Off
Manual approval i Review
Run-API-test
Runscope i
Example of full pipeline
This pipeline:
• Five stages
• Builds code artifact
• Three deployed to “environments”
• Uses AWS SAM/AWS CloudFormation to deploy artifact and other AWS resources
• Has Lambda custom actions for testing functions
• Integrates with a third-party tool/service
• Has a manual approval before deploying to production
Source
Source
GitHub i
Build
test-build-source
CodeBuild i
Deploy-Testing
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
Run-stubs
Lambda i
Deploy-Staging
Deploy-Prod
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
Post-Deploy-Stack
Lambda i
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
QA-Sign-Off
Manual approval i Review
Run-API-test
Runscope i
Dev account
Staging account
© 2019, Amazon Web Services, Inc. or its Affiliates.
Release process stages
Source Build Test Production
Code
Infrastructure
AWS CloudFormation
• Infrastructure as code (IaC)
• Provides a common language for you to describe and provision all the
infrastructure resources in your cloud environment
• Build and rebuild your infrastructure and
applications, without having to perform
manual actions or write custom scripts
https://aws.amazon.com/cloudformation/
AWS Serverless Application Model (SAM)
• Open source framework for building serverless applications on AWS
• Shorthand syntax to express functions, APIs, databases, and event source mappings
• Transforms and expands SAM syntax into AWS CloudFormation syntax on deployment
• Supports all AWS CloudFormation resource types
https://aws.amazon.com/serverless/sam/
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
AWS Cloud
Amazon API Gateway
Lambda function
Table Role
===
To become this
Allowing
this
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
Tells AWS CloudFormation this is a SAM template it
needs to “transform”
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Just 20 lines to create:
• Lambda function
• IAM role
• API Gateway
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
Function configuration
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Permissions for the
function
AWS SAM Policy Templates
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
Policies:
- CloudWatchPutMetricPolicy: {}
Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable
AWS SAM Policy Templates
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
All the available policies can be found in this link
http://bit.ly/sam-policy-template
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
API Gateway
AWS SAM template
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31 Resources:
MySimpleTableFunction:
Type: AWS::Serverless::Function Properties:
Handler: mySimpleTableFunction.handler Runtime: nodejs12.x
CodeUri: ./functions Policies:
- DynamoDBReadPolicy:
TableName: !Ref MySimpleTable Events:
MySimpleFunctionApi:
Type: Api Properties:
Path: /simpleTable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
Creates a Amazon DynamoDB table with 5
# Global information for all the functions Globals:
Function:
Runtime: nodejs12.x MemorySize: 256
Timeout: 100 Tracing: Active
Resources:
MySimpleFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: mySimpleFunction.handler CodeUri: ./functions
Events:
MySimpleFunctionAPI:
Type: Api Properties:
Path: /simple Method: GET
# A function that uses a Simple table function MySimpleTableFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: mySimpleTableFunction.handler CodeUri: ./functions
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MySimpleTable Environment:
Variables:
TABLE_NAME: !Ref MySimpleTable Events:
MySimpleFunctionAPI:
Type: Api Properties:
Path: /simpletable Method: GET
MySimpleTable:
Type: AWS::Serverless::SimpleTable
AWS SAM Globals
# Global information for all the functions Globals:
Function:
Runtime: nodejs12.x MemorySize: 256
Timeout: 100 Tracing: Active
Resources:
MySimpleFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: mySimpleFunction.handler CodeUri: ./functions
Events:
MySimpleFunctionAPI:
Type: Api Properties:
Path: /simple Method: GET
# A function that uses a Simple table function MySimpleTableFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: mySimpleTableFunction.handler CodeUri: ./functions
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MySimpleTable Environment:
Variables:
TABLE_NAME: !Ref MySimpleTable Events:
MySimpleFunctionAPI:
Type: Api Properties:
Path: /simpletable Method: GET
MySimpleTable:
AWS SAM Globals
AWS Lambda Environment Variables
• Key-value pairs that you can dynamically pass to your function
• Available via standard environment variable APIs such as process.env for Node.js or os.environ for Python
• Can optionally be encrypted via AWS Key Management Service (KMS)
• Useful for creating environments per stage (i.e. dev, testing,
production)
AWS Lambda Environment Variables
IN AWS SAM template
MySimpleFunction:
Type: "AWS::Serverless::Function"
Properties:
Handler: mySimpleFunction.handler Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MyDynamoDBTable Environment:
Variables:
TABLE_NAME: !Ref MyDynamoDBTable Events:
MySimpleFunctionAPI:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /simple
AWS Lambda Environment Variables
In the handler of the function
MySimpleFunction:
Type: "AWS::Serverless::Function"
Properties:
Handler: mySimpleFunction.handler Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MyDynamoDBTable Environment:
Variables:
TABLE_NAME: !Ref MyDynamoDBTable Events:
MySimpleFunctionAPI:
Type: Api
Properties:
RestApiId: !Ref MyApi Path: /simple
Method: GET
'use strict';
const TABLE_NAME = process.env.TABLE_NAME;
module.exports.getItem = async (propertyId, sortKey) => { console.log('getItem');
...
Different resources names for different stages
DEV STAGE PROD
Different resources names for different stages
In AWS SAM template
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Mappings:
ResourcesName:
dev:
tableName: MyDynamoDBTable-dev staging:
tableName: MyDynamoDBTable-staging prod:
tableName: MyDynamoDBTable-prod
Resources:
MyDynamoDBTable:
Type: "AWS::DynamoDB::Table"
Properties:
. . .
TableName: !FindInMap [ResourcesName, !Ref MyEnvironment, tableName]
Different resources names for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Mappings:
ResourcesName:
dev:
tableName: MyDynamoDBTable-dev staging:
tableName: MyDynamoDBTable-staging prod:
tableName: MyDynamoDBTable-prod
Resources:
MyDynamoDBTable:
Type: "AWS::DynamoDB::Table"
Properties:
. . .
In AWS SAM template
Different resources names for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Mappings:
ResourcesName:
dev:
tableName: MyDynamoDBTable-dev staging:
tableName: MyDynamoDBTable-staging prod:
tableName: MyDynamoDBTable-prod
Resources:
MyDynamoDBTable:
Type: "AWS::DynamoDB::Table"
Properties:
. . .
TableName: !FindInMap [ResourcesName, !Ref MyEnvironment, tableName]
In AWS SAM template
Different resources names for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Mappings:
ResourcesName:
dev:
tableName: MyDynamoDBTable-dev staging:
tableName: MyDynamoDBTable-staging prod:
tableName: MyDynamoDBTable-prod
Resources:
MyDynamoDBTable:
Type: "AWS::DynamoDB::Table"
Properties:
. . .
In AWS SAM template
We need to pass the stage name as a parameter when we create the AWS Cloudformation change set
Different resources names for different stages
In AWS CodePipeline
AWS CodeCommit
• Fully managed source-control service that hosts secure Git-based repositories
• Allows teams to collaborate on code in a secure and highly scalable ecosystem
• Automatically encrypts your files in transit and at rest
• Integrated with AWS Identity and Access Management (IAM)
• https://aws.amazon.com/codecommit/
Release process stages
Source Build Test Production
AWS CodeBuild
• Fully managed build service that can compile source code, run tests, and produce software packages
• Scales continuously and processes multiple builds concurrently
• Can consume environment variables from AWS Systems Manager Parameter Store
• No build servers to manage
• Supports dependency caching
• https://aws.amazon.com/codebuild/
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
- packaged.yaml
AWS CodeBuild: Lambda buildspec using SAM CLI
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
AWS CodeBuild: Lambda buildspec using SAM CLI
Use install phase to install packages or any pre-
reqs you may need throughout the build
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
- packaged.yaml
AWS CodeBuild: Lambda buildspec using SAM CLI
Use pre-build phase to run unit tests
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
AWS CodeBuild: Lambda buildspec using SAM CLI
In the build phase, we build the project using AWS SAM
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
- packaged.yaml
AWS CodeBuild: Lambda buildspec using SAM CLI
Use post-build for creating the package of the artifact
phases:
install:
commands:
- pip install --upgrade pip - pip install pipenv –user
- pipenv install awscli aws-sam-cli - npm install
pre_build:
commands:
- eslint *.js - npm test build:
commands:
- sam build post_build:
commands:
- sam package –template-file template.yaml –s3-bucket $BUCKET_NAME –output-template packaged.yaml
artifacts:
type: zip files:
AWS CodeBuild: Lambda buildspec using SAM CLI
Where AWS CodeBuild can find the output artifacts
Release process stages
Source Build Test Production
The pipeline: Testing
Configure Test Package
The build phase is a common place for testing
Source control Build Staging Production
Source control Build Staging Production
The pipeline: Testing
Configure and/or compile
Test Package
Test points
With serverless, it is
easy to test at different points in the pipeline
Source control Build Staging Production
Where and what to test
• Code review via pull request
• Lint/syntax check
• Unit test pass
• Code successfully compiles
• Application deploys successfully
• Mocked/stubbed integration tests
• Application deploys successfully
• Test against real services (potentially against
production dependencies)
• Run pre-traffic Lambda tests
• Deploy canaries
• Complete wait period successfully
• Deploy 100%
• Run post-traffic Lambda tests
Source
Source
CodeCommit i
Build
test-build-source
CodeBuild i
Deploy-Testing
create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
Run-stubs
Lambda i
Deploy-Staging
Deploy-Prod
create-changeset
AWS CloudFormation i execute-changeset
AWS CloudFormation i create-changeset
AWS CloudFormation i
execute-changeset
AWS CloudFormation i
QA-Sign-Off
Manual approval i Review
Run-API-test
Runscope i
Different ways to make sure everything is ok
AWS Lambda functions
Third party services
Manual QA
Safe deployments
Using AWS Lambda to perform integration tests
…
exports.handler = async (event, context) => {
let jobId = event["CodePipeline.job"].id;
// DO SOME INTEGRATION TESTS
if (testsPassed) { let params = {
jobId: jobId };
return codepipeline.putJobSuccessResult(params).promise(data => { context.succeed('Test passed');
}).catch(error => {
context.fail(error);
});
} else {
let params = {
jobId: jobId,
failureDetails: {
message: JSON.stringify('Test failed’), type: 'JobFailed’,
externalExecutionId: context.invokeid }
};
return codepipeline.putJobFailureResult(params).promise(data => { context.fail(message);
});
}
Using AWS Lambda to perform integration tests
…
exports.handler = async (event, context) => {
let jobId = event["CodePipeline.job"].id;
// DO SOME INTEGRATION TESTS
if (testsPassed) { let params = {
jobId: jobId };
return codepipeline.putJobSuccessResult(params).promise(data => { context.succeed('Test passed');
}).catch(error => {
context.fail(error);
});
} else {
let params = {
jobId: jobId,
failureDetails: {
message: JSON.stringify('Test failed’), type: 'JobFailed’,
externalExecutionId: context.invokeid }
};
return codepipeline.putJobFailureResult(params).promise(data => { context.fail(message);
});
} };
Write some integration tests
Using AWS Lambda to perform integration tests
…
exports.handler = async (event, context) => {
let jobId = event["CodePipeline.job"].id;
// DO SOME INTEGRATION TESTS
if (testsPassed) { let params = {
jobId: jobId };
return codepipeline.putJobSuccessResult(params).promise(data => { context.succeed('Test passed');
}).catch(error => {
context.fail(error);
});
} else {
let params = {
jobId: jobId,
failureDetails: {
message: JSON.stringify('Test failed’), type: 'JobFailed’,
externalExecutionId: context.invokeid }
};
return codepipeline.putJobFailureResult(params).promise(data => { context.fail(message);
});
}
Needs to call the
putJobSuccessuResult
Using AWS Lambda to perform integration tests
…
exports.handler = async (event, context) => {
let jobId = event["CodePipeline.job"].id;
// DO SOME INTEGRATION TESTS
if (testsPassed) { let params = {
jobId: jobId };
return codepipeline.putJobSuccessResult(params).promise(data => { context.succeed('Test passed');
}).catch(error => {
context.fail(error);
});
} else {
let params = {
jobId: jobId,
failureDetails: {
message: JSON.stringify('Test failed’), type: 'JobFailed’,
externalExecutionId: context.invokeid }
};
return codepipeline.putJobFailureResult(params).promise(data => { context.fail(message);
});
} };
Needs to call the
putJobFailureResult
Using AWS Lambda to perform integration tests
…
exports.handler = async (event, context) => {
let jobId = event["CodePipeline.job"].id;
// DO SOME INTEGRATION TESTS
if (testsPassed) { let params = {
jobId: jobId };
return codepipeline.putJobSuccessResult(params).promise(data => { context.succeed('Test passed');
}).catch(error => {
context.fail(error);
});
} else {
let params = {
jobId: jobId,
failureDetails: {
message: JSON.stringify('Test failed’), type: 'JobFailed’,
externalExecutionId: context.invokeid }
};
return codepipeline.putJobFailureResult(params).promise(data => { context.fail(message);
});
}
More information on how to configure this
https://amzn.to/2SVWZlW
Using 3rd party service to test
For adding tests there are lots of 3rd party tools supported.
Find more information on how to configure them with AWS CodePipeline here:
https://amzn.to/2SV0iK3
Manual approvals
Manual approvals
AWS CodeDeploy
• Automates code deployments to any instance and Lambda
• Handles the complexity of updating your applications
• Avoid downtime during application deployment
• Roll back automatically if failure detected
• Deploy to Amazon EC2, Lambda, Fargate, EC2,
or on-premises servers
Deployment preference
Canary10Percent30Minutes Canary10Percent5Minutes Canary10Percent10Minutes Canary10Percent15Minutes
Linear10PercentEvery10Minutes Linear10PercentEvery1Minute Linear10PercentEvery2Minutes Linear10PercentEvery3Minutes AllAtOnce
BeforeAllowTraffic
AfterAllowTraffic AllowTraffic
Deployment Preference
Versions are immutable
snapshots of a function – code + configuration
An Alias is a pointer to a version
Lambda Version and aliases
v1
v2
v3
Alias: prod
Alias: dev
AWS CodeDeploy – Lambda canary deployment
Gateway API Lambda
function weighted alias “live”
v1 Lambda function
code
100%
Gateway API Lambda function weighted alias “live”
v1 code 100%
Run PreTraffic hook against v2 code before it receives traffic
v2 code 0%
AWS CodeDeploy – Lambda canary deployment
AWS CodeDeploy – Lambda canary deployment
Gateway API Lambda
function weighted alias “live”
v1 code 90%
Wait for 10 minutes, roll back in case of alarm
v2 code
10%
Gateway API Lambda function weighted alias “live”
v1 code 0%
Run PostTraffic hook and complete deployment
v2 code 100%
AWS CodeDeploy – Lambda canary deployment
Testing using safe deployments
HelloFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: handler.hello Runtime: nodejs12.x
CodeUri: ./hello
AutoPublishAlias: live DeploymentPreference:
Type: Linear10PercentEvery10Minutes Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks:
PreTraffic: !Ref PreTrafficLambdaFunction
PostTraffic: !Ref PostTrafficLambdaFunction
HelloFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: handler.hello Runtime: nodejs12.x
CodeUri: ./hello
AutoPublishAlias: live DeploymentPreference:
Type: Linear10PercentEvery10Minutes Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks:
PreTraffic: !Ref PreTrafficLambdaFunction
Testing using safe deployments
Instructs AWS SAM to publish a new
version of the function for each new
deployment and link it to the live alias
HelloFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: handler.hello Runtime: nodejs12.x
CodeUri: ./hello
AutoPublishAlias: live DeploymentPreference:
Type: Linear10PercentEvery10Minutes Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks:
PreTraffic: !Ref PreTrafficLambdaFunction PostTraffic: !Ref PostTrafficLambdaFunction
Testing using safe deployments
Canary10Percent30Minutes Canary10Percent5Minutes Canary10Percent10Minutes Canary10Percent15Minutes
Linear10PercentEvery10Minutes
Linear10PercentEvery1Minute
Linear10PercentEvery2Minutes
Linear10PercentEvery3Minutes
AllAtOnce
HelloFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: handler.hello Runtime: nodejs12.x
CodeUri: ./hello
AutoPublishAlias: live DeploymentPreference:
Type: Linear10PercentEvery10Minutes Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks:
PreTraffic: !Ref PreTrafficLambdaFunction
Testing using safe deployments
A list of alarms that you want to monitor
You can specify a maximum of 10 alarms
HelloFunction:
Type: 'AWS::Serverless::Function’
Properties:
Handler: handler.hello Runtime: nodejs12.x
CodeUri: ./hello
AutoPublishAlias: live DeploymentPreference:
Type: Linear10PercentEvery10Minutes Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks:
PreTraffic: !Ref PreTrafficLambdaFunction PostTraffic: !Ref PostTrafficLambdaFunction
Testing using safe deployments
Validation Lambda functions that are run
before & after traffic shifting
Different strategies for different stages
DEV STAGE PROD
Linear10PercentEvery10Minutes Lambda
function
Different strategies for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Conditions:
IsProd: !Equals [!Ref MyEnvironment, prod]
MySafeDeployedFunction:
Type: "AWS::Serverless::Function"
Properties:
Handler: mySafeDeployedFunction.handler AutoPublishAlias: live
DeploymentPreference:
Type: !If [IsProd, Linear10PercentEvery1Minute, AllAtOnce]
Different strategies for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Conditions:
IsProd: !Equals [!Ref MyEnvironment, prod]
MySafeDeployedFunction:
Type: "AWS::Serverless::Function"
Properties:
Handler: mySafeDeployedFunction.handler AutoPublishAlias: live
DeploymentPreference:
Different strategies for different stages
Parameters:
MyEnvironment:
Type: String Default: dev AllowedValues:
- dev
- staging - prod
Conditions:
IsProd: !Equals [!Ref MyEnvironment, prod]
MySafeDeployedFunction:
Type: "AWS::Serverless::Function"
Properties:
Handler: mySafeDeployedFunction.handler AutoPublishAlias: live
DeploymentPreference:
Type: !If [IsProd, Linear10PercentEvery1Minute, AllAtOnce]
Release process stages
Source Build Test Production
Monitoring and observability
Amazon CloudWatch
Collects monitoring and operational data in
the form of logs, metrics, and events
AWS X-Ray
Provides a trace or an end-to-end view of
requests traveling
through your application
AWS developer tools
AWS CodeBuild + third party
Software release steps
AWS CodeCommit AWS CodeBuild AWS CodeDeploy
AWS CodeStar
AWS X-Ray
Amazon
Source Build Test Production
“Create application” experience
Create a serverless application from a starter template
• AWS SAM template for IaC
• CI/CD pipeline
• Clone locally for
development with AWS SAM
CLI
https://github.com/mavi888/demo-cicd-codepipeline
Thank you!
© 2020, Amazon Web Services, Inc. or its affiliates. All rights reserved.