Manage Learn to apply best practices and optimize your operations.

Continuous Deployment and AWS Elastic Beanstalk

Chris Moyer explains how to use Continuous Deployment with AWS Elastic Beanstalk to reduce development timelines and increase productivity.

Continuous deployment is the process of deploying code when it's ready, not on a release cycle, where developers...

deploy only after a certain period of time has passed or a certain set of features has been completed. This deployment method cuts down on development timelines from a few months to a few days. It allows developers to quickly move on to new features and deploy changes to get feedback as fast as possible. The concept is entirely focused on two simple concepts: many automated tests and strong version control.

Automated tests

Continuous deployment (CD) often is aided by the help of continuous integration (CI) systems. CI is the process of merging code into a production "branch" as soon as the features are ready for testing. In order to safely use CD, developers need to make sure as much as possible is automatically tested. After each change, the CI system will automatically run these tests. If any of them fail, no further build steps are taken, and the developer is notified. If all tests pass, the CI system may be set up to automatically deploy the code to a development environment.

Strong version control

It's important that developers use a strong version-control system, such as Git. Git has a very well-defined workflow process called Git-flow. This process allows everyone on the team to be on the same page, and is very helpful for CI workflows. With Git-flow, developers create a Master branch for all production code, a Develop branch for all development code, Feature branches for each individual feature being worked on and Release branches for creating releases between develop and master. It's also important to properly tag each version that is released into Master, so developers can quickly and easily revert to the old version if needed.

Integrating with Jenkins and Elastic Beanstalk

Developers can also use Jenkins to deploy code to AWS Elastic Beanstalk. When developers push code, it automatically runs tests, sends alerts and updates the development beanstalk environment. It's important to first note the proper way to update beanstalk environments, which is not to simply push everything into production.

If developers push code to the Develop branch, make sure the development environment is updated. If developers push code to the Master branch, however, the best practice is to spin up a new environment and let the developers switch over once they've finished manually testing.

Create an environment for each version of your application you deploy
Create an environment for each version of your application you deploy

Even with the best automated tests, developers can't be sure everything is covered. It's often best to set up a separate environment and use the Swap Environment URLs function to migrate to the new version. Developers can then verify that everything is OK before terminating the old environment. If there is a problem, developers can easily switch back again using the same method:

Choose 'Swap Environment URLs' from the 'Actions' menu
Choose 'Swap Environment URLs' from the 'Actions' menu

Setting up Jenkins

Jenkins is a very popular open source CI system. It's self-hosted, meaning that developers have to download the code and run it on a personal server. Fortunately, this is very easy to do with AWS, and there's even an Amazon Machine Image (AMI) on the Amazon Marketplace.

Starting off with this AMI, developers get a complete version of Jenkins ready to go. Next, developers have to configure the plugins to integrate with the chosen version control system. There are plug-ins for GitHub and Bitbucket, as well as just Git if the code is on any other system. Installation of either plug-in is easy: Just go to the Manage Jenkins section, choose Manage Plugins and search for the plug-in needed. Here are some useful plug-ins:

  • AnsiColor -- Allows jobs to provide colored console output
  • AWS Elastic Beanstalk Deployment Plugin
  • Bitbucket Plugin -- If using Bitbucket for source control
  • Cobertura Plugin -- For code-coverage reports
  • Credentials Binding Plugin -- To deploy to multiple AWS accounts
  • Embeddable Build Status Plugin -- To embed a build status logo on selected Readme files
  • Flowdock Plugin -- Notify Flowdock of builds
  • GitHub Plugin -- If using GitHub for source control
  • Node.js Plugin -- For writing code in Node.js
  • xUnit Plugin -- If tests can output XUnit-style results

Once the plug-ins are installed, it's time to set up the job.

Every project in Jenkins is set up as a Job. This is what Jenkins uses to determine what needs to be done. Jenkins configures everything that needs to be done in the Job itself, instead of in the code. This eliminates the need for pushing up new code just for a change in configuration on how to deploy.

Start off by clicking New Job, and then choose a name for the job, and make sure "free-style software project" is selected:

Setting up a new job in Jenkins
Setting up a new job in Jenkins

Fill out all the information on the next page and make sure to set up the repository where the code resides and set Branches to build to blank. There is currently a bug with the Bitbucket plug-in that sets all branch names to "(detached head)." If the code is on GitHub or Bitbucket, make sure to click the box that says "Build when a change is published to." This will automatically build the project each time a developer pushes code to the repository. Each of those plug-ins includes information on how to configure Bitbucket or GitHub to notify Jenkins when there is an update to the code.

Under "build environment" make sure to check the "Color ANSI Console output" if the plug-in is installed, and if the code uses Node.js, make sure to configure the Node.js environment.

And now, to configure the build steps.

Choose 'Deploy into AWS Elastic Beanstalk' from the 'Add build step' dropdown
Choose 'Deploy into AWS Elastic Beanstalk' from the 'Add build step' dropdown

Under the build steps, make sure to choose the script option that will best test the application. If any build step fails, the entire job will stop and not proceed. This is why it is incredibly important to make sure there are good-quality tests. If the tests are set up to run with "make test," just execute a shell script that runs "make test." If the code uses Node.js with Grunt, configure this section to execute a shell script that installs node modules, then runs the Grunt test. As a good first step though, it is recommended to clean up any old installation code that might be left over.

A simple shell script to test your application
A simple shell script to test your application

The next build step is the heart of what we're trying to accomplish -- deployment to AWS Elastic Beanstalk. First, make sure to add a build step that archives the code. The simplest way to do this is to add a new shell script that just runs:

git archive --format=tgz --output=eb.tgz HEAD

Add a new build task "Deploy into AWS Elastic Beanstalk." Fill out each of the fields:

  • AWS Access Key Id: Set this to a new IAM User for Jenkins
  • AWS Secret Shared Key: This is actually the "Private Key" for the IAM user
  • AWS Region: Something like "us-east-1"
  • Application Name: The name of the application set up in Beanstalk
  • S3 Bucket Name: The name of the S3 bucket that Beanstalk set up for this application. Find this by browsing S3 buckets. It will be named something pretty obvious like "elasticbeanstalk-us-east-1-YOURACCOUNT"
  • S3 Key Prefix: Optional, this will add a prefix to all code packages saved to S3
  • Root Object (File / Directory): Since Jenkins exported the archive, just "eb.tgz" will work here
  • Includes/Excludes: Ignore these fields since Jenkins already exported the archive
  • Version Label Format: Suggestion label - ${GIT_COMMIT}-${BUILD_TAG}
  • Environment Name: Make sure this is the DEVELOPMENT environment name, like "project-dev"

After the build steps are completed, Jenkins will run the post-build actions. Here's where Jenkins can be configured to add any reports and notifications. These are all optional, but at a minimum, adding a notification via email to the developer of the project is a good idea.

Save the job, and commit to the repository. If everything is set up correctly, Jenkins will now deploy to the development environment every time a new version is committed. Since these versions are all uploaded to S3 and registered with AWS Elastic Beanstalk, it's easy to deploy any of these versions to a new environment, including deploying directly to production.

Dig Deeper on AWS network management

Join the conversation


Send me notifications when other members comment.

Please create a username to comment.

Which methods have you found are best for deploying code on AWS Elastic Beanstalk?
This is where AWS is moving to provide more integrated tools for developers with their CodeDeploy, CodePipeline and CodeCommit services.