diff --git a/Gopkg.lock b/Gopkg.lock index 833451eb679..107bbae2c64 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1432,6 +1432,7 @@ "github.com/mattes/migrate/driver/postgres", "github.com/mattes/migrate/migrate", "github.com/mgutz/ansi", + "github.com/miekg/dns", "github.com/opentracing-contrib/go-grpc", "github.com/opentracing-contrib/go-stdlib/nethttp", "github.com/opentracing/opentracing-go", diff --git a/pkg/alertmanager/peers.go b/pkg/alertmanager/peers.go index 03a849d2408..5005b5d3e25 100644 --- a/pkg/alertmanager/peers.go +++ b/pkg/alertmanager/peers.go @@ -1,11 +1,11 @@ package alertmanager import ( - "net" "time" "github.com/cortexproject/cortex/pkg/util" "github.com/go-kit/kit/log/level" + "github.com/miekg/dns" "github.com/prometheus/client_golang/prometheus" ) @@ -34,7 +34,7 @@ type srvDiscovery struct { service string hostname string pollInterval time.Duration - addresses chan []*net.SRV + addresses chan []*dns.SRV stop chan struct{} done chan struct{} @@ -46,7 +46,7 @@ func newSRVDiscovery(service, hostname string, pollInterval time.Duration) *srvD service: service, hostname: hostname, pollInterval: pollInterval, - addresses: make(chan []*net.SRV), + addresses: make(chan []*dns.SRV), stop: make(chan struct{}), done: make(chan struct{}), } @@ -61,8 +61,8 @@ func (s *srvDiscovery) Stop() { } func (s *srvDiscovery) updatePeers() { - var addrs []*net.SRV - _, addrs, err := net.LookupSRV(s.service, "tcp", s.hostname) + var addrs []*dns.SRV + addrs, err := util.LookupSRV(s.service, "tcp", s.hostname) srvRequests.Inc() if err != nil { srvRequestFailures.Inc() diff --git a/pkg/chunk/cache/memcached_client.go b/pkg/chunk/cache/memcached_client.go index d43fa93713f..c670e46a7db 100644 --- a/pkg/chunk/cache/memcached_client.go +++ b/pkg/chunk/cache/memcached_client.go @@ -3,7 +3,6 @@ package cache import ( "flag" "fmt" - "net" "sort" "sync" "time" @@ -100,7 +99,7 @@ func (c *memcachedClient) updateLoop(updateInterval time.Duration) error { // updateMemcacheServers sets a memcache server list from SRV records. SRV // priority & weight are ignored. func (c *memcachedClient) updateMemcacheServers() error { - _, addrs, err := net.LookupSRV(c.service, "tcp", c.hostname) + addrs, err := util.LookupSRV(c.service, "tcp", c.hostname) if err != nil { return err } diff --git a/pkg/util/dns.go b/pkg/util/dns.go new file mode 100644 index 00000000000..04f8ef77e7d --- /dev/null +++ b/pkg/util/dns.go @@ -0,0 +1,67 @@ +package util + +import ( + "fmt" + "net" + + "github.com/go-kit/kit/log/level" + "github.com/miekg/dns" +) + +const defaultResolvConf = "/etc/resolv.conf" + +func getDefaultDNSServers(conf *dns.ClientConfig) []string { + servers := make([]string, 0, len(conf.Servers)) + for _, server := range conf.Servers { + servers = append(servers, net.JoinHostPort(server, conf.Port)) + } + + return servers +} + +// LookupSRV tries to resolve an SRV query of the given service, proto and domain name. +// proto can be 'tcp' or udp'. +// The query will be of the form _service._proto.name. +func LookupSRV(service, proto, name string) ([]*dns.SRV, error) { + conf, err := dns.ClientConfigFromFile(defaultResolvConf) + if err != nil { + return nil, err + } + + dnsServers := getDefaultDNSServers(conf) + + name = "_" + service + "._" + proto + "." + name + names := conf.NameList(name) + + dnsResolved := false + client := dns.Client{} + + for _, name := range names { + msg := &dns.Msg{} + msg.SetQuestion(dns.Fqdn(name), dns.TypeSRV) + + var result []*dns.SRV + for _, serverAddr := range dnsServers { + resMsg, _, err := client.Exchange(msg, serverAddr) + if err != nil { + level.Warn(Logger).Log("msg", "DNS exchange failed", "err", err) + continue + } + dnsResolved = true + for _, ans := range resMsg.Answer { + if srvRecord, ok := ans.(*dns.SRV); ok { + result = append(result, srvRecord) + } + } + if len(result) > 0 { + return result, nil + } + } + } + + if !dnsResolved { + return nil, fmt.Errorf("Couldn't resolve %s: No server responded", name) + } + + return nil, nil +}