I've actually implemented something like that with route53 (amazon't DNS service). For each important host (e.g, db) I've created a name (e.g.
db.domain.com) and added it as CNAME to the host's internal address (this does not work between regions though). The reason I chose route53 was that I think (It's not yet checked) that It helps reduces TTL since I already query the amazon DNS.
#!/usr/bin/env ruby
HOSTNAME = <%= %{'#{node[:ec2][:hostname]}'} %>
DOMAINNAME = <%= %{'#{node[:company][:internal_domain]}'} %>
EC2_KEY_ID = <%= %{'
'EC2_KEY_ID']}'} %>
EC2_SECRET_KEY = <%= %{'
'EC2_SECRET_KEY']}'} %>
require 'rubygems'
require 'right_aws'
module Route53Update
extend self
def r53
@r53 ||= RightAws::Route53Interface.new(EC2_KEY_ID, EC2_SECRET_KEY)
end
def zone_id
return @zone_id if @zone_id
zone = r53.list_hosted_zones.select { |zone|
zone[:name] =~ /^#{DOMAINNAME}\.?$/
}.first
@zone_id = zone ? zone[:aws_id] :
raise("Zone #{DOMAINNAME} doesn't seem to be registered!")
end
def create_cname
delete_cname
resource_record_sets = [{
:name => NODENAME,
:type => 'CNAME',
:ttl => 300,
:resource_records => [HOSTNAME]
}]
r53.create_resource_record_sets(zone_id, resource_record_sets, "")
end
def delete_cname
r53.list_resource_record_sets(zone_id).each do |record|
if record[:name] == "#{NODENAME}."
r53.delete_resource_record_sets(zone_id, [record], "")
break
end
end
end
def validate_cname
res = r53.list_resource_record_sets(zone_id).select { |record|
record[:name] =~ /#{NODENAME}\.?$/
}.first
res && res[:resource_records].include?(HOSTNAME) ? true : false
end
def update_cname
return if validate_cname
create_cname
# TODO: validate sync!
end
end
if $0 == __FILE__
Route53Update.update_cname
end
You have to install right_aws gem and add an init script (so it'll run on boot). You can probably figure out the variables.
Using DNS helps with not having to restart application every time a host changes it IP, but you have to consider DNS caching (e.g, Java caches dns results depending on running environment).