AWS Elastic Beanstalk
A quick and easy way to deploy and manage apps in an AWS cloud.
It has been years since Amazon began innovating in the hosting market with their cloud hosting, but I can still remember the day I spun up an EC2 instance and cried “WHAT?” over my coffee, staring at a Linux machine that cost me US$ 0.10. (By the time I had stopped staring and fiddling around with it, it probably cost me much more.) Nor can I forget the hours configuring machines to do fairly simple things. All along I wished for a tool just to spin up a server and all the stuff that goes with it and just make it work.
Well, for some time there has been: Elastic Beanstalk. This isn't new, but if you’re wandering around the cloud hosting landscape, I find this a much better starting point than the usual configure-your-cloud-from-scratch approaches.
Elastic Beanstalk is similar in its approach to Heroku, which is now just one of many platforms on which you git push your project, then a back-end system – Heroku, Elastic Beanstalk, etc. – deals with getting that project onto a server and behind a URL for you.
The big difference between Beanstalk and many of the other platforms is that, with AWS, the underlying architecture is exposed, so you can dig into it. If your app is successful, or just becomes more complex than the platform can manage, you can take the Beanstalk configuration of servers, load balancers, and the like and extend it.
But you’re not there yet. First, you’ll want to play with Elastic Beanstalk.
Launching
To launch an application, you start by selecting the platform – Tomcat, IIS, Node, PHP, Python, Ruby – or you can customize the platform yourself, which makes it a nice fit if you’re building the a platform for, say, massive online coding schools, and you just want people to be able to spin up the right environment, or any situation in which you want people to be able to spin up from your config.
To keep things simple, select PHP and … that’s it … it's already launching. The UI whirls while your environment boots.
While this is happening, have a look around at what you’ve got, and you’ll notice the individual services of AWS being used to host the application. Notice Beanstalk calls it the “application,” not instance. This is deliberately a level up from the normal nuts-and-bolts.
Again, if you’ve looked at Heroku, the core concepts are similar. The environment is wrapped up for you. You have a CLI tool to push to. Scaling happens out of the box. Like EC2 and other AWS services, monitoring and events show up in their respective tabs; however, unlike Heroku, Elastic Beanstalk (EBS) exposes the underlying technology used to power it, which gives them license to bill it as being “impossible to outgrow.”
EBS is free because it’s simply a wrapper for the existing AWS services. Although this method might make it very attractive for prototyping and rapid deployment, costing it becomes a little more fiddly than with other PaaS offerings.
Setting Up the Environment
You need the eb CLI tool, which you unzip somewhere (e.g., ~/bin/eb/), then change your path to include the path to eb:
export PATH=$PATH:~/bin/eb/eb/macosx/python2.7
First, you must create a Git repo,
git init . git add . git commit -m "Starting..."
then init the eb tool with:
eb init
Enter your AWS access key ID and your secret key, then choose a region and name the app. I’m naming mine DanApp for the purposes of this exercise. Accept the environment name as given. The next option is much like the GUI: Choose 64bit Amazon Linux running PHP 5.4, which for me was option 2:
1) 32bit Amazon Linux running PHP 5.4 2) 64bit Amazon Linux running PHP 5.4 3) 32bit Amazon Linux running PHP 5.3 4) 64bit Amazon Linux running PHP 5.3 5) 32bit Amazon Linux running Node.js 6) 64bit Amazon Linux running Node.js ...
Don’t create an RDS instance this time, so type n for that option; however, notice how easy launching a whole DB-backed application would have been. That’s some fun for you to have on your own later.
In a moment, you’ll launch this killer empty app, but before then, take a look around the eb CLI tool:
$ eb --help ... COMMAND init, branch, start, status, update, stop, delete, logs, events, push ...
The status gives a quick summary of what’s going on with your environment. At the end of this tutorial, you should shut things down so you can check that everything’s dead by using:
$ eb status Environment "DanApp-env" is not running.
To do something interesting, start the environment:
$ eb start Starting application "DanApp". Would you like to deploy the latest Git commit to your environment? [y/n]: y
Booting this is much like booting anything with Cloud Formation – it can take a while for the instances to come to life and get IPs and for everything to complete. While this is booting, you can poke around in the web UI and look at the progress, just as when you launched through the web UI.
When done, this is what you should have seen:
ElasticBeanstalk git:(master) eb start Starting application "DanApp". Would you like to deploy the latest Git commit to your environment? [y/n]: y remote: remote: error: Unable to deploy application version: No Environment found for EnvironmentName = 'DanApp-env'. remote: To https://AKIAJ2XDUJ2NAFXXXXXXXX: XXXXXXa9a9fe7e0fd7XXXXXXXXa94d94942@git.elasticbeanstalk.eu-west -1.amazonaws.com/v1/repos/44616e417070/commitid/ 6335366636313033613837366239366230396534333832386564323637313461 6533383837653130/environment/44616e4170702d656e76 * [new branch] HEAD -> master Waiting for environment "DanApp-env" to launch. 2013-05-08 20:02:27 INFO createEnvironment is starting. 2013-05-08 20:02:32 INFO Using elasticbeanstalk-eu-west-1-894012917938 as Amazon S3 storage bucket for environment data. 2013-05-08 20:03:03 INFO Created load balancer named: awseb-e-m-AWSEBLoa-OXVMML7XC6PR 2013-05-08 20:03:27 INFO Created security group named: awseb-e-mnpsy5bpzk-stack-AWSEBSecurityGroup-18JDKTE9QITLU 2013-05-08 20:03:32 INFO Created Auto Scaling launch configuration named: awseb-e-mnpsy5bpzk-stack-AWSEBAutoScalingLaunchConfiguration- 1QR56F972DMG2 2013-05-08 20:04:57 INFO Created Auto Scaling group named: awseb-e-mnpsy5bpzk-stack-AWSEBAutoScalingGroup-12BAR59E5FUDM 2013-05-08 20:04:57 INFO Waiting for EC2 instances to launch. This may take a few minutes. 2013-05-08 20:07:45 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:eu-west-1:894012917938:scalingPolicy: 927c9769-d96e-46ba-b08f-099650ae7a3d:autoScalingGroupName/awseb- e-mnpsy5bpzk-stack-AWSEBAutoScalingGroup-12BAR59E5FUDM: policyName/awseb-e-mnpsy5bpzk-stack- AWSEBAutoScalingScaleDownPolicy-KW4NGGQ0LULU 2013-05-08 20:07:48 INFO Created CloudWatch alarm named: awseb-e-mnpsy5bpzk-stack-AWSEBCloudwatchAlarmLow-14SOWYQGJ2F5X 2013-05-08 20:07:51 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:eu-west-1:894012917938:scalingPolicy: 22724a85-a99c-4a05-a66a-cb56a70f54e7:autoScalingGroupName/awseb- e-mnpsy5bpzk-stack-AWSEBAutoScalingGroup-12BAR59E5FUDM: policyName/awseb-e-mnpsy5bpzk-stack- AWSEBAutoScalingScaleUpPolicy-1ETLUW450U2V1 2013-05-08 20:07:53 INFO Created CloudWatch alarm named: awseb-e-mnpsy5bpzk-stack-AWSEBCloudwatchAlarmHigh-198IBXQXHBDPH 2013-05-08 20:09:25 INFO Application available at DanApp-env-ceqwdhduep.elasticbeanstalk.com. 2013-05-08 20:09:25 INFO Successfully launched environment: DanApp-env Application is available at "DanApp-env-ceqwdhduep.elasticbeanstalk.com".
What just happened? Using my AWS keys, the code was pushed to a Git server running on Elastic Beanstalk. Beanstalk then starts the launch, which involves creating an S3 bucket, launching the EC2 instance, and creating the autoscaling groups and some monitoring. All this is done for me, so I don’t really have to worry about what’s going on.
When the environment is running, you’ll have a URL like http://DanApp-env-ceqwdhduep.elasticbeanstalk.com/, which delivers a basic page – whatever you put into your app.
Updates Are More Interesting
To update the app, edit anything – create some files, add some HTML, whatever you like – then git add, commit it, and then push using:
git aws.push ElasticBeanstalk git:(master) git aws.push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 331 bytes, done. Total 3 (delta 0), reused 0 (delta 0) remote: To https://XXXXX:XXXXX@git.elasticbeanstalk.eu-west-1.amazonaws.com/v1/repos/44616e417070/commitid/37346533646166656662386330633434363938363361616635383863363963356164326535346466/environment/44616e4170702d656e76 c56f610..74e3daf HEAD -> master
Your app is updated. For hacking something together quickly, this can be a dream. Bash it out locally, spin up a Beanstalk application and git aws.push a few times until it’s done.
After pushing each time, you visit http://<your app URL>/ in your browser again and there it is. Sometimes updating took a few minutes until I eventually added http://danapp-env-ceqwdhduep.elasticbeanstalk.com/?junk=123 to jog whatever cache was in the way into giving me an updated version.
Give It a Poke
You can poke around a bit and have some fun by uploading a script like:
(Adjust this to whatever language you’re using – just throw out the environment variables to see what's going on, on that server.) You can see the environment with $_SERVER['/var/www/html/index.php'].
Git and Branches
One server is cool, but what about an application server for each branch, so you can push to one for development and another for stable? Start by checking out a new branch,
$ git checkout -b stable
then ask eb what’s going on:
$ eb status The current branch "stable" is not associated with an Elastic Beanstalk environment. Call "eb branch" to set up a new environment for this branch. Proceeding with default settings. URL : DanApp-env-ceqwdhduep.elasticbeanstalk.com Status : Ready Health : Green
Ok, eb, I’ll do that:
$ eb branch The current branch is "stable". Enter an AWS Elastic Beanstalk environment name (auto-generated value is "DanApp-stable-env"): Do you want to copy the settings from environment "DanApp-env" for the new branch? [y/n]: y
So where are you now?
$ eb status Environment "DanApp-stable-env" is not running.
You know what to do about that: Start it up:
$ eb start ...the usual stuff
Now pause to realize that you’ve just changed branch, copied the *entire stack config*, and launched a clone of the live environment in a few lines. That is neat and means that when you try something, much as with a new way of caching on the homepage or logging in with Twitter, you can spend an extra couple of minutes sending it to your team to see what they think. When they say – “but will it work on the live servers?” – you can say, “yes,” because you know it will.
While you’re waiting, you can see two environments in the AWS web console. The start-up is the same set of steps, but it’s interesting to see that this is the stable version:
Starting application "DanApp". Waiting for environment "DanApp-stable-env" to launch. 2013-05-08 20:20:43 INFO createEnvironment is starting. 2013-05-08 20:20:48 INFO Using elasticbeanstalk-eu-west-1-894012917938 as Amazon S3 storage bucket for environment data. 2013-05-08 20:21:04 INFO Created load balancer named: awseb-e-h-AWSEBLoa-1118ULBZLSFGH 2013-05-08 20:21:34 INFO Created security group named: awseb-e-hxaxpp3bsa-stack-AWSEBSecurityGroup-ZNUGTMANJ7WO 2013-05-08 20:21:40 INFO Created Auto Scaling launch configuration named: awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingLaunchConfiguration-12RI7463WQWE3 2013-05-08 20:23:25 INFO Waiting for EC2 instances to launch. This may take a few minutes. 2013-05-08 20:23:25 INFO Created Auto Scaling group named: awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingGroup-1NMEE2RF9GMBP 2013-05-08 20:25:11 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:eu-west-1:894012917938:scalingPolicy:8bc35c42-856d-4848-8111-9ec4e4df0fcf:autoScalingGroupName/awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingGroup-1NMEE2RF9GMBP:policyName/awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingScaleDownPolicy-179VH5P3Y0VH9 2013-05-08 20:25:13 INFO Created CloudWatch alarm named: awseb-e-hxaxpp3bsa-stack-AWSEBCloudwatchAlarmLow-1Q23UL8HF2B6K 2013-05-08 20:25:16 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:eu-west-1:894012917938:scalingPolicy:732bdc0c-4734-4d27-b02e-99d716c66dc6:autoScalingGroupName/awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingGroup-1NMEE2RF9GMBP:policyName/awseb-e-hxaxpp3bsa-stack-AWSEBAutoScalingScaleUpPolicy-1Q75QYV2QAY6X 2013-05-08 20:25:18 INFO Created CloudWatch alarm named: awseb-e-hxaxpp3bsa-stack-AWSEBCloudwatchAlarmHigh-1AD9DJ2JI6IPZ 2013-05-08 20:26:56 INFO Application available at DanApp-stable-env-3jhebnynie.elasticbeanstalk.com. 2013-05-08 20:26:56 INFO Successfully launched environment: DanApp-stable-env Application is available at "DanApp-stable-env-3jhebnynie.elasticbeanstalk.com".
To get my app to appear at DanApp-stable-env-3jhebnynie.elasticbeanstalk.com, I need to push to it with
$ git aws.push Pushing to environment: DanApp-stable-env Counting objects: 7, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (7/7), 589 bytes, done. Total 7 (delta 0), reused 0 (delta 0) remote: To https://AKIAJ2XDUJ2NAFFPK5SA:20130508T193045Z74f087d7af6327f3447173d8dba5de13b9c695da67033b955885c5cb4a7226b1@git.elasticbeanstalk.eu-west-1.amazonaws.com/v1/repos/44616e417070/commitid/37346533646166656662386330633434363938363361616635383863363963356164326535346466/environment/44616e4170702d737461626c652d656e76 + 04156e4...74e3daf HEAD -> master (forced update)
and wait a couple of minutes. I now have two environments running, each running its own code, and each running its own virtualized hardware – and you haven’t configured a single thing.
Clean Up, Kill It All, and Rest
To finish, ruthlessly go through, using eb delete. until everything is dead; then, sit back and enjoy how little work it took to launch so much stuff.
It’s kind of mad that AWS throws out stuff that feels too bare, when they could ship things like this that are wrapped up a little more. Using Elastic Beanstalk has been the easiest and most sensibly integrated system in AWS I’ve seen, yet it feels tucked away. While this example launched, it gave me time to think about how this method is a much better way to get into AWS. Don’t start with EC2. Don’t start with Cloud Formation. Start with EB, because you get to experience the performance of AWS yet save yourself days of getting things to work.