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. // Serf WAN IP. If not specified, the general advertise address is used.
AdvertiseAddrWan string `mapstructure:"advertise_addr_wan"` 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 // Port configurations
Ports PortConfig Ports PortConfig
@ -968,6 +972,9 @@ func MergeConfig(a, b *Config) *Config {
if b.AdvertiseAddrWan != "" { if b.AdvertiseAddrWan != "" {
result.AdvertiseAddrWan = b.AdvertiseAddrWan result.AdvertiseAddrWan = b.AdvertiseAddrWan
} }
if b.TranslateWanAddrs == true {
result.TranslateWanAddrs = true
}
if b.AdvertiseAddrs.SerfLan != nil { if b.AdvertiseAddrs.SerfLan != nil {
result.AdvertiseAddrs.SerfLan = b.AdvertiseAddrs.SerfLan result.AdvertiseAddrs.SerfLan = b.AdvertiseAddrs.SerfLan
result.AdvertiseAddrs.SerfLanRaw = b.AdvertiseAddrs.SerfLanRaw result.AdvertiseAddrs.SerfLanRaw = b.AdvertiseAddrs.SerfLanRaw

View File

@ -524,9 +524,15 @@ RPC:
// Perform a random shuffle // Perform a random shuffle
out.Nodes.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 // Add various responses depending on the request
qType := req.Question[0].Qtype qType := req.Question[0].Qtype
d.serviceNodeRecords(out.Nodes, req, resp, ttl) d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan)
if qType == dns.TypeSRV { if qType == dns.TypeSRV {
d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl)
@ -620,9 +626,15 @@ RPC:
return 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. // Add various responses depending on the request.
qType := req.Question[0].Qtype qType := req.Question[0].Qtype
d.serviceNodeRecords(out.Nodes, req, resp, ttl) d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan)
if qType == dns.TypeSRV { if qType == dns.TypeSRV {
d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) 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 // 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 qName := req.Question[0].Name
qType := req.Question[0].Qtype qType := req.Question[0].Qtype
handled := make(map[string]struct{}) handled := make(map[string]struct{})
for _, node := range nodes { for _, node := range nodes {
// Avoid duplicate entries, possible if a node has // Prefer the Service Address or WAN Address over the
// the same service on multiple ports, etc. // Node Address when configured
addr := node.Node.Address addr := node.Node.Address
if node.Service.Address != "" { if node.Service.Address != "" {
addr = 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 { if _, ok := handled[addr]; ok {
continue continue
} }

View File

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