Skip to content

Instantly share code, notes, and snippets.

@ianunruh
Last active September 27, 2020 17:54
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ianunruh/f4a306ff80cdfcab01c1 to your computer and use it in GitHub Desktop.
Save ianunruh/f4a306ff80cdfcab01c1 to your computer and use it in GitHub Desktop.
Join RabbitMQ to cluster via Consul
#!/usr/bin/env ruby
require 'json'
require 'net/http'
require 'optparse'
require 'ostruct'
options = OpenStruct.new
options.service_name = "rabbitmq"
options.port = 8500
OptionParser.new { |opts|
opts.banner = "Usage: join-rabbitmq-cluster.rb [options]"
opts.on("-s", "--service NAME", "Name of the RabbitMQ service") do |name|
options.service_name = name
end
opts.on("-p", "--port PORT", "Consul HTTP API port") do |port|
options.port = port
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
}.parse!
begin
uri = URI("http://localhost:#{options.port}/v1/health/service/#{options.service_name}")
nodes = JSON.load(Net::HTTP.get(uri))
rescue => error
$stderr.puts "Could not retrieve health information for service"
$stderr.puts error
exit 1
end
nodes.reject! do |node|
node['Checks'].none? do |check|
check['ServiceID'] == options.service_name && check['Status'] == 'passing'
end
end
if nodes.empty?
$stderr.puts "Could not locate node providing suitable \"#{options.service_name}\" service"
exit 2
end
node = nodes.sample['Node']
puts "Using node \"#{node['Node']}\" to provide \"#{options.service_name}\" service"
if `rabbitmqctl cluster_status`.include?(node['Node'])
puts "RabbitMQ already belongs to the cluster"
exit 0
end
unless `host #{node['Node']}`
$stderr.puts "Could not resolve node #{node['Node']} with DNS"
exit 3
end
system "rabbitmqctl stop_app"
system "rabbitmqctl join_cluster --ram rabbit@#{node['Node']}"
system "rabbitmqctl start_app"
system "rabbitmqctl cluster_status"
@ianunruh
Copy link
Author

RabbitMQ is configured by default to use the short hostname, not the FQDN, of cluster nodes. This means that RabbitMQ must be able to resolve rabbit1, for instance. You can either use your own DNS set the search domain OR you can setup dnsmasq to forward to Consul's DNS interface with the search domain node.dc1.consul.

@ianunruh
Copy link
Author

Note that changing RabbitMQ to use FQDN requires changing the files in /usr/lib/rabbitmq/bin to use the -name flag instead of -sname.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment