June 20th, 2016
Deploying Applications to EC2
By Gregg Gibson
Cloud Configuration AWS provides an ideal environment for taking advantage of best practices such as infrastructure-as-code and continuous delivery. Automation enabled by cloud computing can result in huge productivity gains and site availability that is difficult to achieve doing manual application deployment. To fully take advantage of the scalability offered by EC2, you need to make some decisions about how to deploy and manage application code and configuration data. Here are some good options:

Handcrafted AMIs

This is the most straightforward option and may be a good starting point. Start a generic AMI, install your code, and configure it. Once it is working, create an AMI from the working instance, and use that AMI as your base image for the instances in your auto scale group. This is a reasonable option if you deploy new application code relatively infrequently.

AMI bakery

If your code deployments happen too frequently for that to be practical, or better yet, you have a continuous delivery philosophy, you can still take the same approach of using customized AMIs, but you can create the AMIs using automation. There are a number of tools available that can help you automate AMI creation, including Ansible (https://www.ansible.com), Aminator (https://github.com/aminator), Chef (https://www.chef.io), and AWS Opsworks (https://aws.amazon.com/opsworks). All of these offer offer methods for creating AMIs in a continuous integration environment.

Bootstrapping

Building AMIs has some advantages, including potentially being up and running faster during an auto scaling event; however, there are downsides as well. Managing a large inventory of AMIs can become challenging since it can be difficult to keep track what is in each one. The alternative to custom AMIs is to bootstrap a basic AMI with the desired code at provisioning time. Some tools and options for bootstrapping are as follows:

Salt

Salt (http://saltstack.com) began its life as an approach for fast remote execution of multiple commands, but it developed into a great configuration management tool that can be used to deploy the same code to many different servers at the same time. Note, too, that Salt now offers other capabilities such as Salt-cloud that orchestrates the provisioning and management of EC2 instances.

Chef

Chef (https://www.chef.io) has the same kinds of capabilities and has a longer track record. It uses scripts known as cookbooks written in Ruby to specify configurations. It also offers automated testing and continuous integration/continuous delivery tools, including a workflow pipeline. The tools promote the infrastructure-as-code approach, which ensures reproducibility.

Ansible

Ansible (https://www.ansible.com) also does the same kinds of things using a slightly different approach. Ansible has an agent-less design, so there is no drain on system resources, and the configuration and usage can be simpler.

Packer

Packer is an open-source automation tool for creating repeatable machine images, e.g. AMIs, from source code. It can use Chef, Puppet, Ansible, Salt, or shell scripts to customize the AMI with your software. Since it’s a command line tool, you can use Packer in a CI/CD pipeline to automatically create custom AMIs for each successful build of your application.

AWS CodeDeploy

CodeDeploy (https://aws.amazon.com/codedeploy/details) is slightly different in that it doesn’t set up AWS resources itself, but it integrates with native EC2 auto scaling to automatically set up a new instance with the correct application code before it is added to a fleet’s elastic load balancer (ELB). It provides an option for rolling code updates to update a few instances in a fleet at a time, keeping the rest of the fleet in service. A YAML file describes the specifications for the app, including the locations of the scripts used for managing the app.

AWS Elastic Beanstalk

Elastic Beanstalk (https://aws.amazon.com/elasticbeanstalk) is a fast and simple way to get started with minimal effort. You provide your code to Elastic Beanstalk (or just point it at your Git repository) and give it a few parameters, and it sets up your AWS environment for you, including load balances and auto scale groups. Elastic Beanstalk can be used with PHP, Node.js, Python, Ruby, Go, Java, and .NET. Docker containers are supported, as well. Any of the above improves outcomes and system availability over manually deploying code on individual servers.