Run clockwork only on one production instance (rails capistrano) - ruby-on-rails

I have a production server with two instances app1 and app2 to which I use capistrano to deploy my application, ie: cap app1 deploy, cap app2 deploy.
I am now configuring the clockwork to schedule my delayed jobs. But what happens the jobs are scheduled twice, because the clockwork process runs on both app1 and app2 after application is deployed.
How can I force the capistrano to run the clockwork process only on app2 ?
Thanks for a hint.
Miroslav
SOLUTION
Add the following settings into the deploy.rb:
set :clockwork_role, :clock
And then configure only one of the instances to use the role :clock, ie:
server 'URL', user: 'deploy', roles: %w{app db web clock}

In your case you can set some config variable to true in one case, and to false in the second, and check it when setting clockwork.
But want to mention that you are using different 'stages' (which are usually 'staging', 'production', 'qa', 'features', etc) for the different servers of one stage.
Capistrano has 'roles' (app, db, background jobs, etc) each can have several servers.
Also please mention which capistrano version you're using - there were big changes from 2 to 3

Related

Capistrano deploy one server at a time

I am using capistrano for our RAILS deployment. We want to deploy to one server first, and after deployment is finished on the first server, then we want to start deployment on second server. We do not want restarting in sequence with delay. We want to have complete deployment one at a time. So far I have this:
namespace :deploy do
task :sequence do
on roles(:app), in: :sequence do |host|
invoke 'deploy'
end
end
end
The problem is with invoke 'deploy'
It calls deploy for all the app servers which in turns deploy in parallel.
Finally How Do I invoke deploy task for a specific host?
Following should help you to run the deploy task in sequential mode:
task :my_task, roles: :web do
find_servers_for_task(current_task).each do |server|
run "YOUR_COMMAND", hosts: server.host
end
end
If I had that requirement, I'd probably script it. You can run Capistrano with the --hosts parameter to define which of the servers you described in your stage file (config/deploy/dev|stage|prod|somethingelse.rb) you actually want to run the command against. This can take two forms. Let's say I have three servers, test1, test2, and prod1. I can run it with a list, like cap prod --hosts=test1,test2 deploy and only test1 and test2 will receive the deployment. You can also use a regular expression to achieve the same thing, like cap prod --hosts=^test deploy.
This is documented here: http://capistranorb.com/documentation/advanced-features/host-filtering/
With this in mind, I'd probably write a script (or Makefile) which runs capistrano N time, for a different server each time.

Local configuration for multinode rails applications

I'd like to introduce per-machine configuration to my rails application. It's currently deployed with Capistrano, and I need to introduce at least one machine-specific variable -- a hostname, so that performance characteristics can be properly tracked. In the future, there are likely going to be further local differences. The code is deployed to a 3 node load balanced cluster from the same git repo.
What is the best way to manage machine specific config?
You can set environment variables in Capistrano config file, and fetch it in your rails app.
config/deploy/.rb
%w[
node1.example.com
node2.example.com
node3.example.com
].each do |host|
server host, roles: %w[app], default_env: {hostname: host}
end
Then you can access the hostname with ENV['HOSTNAME'].

Capistrano appserver as service without sudo

Does anyone have a good way to manage the appserver with capistrano?. This seems to be a leave it to your own devices situation, and I've yet to see a good example of it.
There is basically two trains of thoughts I see.
1) Daemonize it as the deploy user. Pros, no system service etc, so no permissions issues. However this wreaks as if the machine is rebooted, blam the system goes down.
2) Init scripts. Installing a init script and using that to manage the server. This would survive reboots, and allow for say /etc/init.d/myapp restart/stop/start control if you ssh'd in. This is decent apart from two reasons
Most people manage it from capistrano with sudo (I feel like capistrano 3 discourages this)
I've yet to see a good upstart or the like script that works with unicorn for it.
I'm experimenting with using nginx+unicorn. Nginx I have set perfectly. I've added a site to sites-available and pointed upstream to /appserver/public. This works great, asset precompilation works fantastic and all is well, I can redeploy and be served new assets. It's simple, works with the OS init process. However I've lucked out as the nginx config is basically static, and nginx only has to serve static files.
The appserver.. unicorn/thin/puma/ whatever is the part thats tripping me. I would like it to reload the application on cap deploy, but I'm struggling to find a good enough example of this.
In summary. What is a simple way of having a rails application survive reboots, and reload when cap deploy is called
If you use Passenger with your nginx and unicorn or thin... you can restart after deployment by touching tmp/restart.txt file:
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute :touch, release_path.join('tmp/restart.txt')
end
end
To reload a puma server after deploy use capistrano3-puma:
Gemfile:
gem 'capistrano3-puma'
Capfile:
require 'capistrano/puma'

Running Capistrano tasks only for certain roles

My project has a multi-step pipeline that includes some steps like Crawling, NLP, etc, but I'll just refer to them as Step1, Step2, etc. Additionally I want to be able to deploy to different environments (dev, prod, etc).
I figure I'll use multistage component for Capistrano in order to deploy to the different environments (e.g. cap dev deploy vs cap prod deploy).
It also seems to make intuitive sense to use roles for each pipeline step. However, each step runs fairly independently of the rest of the pipeline, so each step can be restarted/deployed independently of the other steps. It doesn't seem like Capistrano explicitly supports running tasks only for a specific role. What's a good way to do this?
Is the best way of doing this defining tasks specifically for each role? What if there are some tasks common between roles? Maybe helper methods is the answer there?
Not sure this is exactly what you are looking for, but when I want to do something just to a particular role, I use the capistrano shell. For example, let's say I want to deploy but only to my app servers, I might do the following:
cap production shell
cap>with app
cap>!deploy #or any other cap task you have
You can also scope by machine if you want. Again:
cap production shell
cap>on <machine name or ip>
cap>!deploy #or any other cap task you have
Hope it helps,
Scott
If you want to run a capistrano task from the command line, but only for a subset of defined roles, you can use the ROLES parameter.
The command below executes the task category:task only for role was:
cap ROLES=was category:task
The ROLES parameter is multivalued, so you can add more roles separated by a comma:
cap ROLES=was,db category:task
For more details, you can refer to the invoke documentation
Check this discussion Creating a Capistrano task that performs different tasks based on role
task :stop_memcached, :roles => :memcache do
...
end
Not sure at what version the feature was added, but cap will look in the ROLES environment variable to determine which roles to run so
$ ROLES=db cap deploy

whenever gem have cronjob on only one machine?

We have a large deployment of around a dozen servers. We'd like to use the Whenever gem but I can't figure out a way to say which machine the cron jobs should go on! We only want these jobs to run on our server that does background jobs.
Is there a way to specify this?
If you deploy the project with Capistrano and you use the default Whenever recipe, you can create a new Capistrano role
role :whenever, "192.168.1.1"
and set the role in your deploy.rb file
set :whenever_roles, "whenever"
In this way, the task will be executed only on the specified server.
whenever is preconfigured to run against the db role, so if your db role is also the background machine's role you don't have to do the 'role :whenever, "192.168.0.1"' hack. see the codes
https://github.com/javan/whenever/blob/master/lib/whenever/capistrano.rb#L2

Resources