This guide is a continuation of AWS Deployment Strategies and will be a hands-on tutorial of setting up an app deployment using AWS Codedeploy.
Deploying resources can be tricky. There is a strict balancing act that needs to be done in order to successfully deploy an app with minimal service interruption. Any service interruptions that can negatively affect user experience should be mitigated greatly. In the world of software as a service (SaaS), negative user experience can directly hurt your organization's subscription revenue.
To remedy any negative experience caused by deployments, AWS allows for multiple deployment options built into their services. In this guide we'll be taking a look at blue/green deployment using AWS Codedeploy.
The AWS environment shown in this guide's example will have two subnets. A private subnet will contain EC2 instances in an autoscaling group with Apache installed on two EC2 instances, and a public subnet will contain a NAT gateway that will allow the EC2 instances to reach the internet.
Finally, all of the resources are behind an app load balancer. The load balancer is configured to send traffic on port 80 to one of the EC2 instances. Users will not be able to reach the Apache webpage directly.
This is how the default Apache page looks before Codedeploy has run its course. After Codedeploy runs its course, it will be changed to have a green banner.
Codedeploy is configured to connect to a Github repo and uses the
appspec.yml file in the root of the repo. The
appspec.yml defines life cycle hooks to be executed against the EC2 instances.
Below is an example of the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
version: 0.0 os: linux files: - source: /index.html destination: /tmp hooks: BeforeInstall: - location: scripts/install_dependencies.sh timeout: 300 runas: root AfterInstall: - location: scripts/move_files.sh timeout: 300 runas: root ApplicationStop: - location: scripts/stop_server.sh timeout: 300 runas: root ApplicationStart: - location: scripts/start_server.sh timeout: 300 runas: root
There are four life cycle hooks for this deployment:
ApplicationStart. These will be executed in sequence to install a new version of the index.html.
You can view this Codedeploy sample in its entirety here.
Blue/green will deploy code by creating a completely separate and independent environment. Both environments will be similar in their infrastructure configurations, however both will be isolated in their own autoscaling groups.
Initially the blue environment will be running Apache with an older version of the landing page simulating the app. Then, use AWS Codedeploy to deploy a new version of the landing page.
Unlike a standard blue/green deployment where traffic is routed at the DNS level, Codedeploy will route traffic at the target group level. During the deployment, instances will register as they become available and deregister automatically from the target group.
Now you will dive in and configure Codedeploy. Select the Codedeploy service and click on the Create application button. In the new page that appears, enter the app name, (the app in this example is named "codedeploy-blue-green-1") and select EC2/On-premises as the compute platform.
Next you will create a deployment group by clicking on the Create deployment group button. Give the deployment group a name. The one in this example is named "codedeploy-blue-green-dg."
Select a service role that will allow Codedeploy to interact with EC2 instances and autoscaling groups. If you need to create a role, ensure that the role has the
AWSCodeDeployRole policy. Select Blue/green in the deployment type.
On the same window, scroll farther down to configure the rest of the deployment group. In the environment configuration section, select Automatically copy Amazon EC2 Auto Scaling group and the autoscaling group containing your webservers.
Under Deployment Settings, ensure traffic rerouting is set to Reroute traffic immediately. This will route traffic to the new green autoscaling group that is spun up during the deployment. Terminate the original instances (blue) immediately by setting the the wait time to zero. Choose CodeDeployDefault.HalfAtATime for the deployment configuration. This will ensure only half the instances in your autoscaling group are upgraded at a time.
Scroll farther down and you will see the final setting in this page. Under the Load balancer section choose Application Load Balancer or Network Load Balancer. Follow that by selecting the target group associated with your app's load balancer. The one in this example is named "test-tg."
Once you have created a deployment group, it's time to create a deployment! Select the deployment group and choose My application is stored in Github. This will allow Codedeploy to grab new versions of your app from Github.
Enter your Github username as the token name and the path to the repository name. Add the commit ID of the app version you want to deploy.
Once your deployment settings have been configured, click to begin the deployment. In the next page that appears you will be able to monitor the deployment status
Further down on the page you will be able to monitor the life cycle hook status on each instance. You may have also noticed that two more instances have been created. These extra instances have been created by Codedeploy in a new autoscaling group.
All you have to do now is to wait until the deployment finishes. If you're curious, about what is going to happen with the original EC2 instances, at step four the original instances will be terminated. You can view the original instances being terminated from within the EC2 instance console.
Once the deployment is complete you should be greeted with the green banner, if you access the load balancer DNS name again.
Note: If you are running into issues where your EC2 instances are not downloading content from Github, ensure that your they have an IAM role assigned to them that allows them to read from S3. You will also have to specify the role within the launch configuration so that other instances within the autoscaling group can access Github.
As you can imagine, doing a manual release process is time consuming. The example deployment that uses Codedeploy and blue/green takes about seven minutes to complete. More complex apps involving more hosts and databases can take hours to complete if done manually.
Codedeploy streamlines the operation and automates it! Codedeploy also allows your deployments to be treated like code using an
appspec.yml file. Peer reviews can be conducted so everyone on the team can provide input on the steps being executed during the deployment. Finally, if any issues occur Codedeploy has guard rails in place to roll back your deployment in case it runs into problems.
What is next from here? Now that Codedeploy is fully configured and smoothly deploying new versions of your app, you can integrate it with your CI/CD platform of choice. Codepipeline, Jenkins, Bamboo, and Gitlab-CI can all leverage Codedeploy.