Deploying rails apps on ec2 with impunity
25 Nov 2011
There’s no shortage of deployment systems for rails/rack applications, and the learning curve for many of them makes it a fairly difficult task for choosing the ‘right one.’ You can find a pretty complete list here at ruby-toolbox.com. I’ve used Capistrano professionally enough in the past that I knew I didn’t want to open that can of worms for my new employer (Gild).
I toyed around with vlad, rubber, and whiskey_disk. I’ll get to my decision later, but while these were much simpler than capistrano, they still required me to deal with the constraints of someone else’s idea of configuration, and breaking my mental rule of keeping configuration seperate from code. I’ve always had the notion that Ruby is and its various frameworks are comfortable with the ‘UNIX way,’ and every one of these systems seemed to break that.
Deployment should be dead simple, especially when we’re talking about virtualized environments that let you set plenty of metadata and have awesome APIs for every language. I want to make these app servers as light as possible. Not running chef-client or puppetd constantly, minimal set of packages, and no passwords (keys only). Chef-solo and git are enough for complete configuration management, and believe it or not, enough for managing deployment, too. Chef has this built in.
I’ll admit, we were already using chef for all of our configuration, why not use it for this, too?
All I have to do now, is use Net::SSH to send over a JSON file for chef to run against for deployment, which is as easy as taking my big YAML file that describes my environments and applications ‘.to_json.’ Using AWS’s RDS and load balancer service in front of my apps means, I basically just maintain my http stack, nginx and unicorn, and other than kernel processes, that’s pretty much all that’s running on my VMs. I can nuke them without fear, I can rebuild and change my environments quickly, and managing deployment configuration is in the same place as I manage all my other configuration. The nodes in app clusters are aware of each other through a ec2 instance I have running dnsmasq that updates itself through ec2 api calls, and that’s pretty much my only infrastructure.
Run this in a cron on the dnsmasq server:
Then you can query in your deployment/chef/vm init scripts with:
The rest is all details, describe your environment in yaml, push it to your hosts as json, and run chef against it all via Net::SSH. I wrote a simple CLI app for deploying ar apps using Trollop.