Implement `translate_wan_addrs` config option

This knob tells consul whether it should prefer the WAN address (if set)
when making service lookups in remote datacenters. This enables
reachability for remote services which are behind a NAT.
This commit is contained in:
Evan Gilman 2015-12-22 03:31:40 -08:00 committed by James Phillips
parent 8fa2a60208
commit 496cf5ae73
3 changed files with 30 additions and 7 deletions

View File

@ -189,6 +189,10 @@ type Config struct {
// Serf WAN IP. If not specified, the general advertise address is used.
AdvertiseAddrWan string `mapstructure:"advertise_addr_wan"`
// TranslateWanAddrs controls whether or not Consul should prefer
// the AdvertiseAddrWan address when doing lookups in remote datacenters.
TranslateWanAddrs bool `mapstructure:"translate_wan_addrs"`
// Port configurations
Ports PortConfig
@ -968,6 +972,9 @@ func MergeConfig(a, b *Config) *Config {
if b.AdvertiseAddrWan != "" {
result.AdvertiseAddrWan = b.AdvertiseAddrWan
}
if b.TranslateWanAddrs == true {
result.TranslateWanAddrs = true
}
if b.AdvertiseAddrs.SerfLan != nil {
result.AdvertiseAddrs.SerfLan = b.AdvertiseAddrs.SerfLan
result.AdvertiseAddrs.SerfLanRaw = b.AdvertiseAddrs.SerfLanRaw

View File

@ -524,9 +524,15 @@ RPC:
// Perform a random shuffle
out.Nodes.Shuffle()
// Determine whether we should use the WAN address or not
var useWan bool
if d.agent.config.TranslateWanAddrs && datacenter != d.agent.config.Datacenter {
useWan = true
}
// Add various responses depending on the request
qType := req.Question[0].Qtype
d.serviceNodeRecords(out.Nodes, req, resp, ttl)
d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan)
if qType == dns.TypeSRV {
d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl)
@ -620,9 +626,15 @@ RPC:
return
}
// Determine whether we should use the WAN address or not
var useWan bool
if d.agent.config.TranslateWanAddrs && datacenter != d.agent.config.Datacenter {
useWan = true
}
// Add various responses depending on the request.
qType := req.Question[0].Qtype
d.serviceNodeRecords(out.Nodes, req, resp, ttl)
d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan)
if qType == dns.TypeSRV {
d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl)
}
@ -646,18 +658,22 @@ RPC:
}
// serviceNodeRecords is used to add the node records for a service lookup
func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration) {
func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, useWan bool) {
qName := req.Question[0].Name
qType := req.Question[0].Qtype
handled := make(map[string]struct{})
for _, node := range nodes {
// Avoid duplicate entries, possible if a node has
// the same service on multiple ports, etc.
// Prefer the Service Address or WAN Address over the
// Node Address when configured
addr := node.Node.Address
if node.Service.Address != "" {
addr = node.Service.Address
} else if useWan == true && node.Node.WanAddress != "" {
addr = node.Node.WanAddress
}
// Avoid duplicate entries, possible if a node has
// the same service on multiple ports, etc.
if _, ok := handled[addr]; ok {
continue
}

View File

@ -526,7 +526,7 @@ func (l *localState) syncService(id string) error {
Datacenter: l.config.Datacenter,
Node: l.config.NodeName,
Address: l.config.AdvertiseAddr,
WanAddress: l.config.ConsulConfig.SerfWANConfig.MemberlistConfig.AdvertiseAddr,
WanAddress: l.config.AdvertiseAddrWan,
Service: l.services[id],
WriteRequest: structs.WriteRequest{Token: l.serviceToken(id)},
}
@ -584,7 +584,7 @@ func (l *localState) syncCheck(id string) error {
Datacenter: l.config.Datacenter,
Node: l.config.NodeName,
Address: l.config.AdvertiseAddr,
WanAddress: l.config.ConsulConfig.SerfWANConfig.MemberlistConfig.AdvertiseAddr,
WanAddress: l.config.AdvertiseAddrWan,
Service: service,
Check: l.checks[id],
WriteRequest: structs.WriteRequest{Token: l.checkToken(id)},