- Notifications
You must be signed in to change notification settings - Fork2
This is a sample app created to illustrate the best practices outlined in the following blog post
License
aws-samples/bluegreen-to-amazon-ecs-using-aws-cdk-aws-codedeploy
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
The project deploys a Java-based microservice using a CI/CD pipeline. The pipeline is implemented using the CDK Pipelines construct. The deployment uses AWS CodeDeploy Blue/Green deployment strategy. The service can be deployed insingle orcross-account andsingle orcross-Region scenarios.
The AWS CDK application defines a top-level stack that deploys the CI/CD pipeline using AWS CodeDeploy in the specified AWS account and region. The pipeline can deploy theService to a single environment or multiple environments. Theblue version of theService runtime code is deployed only once when the Service is deployed the first time in an environment. Onwards, thegreen version of the Service runtime code is deployed using AWS CodeDeploy. This Git repository contains the code of the Service and its toolchain as a self-contained solution.
Considerations when managing ECS blue/green deployments using CloudFormation documentation includes the following:"When managing Amazon ECS blue/green deployments using CloudFormation, you can't include updates to resources that initiate blue/green deployments and updates to other resources in the same stack update". The approach used in this project allows to update the Service infrastructure and runtime code in a single commit. To achieve that, the project leverages AWS CodeDeploy'sdeployment model using configuration files to allow updating all resources in the same Git commit.
The project requires the following tools:
- Amazon Corretto 8 - See installation instructions in theuser guide
- Apache Maven - Seeinstallation instructions
- Docker - Seeinstallation instructions
- AWS CLI v2 - Seeinstallation instructions
- Node.js - Seeinstallation instructions
Although instructions in this document are specific for Linux environments, the project can also be built and executed from a Windows environment.
After all prerequisites are met, it usually takes around 10 minutes to follow the instructions below and deploy the AWS CDK Application for the first time. This approach supports all combinations of deploying the microservice and its toolchain to AWS accounts and Regions.
To make it easier following the example, the next steps creates an AWS CodeCommit repository and use it as source. In this example, I'm authenticating into AWS CodeCommit usinggit-remote-codecommit. Once you havegit-remote-codecommit configured, you can copy and paste the following commands:
git clone https://github.com/aws-samples/bluegreen-to-amazon-ecs-using-aws-cdk-aws-codedeploy.gitcd bluegreen-to-amazon-ecs-using-aws-cdk-aws-codedeployrepo_name=$(aws codecommit create-repository \ --repository-name Demo \ --output text \ --query repositoryMetadata.repositoryName)git remote set-url --push origin codecommit://${repo_name}git add .git commit -m "initial import"git pushThis approach supports all combinations of deploying the Service and its toolchain to AWS accounts and Regions. Below you can find a walkthrough for two scenarios: 1/ single account and single region 2/ cross-account and cross-region.
Note: As of today, single account and cross-Region scenario leads to a circular dependency duringsynth phase. If you want details about this issue, please refer tothis report. As an option, you can deploy cross-account and cross-Region.
If you already executed the cross-account scenario you shouldcleanup first.
Service is a component from theDemo application. Let's deploy the Service in single account and single Region scenario. Demo application belongs to theExample Corp. This can be accomplished in 5 steps.
1. Configure environment
Editsrc/main/java/com/example/demo/Demo.java and update value of the following 2 properties: account number and region:
publicstaticfinalStringTOOLCHAIN_ACCOUNT ="111111111111";publicstaticfinalStringTOOLCHAIN_REGION ="us-east-1";
2. Install AWS CDK locally and Synth
npm installmvn clean packagenpx cdk synth3. Push configuration changes to AWS CodeCommit
git add src/main/java/com/example/demo/Demo.javagit add cdk.context.jsongit commit -m "initial config"git push codecommit://${repo_name}4. One-Time Bootstrap
- AWS CDK
Deploying AWS CDK apps into an AWS environment (a combination of an AWS account and region) requires that you provision resources the AWS CDK needs to perform the deployment. Use the AWS CDK Toolkit'scdk bootstrap command to achieve that. See thedocumentation for more information.
You need to run cdk bootstrap once for each deployment environment (account and Region). Below is an example of bootstrapping the account111111111111 for both toolchain and service:
npx cdk bootstrap 111111111111/us-east-15. Deploy the Toolchain stackIt will deploy the microservice in the same account and region as the toolchain:
npx cdk deploy DemoToolchainIf you already executed the single account and single region scenario you shouldclean up first.
Service is a component from theDemo application. Demo application belongs to theExample Corp. Let's deploy the Demo service in cross-account and cross-Region scenario. This can be accomplished in 5 steps:
1. Configure environment:
Editsrc/main/java/com/example/demo/Demo.java and update the following environment variables:
//this is the account and region where the pipeline will be deployedpublicstaticfinalStringTOOLCHAIN_ACCOUNT ="111111111111";publicstaticfinalStringTOOLCHAIN_REGION ="us-east-1";//this is the account and region where the component (service) will be deployedpublicstaticfinalStringSERVICE_ACCOUNT ="222222222222";publicstaticfinalStringSERVICE_REGION ="us-east-2";
2. Install AWS CDK locally and Synth
npm installmvn clean packagenpx cdk synth3. Push configuration changes to AWS CodeCommit
git add src/main/java/com/example/demo/Demo.javagit add cdk.context.jsongit commit -m "cross-account config"git push codecommit://${repo_name}4. One-Time Bootstrap
- AWS CDK
Deploying AWS CDK apps into an AWS environment (a combination of an AWS account and region) requires that you provision resources the AWS CDK needs to perform the deployment. Use the AWS CDK Toolkit'scdk bootstrap command to achieve that. See thedocumentation for more information.
You need to runcdk bootstrap once for each deployment environment (account and region). For cross-account scenarios, you should add the parameter--trust. For more information, please see theAWS CDK Bootstrapping documentation. Below is an example for service in account222222222222 and toolchain in account111111111111:
npx cdk bootstrap 111111111111/us-east-1 #make sure your aws credentials are pointing to account 222222222222 npx cdk bootstrap 222222222222/us-east-2 --trust 1111111111115. Deploy the Toolchain stack
npx cdk deploy DemoToolchainTheToolchain Stack instantiates a CI/CD pipeline that builds Java based HTTP microservices. As a result, each newPipeline comes with 2 stages: source and build and we configure as many deployment stages as needed. The example below shows how to create a newToolchain pipeline using a builder pattern:
Toolchain.Builder.create(this,"BlueGreenPipeline") .setGitRepo(Toolchain.CODECOMMIT_REPO) .setGitBranch(Toolchain.CODECOMMIT_BRANCH) .addStage("UAT",EcsDeploymentConfig.CANARY_10_PERCENT_5_MINUTES,Environment.builder() .account(Toolchain.SERVICE_ACCOUNT) .region(Toolchain.SERVICE_REGION) .build()) .build();
TheaddStage method needs to be invoked at least once to add a deployment stage. When invoked, it creates deployment stages to different AWS accounts and regions. This feature enables the implementation of different scenarios, going from single region to cross-region deployment (DR).
In the example below, there is a pipeline that has three deployment stages:UAT (User Acceptance Test),Prod andDR (Disaster Recovery). Each deployment stage has a name, adeployment configuration and environment information, such as, account and Region where the component should be deployed.
In detail:
publicclassDemo {privatestaticfinalStringTOOLCHAIN_ACCOUNT ="111111111111";privatestaticfinalStringTOOLCHAIN_REGION ="us-east-1";//CodeCommit account is the same as the toolchain accountpublicstaticfinalStringCODECOMMIT_REPO ="DemoService";publicstaticfinalStringCODECOMMIT_BRANCH ="main";publicstaticfinalStringSERVICE_ACCOUNT ="222222222222";publicstaticfinalStringSERVICE_REGION ="us-east-1";publicstaticfinalStringSERVICE_DR_ACCOUNT ="333333333333";publicstaticfinalStringSERVICE_DR_REGION ="us-east-2";publicstaticvoidmain(Stringargs[]) {super(scope,id,props);Toolchain.Builder.create(app,Constants.APP_NAME) .stackProperties(StackProps.builder() .env(Environment.builder() .account(Demo.TOOLCHAIN_ACCOUNT) .region(Demo.TOOLCHAIN_REGION) .build()) .stackName(Constants.APP_NAME) .build()) .setGitRepo(Demo.CODECOMMIT_REPO) .setGitBranch(Demo.CODECOMMIT_BRANCH) .addStage("UAT",EcsDeploymentConfig.CANARY_10_PERCENT_5_MINUTES,Environment.builder() .account(Demo.COMPONENT_ACCOUNT) .region(Demo.COMPONENT_REGION) .build()) .addStage("Prod",EcsDeploymentConfig.CANARY_10_PERCENT_5_MINUTES,Environment.builder() .account(Demo.COMPONENT_ACCOUNT) .region(Demo.COMPONENT_REGION) .build()) .addStage("DR",EcsDeploymentConfig.CANARY_10_PERCENT_5_MINUTES,Environment.builder() .account(Demo.COMPONENT_DR_ACCOUNT) .region(Demo.COMPONENT_DR_REGION) .build()) .build(); }}
Instances ofToolchain create self-mutating pipelines. This means that changes to the pipeline code that are added to the repository will be reflected to the existing pipeline next time it runs the stageUpdatePipeline. This is a convenience for adding stages as new environments need to be created.
Self-Mutating pipelines promote the notion of a self-contained solution where the toolchain code, microservice infrastructure code and microservice runtime code are all maintained inside the same Git repository. For more information, please checkthis blog about CDK Pipelines.
The image below shows an example pipeline created with a deployment stage namedUAT:
In a minimal deployment scenario, AWS CloudFormation will display two stacks:DemoToolchain andDemoService-UAT. CDKPipelines takes care of configuring permissions to CodeDeploy, KMS and S3 (pipeline artifacts). TheDemoToolchain stack deploys the pipeline and theDemoService-UAT stack deploys the component in theUAT environment. In this case, pipeline andUAT were deployed in the same account and region.
- Clean the S3 bucket used to store the pipeline artifacts. Bucket name should be similar to the one from the example below:
aws s3 rm --recursive s3://demotoolchain-pipelinedemopipelineartifactsbucket-1e9tkte03ib30- Destroy the stacks:
npx cdk destroy "**" #Includes the deployments done by the pipelineIf, for some reason, the destroy fails, just wait for it to finish and try again.
- Delete the repository:
aws codecommit delete-repository --repository-name DemoServiceOnce the deployment of the blue task is complete, you can find the public URL of the application load balancer in the Outputs tab of the CloudFormation stack namedDemoService-UAT (image below) to test the application. If you open the application before the green deployment is completed, you can see the rollout live.
Once acessed, thhe service displays a hello-world screen with some coloured circules representing the version of the service. At this point, refreshing the page repeatedly will show the different versions of the same service. The Blue and Green versions will appear as in the images below:
At the same time, you can view the deployment details using the console of the CodeDeploy: for that, Sign in to the AWS Management Console and open the CodeDeploy console athttps://console.aws.amazon.com/codedeploy. In the navigation pane, expandDeploy, and then chooseDeployments. Click to view the details of the deployment from applicationDemoService-UAT and you will be able to see the deployment status and traffic shifting progress (image below) :
The deployment model using AWS CodeDeploy will require changes to the properties of the task to be added into thetemplate-taskdef.json file, located inside the directory/src/main/java/com/example/demo/toolchain/codedeploy. As an example, to update the log location for the microservice, your file will look like the following:
{"executionRoleArn":"TASK_EXEC_ROLE","containerDefinitions": [ {"essential":true,"image":"<IMAGE1_NAME>","logConfiguration": {"logDriver":"awslogs","options": {"awslogs-group" :"/ecs/Service","awslogs-region":"us-east-1","awslogs-create-group":"true","awslogs-stream-prefix":"ecs" } },"name":"APPLICATION","portMappings": [ {"containerPort":8080,"hostPort":8080,"protocol":"tcp" } ] } ],"cpu":"256","family":"fargate-task-definition","memory":"512","networkMode":"awsvpc","requiresCompatibilities": ["FARGATE" ]}This project is licensed under theMIT-0 license.
About
This is a sample app created to illustrate the best practices outlined in the following blog post
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.









