Capistrano – Deploy to servers from different load balancers

Posted on Aug 8, 2011

As I posted back on March 14th, I work at Gogobot, an app that connects you with your friends all over the world and helps you plan your next new travel.

At Gogobot we are working with Capistrano to deploy our production and to our staging servers.

Recently, we changed out architecture and we now have user facing production servers (where you see the pages coming from) and backend servers that run delayed_jobs, resque, photos uploading and many more things that have no business in affecting the load of the user experience.

So, of course we did not want to deploy twice, once for the http servers and once for the backed servers, so I changed the deploy script.

The important thing to understand is that due to loads, we don’t just write the server DNS’s in the deploy script, we change the number of servers constantly so we want to do it very dynamically and just grab the servers from the load balancer that it’s attached to.

For example, if we have 100 servers on the front end and 50 servers on the backend, we will deploy to 150 servers and tomorrow that number can change, and we will need no change in the deploy script.

This is the deploy script part that handles the servers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def fetch\_from\_ec2
      
require ‘right_aws’
      
instances\_for\_deploy = []

[backend\_load\_balancer, aws\_load\_balancer].each do |load_balancer|
        
payload = elb.describe\_load\_balancers(load_balancer)
        
instances = aws.describe_instances payload.first[:instances]
        
instances\_for\_deploy += instances.collect{|instance| instance[:dns\_name] if (instance[:aws\_state] == ‘running’)}
      
end
      
instances\_for\_deploy
  
end
  

This is the target of capistrano:

1
2
3
4
5
  
role :app do
    
ENV[‘TARGET’] || fetch\_from\_ec2
  

So, if there’s an ENV variable defined called ‘TARGET’ the script will only deploy to this server, if not, it will deploy to all of the servers from the load balancers.

Now, in the production.rb in your deploy folder, all you need is to define the load balancer names:

1
2
3
4
5
  
set :aws\_load\_balancer, "prod-load-balancer-name"
  
set :backend\_load\_balancer, "backend-load-balancer-name"