Reputation: 6198
I am using Capistrano 2.15.5 to deploy Java web applications to Tomcat application servers. For the time being, we are tied and committed to this version of Capistrano and we cannot upgrade to v3. The deploy task will call on the other tasks to get executed in parallel on all servers in the role. This works as expected and has been working well for a while.
Now we need to implement a Rolling Deployment when the tasks are executed on one server at a time. So, based on the code below, we would execute shutdown_tomcat, download_bits, deploy_bits, start_tomcat
on prdapp01
first and then prdapp02
and so on... So that only one server in the cluster is offline at any given time, thus maximizing our uptime.
What is the best way to implement this Rolling Deployment strategy with Capistrano?
This is what a paired-down version of my Capistrano script looks like currently:
task :production do
role :app, "deployuser@prdapp01", "deployuser@prdapp02", "deployuser@prdapp03"
# ...
end
task :deploy do
shutdown_tomcat
download_bits
deploy_bits
start_tomcat
end
task :shutdown_tomcat, :roles => :app do
run "sudo /sbin/service tomcat stop || exit 1;"
end
task :download_bits, :roles => :app do
run <<-EOS
[ -f /tmp/app_download ] && rm -rf /tmp/app_download;
mkdir -p /tmp/app_download;
cd /tmp/app_download;
wget -q https://internal.server/path/to/application.war || exit 1;
EOS
end
task :deploy_bits, :roles => :app do
run <<-EOS
cd /tmp/app_download;
unzip -q -o /tmp/app_download/application.war -d /usr/local/tomcat/webapps/ || exit 1;
exit 0;
EOS
end
task :start_tomcat, :roles => :app do
run "sudo /sbin/service tomcat start || exit 1;"
end
Upvotes: 2
Views: 2453
Reputation: 6198
I believe that I came up with a reasonable solution to the Rolling Deployment strategy I described above. First, I pass in to Capistrano an argument telling it what deployment type I want to perform: Full or Rolling. Then I follow this process:
Here are the relevant changes to the deploy
task:
task :deploy do
deploy_type = fetch(:deploytype).downcase
case deploy_type
when 'full' then
shutdown_tomcat
download_bits
deploy_bits
start_tomcat
when 'rolling' then
server_list = roles[:app].servers # get the original servers
server_list.each do |current_server| # apply other tasks in series
roles[:app].servers = [] # reset original server list
role :app, "#{current_server}" # otherwise you'll append to it
shutdown_tomcat
download_bits
deploy_bits
start_tomcat
end # each loop
else
puts 'Invalid deployment type'
exit
end # case deploy_type
end # task :deploy
Then you can invoke it with the following command:
$ cap -f deploy.cap -s deploytype=rolling production deploy
Feedback is appreciated!
Upvotes: 2