diff --git a/plugin/traffic/HACKING.md b/plugin/traffic/HACKING.md index d17a52259..71fbdd48c 100644 --- a/plugin/traffic/HACKING.md +++ b/plugin/traffic/HACKING.md @@ -36,6 +36,7 @@ Then for CoreDNS, check out the `traffic` branch, create a Corefile: example.org { traffic grpc://127.0.0.1:18000 { id test-id + ignore_health } debug } diff --git a/plugin/traffic/README.md b/plugin/traffic/README.md index c08d83478..4c9735622 100644 --- a/plugin/traffic/README.md +++ b/plugin/traffic/README.md @@ -62,6 +62,7 @@ traffic TO... { node ID tls CERT KEY CA tls_servername NAME + ignore_health } ~~~ @@ -78,6 +79,7 @@ traffic TO... { * `tls_servername` **NAME** allows you to set a server name in the TLS configuration. This is needed because *traffic* connects to an IP address, so it can't infer the server name from it. +* `ignore_health` can be enabled to ignore endpoint health status, this can aid when debugging. ## Naming Clusters diff --git a/plugin/traffic/setup.go b/plugin/traffic/setup.go index 4557faa7e..0806d15c2 100644 --- a/plugin/traffic/setup.go +++ b/plugin/traffic/setup.go @@ -101,6 +101,8 @@ func parseTraffic(c *caddy.Controller) (*Traffic, error) { return nil, c.ArgErr() } tlsServerName = c.Val() + case "ignore_health": + t.health = true default: return nil, c.Errf("unknown property '%s'", c.Val()) } diff --git a/plugin/traffic/traffic.go b/plugin/traffic/traffic.go index e11ea0b51..4aee275ad 100644 --- a/plugin/traffic/traffic.go +++ b/plugin/traffic/traffic.go @@ -19,6 +19,7 @@ import ( type Traffic struct { c *xds.Client id string + health bool origins []string Next plugin.Handler @@ -41,7 +42,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg m.SetReply(r) m.Authoritative = true - sockaddr, ok := t.c.Select(cluster) + sockaddr, ok := t.c.Select(cluster, t.health) if !ok { // ok the cluster (which has potentially extra labels), doesn't exist, but we may have a query for endpoint-0.. // check if we have 2 labels and that the first equals endpoint-0. @@ -55,7 +56,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg if strings.HasPrefix(labels[0], "endpoint-") { // recheck if the cluster exist. cluster = labels[1] - sockaddr, ok = t.c.Select(cluster) + sockaddr, ok = t.c.Select(cluster, t.health) if !ok { m.Ns = soa(state.Zone) m.Rcode = dns.RcodeNameError @@ -88,7 +89,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg } m.Answer = []dns.RR{&dns.AAAA{Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 5}, AAAA: sockaddr.Address()}} case dns.TypeSRV: - sockaddrs, _ := t.c.All(cluster) + sockaddrs, _ := t.c.All(cluster, t.health) for i, sa := range sockaddrs { target := fmt.Sprintf("endpoint-%d.%s.%s", i, cluster, state.Zone) @@ -133,7 +134,7 @@ func (t *Traffic) serveEndpoint(ctx context.Context, state request.Request, endp return 0, nil } - sockaddrs, _ := t.c.All(cluster) + sockaddrs, _ := t.c.All(cluster, t.health) if len(sockaddrs) < nr { m.Ns = soa(state.Zone) m.Rcode = dns.RcodeNameError diff --git a/plugin/traffic/xds/assignment.go b/plugin/traffic/xds/assignment.go index 299b4a5e0..1e5381e0d 100644 --- a/plugin/traffic/xds/assignment.go +++ b/plugin/traffic/xds/assignment.go @@ -67,7 +67,7 @@ func (a *assignment) clusters() []string { } // Select selects a endpoint from cluster load assignments, using weighted random selection. It only selects endpoints that are reporting healthy. -func (a *assignment) Select(cluster string) (*SocketAddress, bool) { +func (a *assignment) Select(cluster string, ignore bool) (*SocketAddress, bool) { cla := a.ClusterLoadAssignment(cluster) if cla == nil { return nil, false @@ -77,7 +77,7 @@ func (a *assignment) Select(cluster string) (*SocketAddress, bool) { healthy := 0 for _, ep := range cla.Endpoints { for _, lb := range ep.GetLbEndpoints() { - if lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { + if !ignore && lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { continue } total += int(lb.GetLoadBalancingWeight().GetValue()) @@ -94,7 +94,7 @@ func (a *assignment) Select(cluster string) (*SocketAddress, bool) { i := 0 for _, ep := range cla.Endpoints { for _, lb := range ep.GetLbEndpoints() { - if lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { + if !ignore && lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { continue } if r == i { @@ -109,7 +109,7 @@ func (a *assignment) Select(cluster string) (*SocketAddress, bool) { r := rand.Intn(total) + 1 for _, ep := range cla.Endpoints { for _, lb := range ep.GetLbEndpoints() { - if lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { + if !ignore && lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { continue } r -= int(lb.GetLoadBalancingWeight().GetValue()) @@ -122,7 +122,7 @@ func (a *assignment) Select(cluster string) (*SocketAddress, bool) { } // All returns all healthy endpoints. -func (a *assignment) All(cluster string) ([]*SocketAddress, bool) { +func (a *assignment) All(cluster string, ignore bool) ([]*SocketAddress, bool) { cla := a.ClusterLoadAssignment(cluster) if cla == nil { return nil, false @@ -131,7 +131,7 @@ func (a *assignment) All(cluster string) ([]*SocketAddress, bool) { sa := []*SocketAddress{} for _, ep := range cla.Endpoints { for _, lb := range ep.GetLbEndpoints() { - if lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { + if !ignore && lb.GetHealthStatus() != corepb.HealthStatus_HEALTHY { continue } sa = append(sa, &SocketAddress{lb.GetEndpoint().GetAddress().GetSocketAddress()}) diff --git a/plugin/traffic/xds/client.go b/plugin/traffic/xds/client.go index 4aed20fba..e54514f51 100644 --- a/plugin/traffic/xds/client.go +++ b/plugin/traffic/xds/client.go @@ -227,17 +227,17 @@ func (c *Client) receive(stream adsStream) error { // Select returns an address that is deemed to be the correct one for this cluster. The returned // boolean indicates if the cluster exists. -func (c *Client) Select(cluster string) (*SocketAddress, bool) { +func (c *Client) Select(cluster string, ignore bool) (*SocketAddress, bool) { if cluster == "" { return nil, false } - return c.assignments.Select(cluster) + return c.assignments.Select(cluster, ignore) } // All returns all endpoints. -func (c *Client) All(cluster string) ([]*SocketAddress, bool) { +func (c *Client) All(cluster string, ignore bool) ([]*SocketAddress, bool) { if cluster == "" { return nil, false } - return c.assignments.All(cluster) + return c.assignments.All(cluster, ignore) }