Elastic Beanstalk: Advantages and Drawbacks
At Artefact, we are always working on new types of projects and experiences, which means we’re also constantly on the lookout for software and services that will help us quickly and reliably build out these new solutions. Recently, we used AWS Elastic Beanstalk to manage the web servers that power or SaaS projects. Specifically, these are two dynamic web-based platforms that power internal innovations and creativity. In this post, I’ll detail how we used it and what’s gone well, as well as what hasn’t, so you can decide if it’s the right tool for your needs.
First, let’s start with the basics: According to the AWS site, “Elastic Beanstalk makes it even easier for developers to quickly deploy and manage applications in the AWS cloud. Developers simply upload their application, and Elastic Beanstalk automatically handles the deployment details of capacity provisioning, load balancing, auto-scaling, and application health monitoring.”
Now that we have that out of the way, let’s get to the good stuff!
Elastic Beanstalk’s main benefits include timesaving server configuration, powerful customization, and a cost-effective price point.
Lightning Fast Configuration with Automation
Elastic Beanstalk automates the setup, configuration, and provisioning of other AWS services like EC2, RDS, and Elastic Load Balancing to create a web service. You can log into your AWS management console, and have a new site up and accessible in less than an hour. Elastic Beanstalk also creates a fairly standard configuration for a modern Rails application.
This automation can save precious time by handling all the things that need to be completed for a production app (configuring log file rotations, nginx config files, puma service configuration, linux package installation, ruby installation, load balancer configuration, and database setup). There are more services like Heroku, Engine Yard, and others that do this as well, but in general, we found Elastic Beanstalk was on par and had a good standard setup, especially when you factor in its price. These are some of the specifics on the configuration:
- Support: AWS Elastic Beanstalk supports Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker web applications.
- Rails Servers: For Rails, you can run either a Passenger or a Puma application stack — we’ve only used Puma so far, and the servers will be configured by Elastic Beanstalk to run a Puma process (with Nginx used as a reverse proxy in front of it) and a reasonable server configuration for log files, directory security, and user security.
- SQL server: This is configured through Amazon RDS, but at its heart is a EC2 server with a database running on it. We’ve used both postgres and Mysql.
- AWS Elastic Load Balancer: Running and with the correct configuration for the Rails servers.
- Security: New AWS security groups and policies are created, along with permissions for these services to securely talk to each other. All the servers are configured so they can only talk to and have permissions for what they need. For example, your Rails servers have just one port open specifically for the load balancers, and nothing can talk to your DB server, except for your Rails servers. This is fantastic, because it can be hard to do correctly on your own.
- Default Configuration: ENV variables on the Rails servers that securely set secrets needed for Rails to run — like Database endpoint, username, and password. This is also helpful, because figuring out a secure way to do this on your own can be a pain and is easy to get wrong.
- Custom Configuration: An easy and secure way (either in the Elastic Beanstalk UI or through the AWS command line tools) to set custom ENV variables. For example, you can set your Mailchimp account and password and have it accessible to your running Rails code as an ENV variable.
- Monitoring: Basic monitoring of your servers through Cloudwatch.
- Deployment: Easy deployment of new versions through AWS CLI. Once configured, you run `eb deploy` from the root of your git repository, and the deploy just works. This was also easy to integrate with Codeship, a Continuous Integration service that we used.
Elastic Beanstalk’s automated configuration helps avoid mistakes that happen from missing small details when you try to DIY. These are great boilerplate specs that you typically look for when using a service like this because they can be pretty tricky to get right on your own.
With Elastic Beanstalk, it’s all under your control. Everything that is created is just an AWS service — so you can look at EC2, see the new instances, and ssh into them. You can update your database config file. You can update the security group for all of the machines, so that, for example, the entire application is only accessible from your office IP address.
While at some level this is a similar service to Heroku, it also gives you more low level access and control. Customization is more complicated, but much more flexible and powerful than using Heroku. For example, when we wanted to add sidekiq, it wasn’t straightforward (but possible) — that’s another post for another time.
Price and Flexibility
Elastic Beanstalk’s price and flexibility are great. The platform itself is nothing, so there is no extra charge on top of the AWS services you’re using. Also, because you can pick your instance size, as well as easily add more front-end servers to the load balancer, you can easily match your server needs to your service load. Elastic Beanstalk even has auto-scaling functionality built in, which we never used, but would be a great way to save money for larger applications by only bringing up extra servers when needed. Overall, our costs on a application with a similar size and scope we built during the same timeframe was 400% higher on Heroku vs. Elastic Beanstalk. Although each application is different, it’s a good ballpark comparison.
Some of the biggest pains with Elastic Beanstalk include unreliable deployments, lack of transparency and documentation around stack and application upgrades, and an overall lack of clear documentation.
We do a lot of deployments — we have a continuous integration setup via Codeship, so with every commit (or merged pull request), if tests pass, we deploy a new version. We practice small, incremental changes and strive to be as nimble as possible. Some days, we might deploy 10 times.
Over the last year or so of using Elastic Beanstalk, our deploys have failed five or six times. When the failure happens, we get no indication why, and further deployments will fail as well. On the positive side, this didn’t result in downtime for us. We simply couldn’t deploy, and if we tried again it would fail.
Each time, we needed to troubleshoot and fix on our own. We found and tried multiple solutions, such as terminating the instance that had the deployment issue, and let Elastic Beanstalk recover. Sometimes, we could ssh into the stuck machine, kill a process that was part of the eb deploy, the machine would recover. But overall, we didn’t know what failed, and it’s never a good thing to not be sure that your machine is in a good state.
Considering we have done over 1000 deployments, this isn’t a high failure rate. It never hit us at a critical time, but what if this happened when we were trying to do a hotfix for a performance issue that was crippling our site? Or, what if we had larger sites with more than two or three front-end servers? Would this increase our deployment failure rate? For the two applications we have done, we decided that the risk of this happening was small and that it didn’t warrant switching to a new service. For some applications this would not be an acceptable risk.
Deployments would take five minutes at least, and sometimes stretch to 15, for a site with just two front-ends. With more servers, deployments could take even longer. This might not seem like much, but we have setup other Rails environments where deployment can be done in one or two minutes. And this can be critical if you are trying to be responsive in real-time.
Attempts have been made to improve the Elastic Beanstalk deployment process, and a good summary to start with is this post from HE:labs. We may try some things from there in the future.
Elastic Beanstalk comes out with new stack versions all the time — but we have zero information on what has changed. No release notes, no blog post, not even a forum post. Sometimes, it’s obvious — the version of Ruby or Puma will change. But other times, it’s just an upgrade. We’ve done several upgrades, and sometimes it goes smoothly, and sometimes it takes a week.
Old Application Versions
Another thing we learned is to occasionally delete old application versions. With every deploy, Elastic Beanstalk archives the old application version in an S3 bucket. However, if there are 500 old versions, further deploys fail. You can delete them through the Elastic Beanstalk UI, but this caught us off guard multiple times. Although this seems like a small problem, I really don’t like it when deployments fail.
All of these problems are an indication of Elastic Beanstalk’s general lack of transparency. We had to figure out a lot of these issues on our own and through blog posts and internet searches. On the plus side, we had complete transparency into EC2 instances, database, and other services created, so we were free to learn on our own. And while stack upgrades and failed deployments are the most clear moments of pain, in general they were indicators of the types of things that you have to learn on your own.
Elastic Beanstalk helps us to easily deploy updates to our Rails application while also leveraging Amazon’s powerful infrastructure. Enhancing our deployment process with containers — like Docker — will add even more versatility. Thanks to the fine-grain control offered by Elastic Beanstalk we get to choose technologies that work best for us. Ultimately, we found the most helpful thing about Elastic Beanstalk to be that its automation features let us easily deploy updates to our Rails application. While it’s certainly not a perfect tool, if you’re looking to reduce system operations and just focus on what you’re developing, Elastic Beanstalk is a solid choice.