Chef - Trigger reboot service on different node

2019-09-08 14:25发布

问题:

I have a master node and client nodes for some application that I want to manage with Chef. They all pointing to one shared folder with configuration file that contain info about all the clients and a master. Thus, app on master node should be reloaded/rebooted each time a client app (on another client node) is installed - and its hostname added to that one shared file.

Any ideas how can I trigger restart of the Master app on Master node from a client node?

回答1:

Stop using a shared file, this is a SPOF in your architecture and subject to very very very much concurrency problems.

Chef has a feature for this, it is search.

With this in mind I would do something along the line of having two recipes in your my_app cookbook, named master.rb and client.rb

In client.rb in addition to installing the client, add a tag to the node. (or use a role to define which are clients, etc)

tag('my_app_client') if !tagged?('my_app_client')

master = search(:node, 'tag:my_app_master') 
slaves = search(:node, 'tag:my_app_client') 

#Tricky line to add current node to the list of slaves, as in first run it won't have been indexed by chef.
slaves[] << node if !slaves.any? { |n| n['hostname'] == node['hostname'] } 

return is master.empty? # to avoid trying to write a file without master

template '/local/path/to/conffile' do
  source 'config.erb' 
  variables({ 
    :master => master
    :slaves => slaves
  })
end

in master.rb, repeat the search and templating:

tag('my_app_master') if !tagged?('my_app_master')

master = search(:node, 'tag:my_app_master') 
slaves = search(:node, 'tag:my_app_client') 

#Tricky line to add current node as the master, as in first run it won't have been indexed by chef.
master = node if !master.any? { |n| n['hostname'] == node['hostname'] } 

template '/local/path/to/conffile' do
  source 'config.erb' 
  variables({ 
    :master => master
    :slaves => slaves
  })
  notify :restart,"service[my_app_service]", :immediately
end

And in the config.erb file for example:

master_host: <%= @master['hostname'] %>
<%- @slaves.each_with_index do |s,i|
  slave_host<%= i %>: <%= s['hostname'] %>
<%- end %>

There's some indexing delay to manage, and probably the files on each macine could be a little out of sync if the chef-run order is not carefully planned.

If you keep chef running periodically, it will converge your entire cluster within twice the run interval at maximum.