diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a9e49f667..8f46c0c168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,12 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re ## Unreleased - [#3259](https://github.com/thanos-io/thanos/pull/3259) Thanos BlockViewer: Added a button in the blockviewer that allows users to download the metadata of a block. - - [#3261](https://github.com/thanos-io/thanos/pull/3261) Thanos Store: Use segment files specified in meta.json file, if present. If not present, Store does the LIST operation as before. - [#3276](https://github.com/thanos-io/thanos/pull/3276) Query Frontend: Support query splitting and retry for labels and series requests. +### Fixed +- [#3257](https://github.com/thanos-io/thanos/pull/3257) Ruler: Prevent Ruler from crashing when using default DNS to lookup hosts that results in "No such hosts" errors. + ## [v0.16.0](https://github.com/thanos-io/thanos/releases) - Release in progress ### Fixed diff --git a/pkg/discovery/dns/provider.go b/pkg/discovery/dns/provider.go index e80f7aac49..75c3b02fd1 100644 --- a/pkg/discovery/dns/provider.go +++ b/pkg/discovery/dns/provider.go @@ -57,7 +57,7 @@ func (t ResolverType) ToResolver(logger log.Logger) ipLookupResolver { // If empty resolver type is net.DefaultResolver. func NewProvider(logger log.Logger, reg prometheus.Registerer, resolverType ResolverType) *Provider { p := &Provider{ - resolver: NewResolver(resolverType.ToResolver(logger)), + resolver: NewResolver(resolverType.ToResolver(logger), logger), resolved: make(map[string][]string), logger: logger, resolverAddrs: extprom.NewTxGaugeVec(reg, prometheus.GaugeOpts{ diff --git a/pkg/discovery/dns/resolver.go b/pkg/discovery/dns/resolver.go index ef73054768..679834f7b2 100644 --- a/pkg/discovery/dns/resolver.go +++ b/pkg/discovery/dns/resolver.go @@ -9,6 +9,9 @@ import ( "strconv" "strings" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/pkg/errors" ) @@ -38,11 +41,12 @@ type ipLookupResolver interface { type dnsSD struct { resolver ipLookupResolver + logger log.Logger } // NewResolver creates a resolver with given underlying resolver. -func NewResolver(resolver ipLookupResolver) Resolver { - return &dnsSD{resolver: resolver} +func NewResolver(resolver ipLookupResolver, logger log.Logger) Resolver { + return &dnsSD{resolver: resolver, logger: logger} } func (s *dnsSD) Resolve(ctx context.Context, name string, qtype QType) ([]string, error) { @@ -71,7 +75,15 @@ func (s *dnsSD) Resolve(ctx context.Context, name string, qtype QType) ([]string } ips, err := s.resolver.LookupIPAddr(ctx, host) if err != nil { - return nil, errors.Wrapf(err, "lookup IP addresses %q", host) + // We exclude error from std Golang resolver for the case of the domain (e.g `NXDOMAIN`) not being found by DNS + // server. Since `miekg` does not consider this as an error, when the host cannot be found, empty slice will be + // returned. + if dnsErr, ok := err.(*net.DNSError); !ok || !dnsErr.IsNotFound { + return nil, errors.Wrapf(err, "lookup IP addresses %q", host) + } + if ips == nil { + level.Error(s.logger).Log("msg", "failed to lookup IP addresses", "host", host, "err", err) + } } for _, ip := range ips { res = append(res, appendScheme(scheme, net.JoinHostPort(ip.String(), port))) @@ -106,6 +118,10 @@ func (s *dnsSD) Resolve(ctx context.Context, name string, qtype QType) ([]string return nil, errors.Errorf("invalid lookup scheme %q", qtype) } + if res == nil && err == nil { + level.Warn(s.logger).Log("msg", "IP address lookup yielded no results. No host found or no addresses found", "host", host) + } + return res, nil } diff --git a/pkg/discovery/dns/resolver_test.go b/pkg/discovery/dns/resolver_test.go index 5663ca7380..2eef7b4fbe 100644 --- a/pkg/discovery/dns/resolver_test.go +++ b/pkg/discovery/dns/resolver_test.go @@ -9,6 +9,8 @@ import ( "sort" "testing" + "github.com/go-kit/kit/log" + "github.com/pkg/errors" "github.com/thanos-io/thanos/pkg/testutil" ) @@ -184,7 +186,7 @@ func TestDnsSD_Resolve(t *testing.T) { func testDnsSd(t *testing.T, tt DNSSDTest) { ctx := context.TODO() - dnsSD := dnsSD{tt.resolver} + dnsSD := dnsSD{tt.resolver, log.NewNopLogger()} result, err := dnsSD.Resolve(ctx, tt.addr, tt.qtype) if tt.expectedErr != nil {