Capistrano is the tool typically used to deploy Ruby applications. It is not however the best option when deploying software in the cloud.

Do not take me wrong. Capistrano is a great tool. It works very well when deploying an application to a small number of servers with the static IP addresses, e.g. when staging and production environments consist of dedicated servers. Deploying in the cloud however creates some unique deployment challenges:

  1. Servers may go down and the new servers launched to replace them will run on different hardware with a different set of IP addresses.
  2. You may want to set up a dynamically scalable server array where servers are added and terminated automatically based on the application load.

To address these challenges you need a self-contained deployment process which gets an application running on a server upon launch without manual intervention such as release master fiddling with the IP addresses or running ‘cap deploy’.

Our Setup

We are running a set of servers on Amazon including a dynamically scalable array of EC2 application servers. In building our infrastructure we leveraged RightScale which adds a management layer on top of the Amazon services. Using RightScale you can create server templates which combine Amazon machine images (AMIs) with a set of configurable scripts (RighScripts) which for example can be invoked on server launch. To make it even easier, they have a fairly comprehensive set of pre-built server templates.

To build our application server template we started with a RightScale template and substantially modified it to suit our needs. On launch, at a high level, our servers run the following sequence of scripts:

  • Install SSH keys
  • Install Ruby
  • Install Nginx/Passenger
  • Create application directory structure
  • Install and configure git
  • Checkout application code from github
  • Create database.yml file
  • Install gems
  • Install monitoring agents
  • Start delayed_job
  • Connect application to the load balancers

For example a script to create database.yml file looks like that:

#!/bin/bash -ex
# Create database.yml for a Ruby on Rails application
# Storing database.yml in a source code control system with its production database credentials creates a security risk.
# Using this script, you can take advantage of the RightScale's secure credentials store and generate the file when an application server is launched.

# If this is a reboot skip this script
if test "$RS_REBOOT" = "true" ; then
logger -t RightScale "Skip RB create database.yml."
exit 0
fi

# Create database.yml file
cat webapps/$APPLICATION/shared/system/config/database.yml
$RAILS_ENV:
adapter: mysql2
host: $MASTER_DB_DNSNAME
port: 3306
encoding: utf8
reconnect: false
database: $DB_SCHEMA_NAME
pool: 5
username: $DBAPPLICATION_USER
password: $DBAPPLICATION_PASSWORD
EOF

ln -nfs /home/webapps/$APPLICATION/shared/system/config/database.yml /home/webapps/$APPLICATION/current/config/database.yml

logger -t RightScale "database.yml created."

The script is also available at https://gist.github.com/1132976.

Summary

When deploying Ruby applications in the cloud, you need an ability for servers to fully bootstrap themselves – including getting an application up and running. Rather than using Capistrano, you may want to develop a set of scripts to execute the application deployment tasks automatically, as part of the server launch sequence.

About these ads