Rolling Deploys on AWS using Terraform
New: Work with me @ Brightfame - We build modern solutions to run your business on the AWS cloud.
This post explains how to achieve rolling deploys on AWS using the HashiCorp stack. It is based on a strategy proposed by Paul Hinze. Normally when I deploy our applications to AWS I first 'bake' the code into an AWS AMI using Packer and then feed that image into an auto scaling group. Previously I relied on a lot of custom code/bash scripts etc to do this, but now Terraform makes it much easier.
My example creates a basic one tier architecture inside an AWS VPC. I have based my example on the eu-west-1 region, however it should be fairly straight forward to switch to another one. The resources are spread across all 3 availability zones for high availability.
Before we get started you will need to have the following tools installed:
You should also have the following environment variables set:
Creating the AWS resources
Start my cloning my example Github repository:
Next copy your public SSH key to the ssh_keys directory and update the path in key-pairs.tf.
The first step is to bake an Amazon Machine Image or AMI. We do this using Packer and a helper script I've created:
Packer should boot an instance on AWS, provision it then create an new image based on it.
Using the AMI ID Packer provided run the Terraform plan step:
And once we are confident we can use the apply step to create the AWS resources:
Rolling Deploys
Let's bake a fresh AMI so we can demonstrate a rolling deploy. Run the bake command again:
Packer will output a new AMI ID. Lets use the plan command to ensure Terraform will only create a new auto scaling group:
Once we are satisified we can use the apply command again to initiate the rolling deploy.
If you are using the AWS console you will notice that Terraform creates a new launch configuration and auto scaling group, but re-uses the existing elastic load balancer. The fresh auto scaling group in turn will boot two instances using the new AMI. Once these instances are passing the ELB health checks, Terraform will remove the old resources. If there is a problem with the new instances Terraform will marked the new ASG as 'tainted' and leave the old instances in service.
Here is the code that enables this:
As Paul mention, the key parts are:
Cleaning Up
Finally when you are finished, you can run the destroy command to cleanup the AWS resources used for this example:
Moving Forwards
My example provides a good starting point for building out your own architecture using the HashiCorp tools. You can tweak the code to add your own application during the bake phase and add other AWS resources such as an RDS database. If you are bored or want to learn you can help me refactor and harden my example - just fork the repository. Also investigate other AWS deployment strategies such as blue/green. If you have any questions, then please get in touch on Twitter: @rjm.