From 246782b726326e5a26e45cab07715504d3f75ceb Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Thu, 16 Jan 2020 19:45:43 +0100 Subject: [PATCH] fixes Signed-off-by: Miek Gieben --- plugin/traffic/README.md | 15 ++++++++------- plugin/traffic/traffic.go | 16 +++++++++------- plugin/traffic/xds/assignment.go | 10 +++++----- plugin/traffic/xds/client.go | 5 +++-- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/plugin/traffic/README.md b/plugin/traffic/README.md index 391f0cc5b..f48741392 100644 --- a/plugin/traffic/README.md +++ b/plugin/traffic/README.md @@ -23,7 +23,7 @@ endpoints need to be drained from it. every 10 seconds. The plugin hands out responses that adhere to these assignments. Each DNS response contains a single IP address that's considered the best one. *Traffic* will load balance A and AAAA queries. The TTL on these answer is set to 5s. It will only return successful responses either with -an answer or otherwise a NODATA response. NXDOMAIN responses will *never* be sent. +an answer or otherwise a NODATA response. Queries for non-existent clusters get a NXDOMAIN. The *traffic* plugin has no notion of draining, drop overload and anything that advanced, *it just acts upon assignments*. This is means that if a endpoint goes down and *traffic* has not seen a new @@ -35,8 +35,9 @@ assignment yet, it will still include this endpoint address in responses. traffic TO... ~~~ - * **TO...** are the Envoy control plane endpoint to connect to. The syntax mimics the *forward* - plugin and must start with `grpc://`. +This enabled the *traffic* plugin, with a default node id of `coredns` and no TLS. + +* **TO...** are the Envoy control plane endpoint to connect to. This must start with `grpc://`. The extended syntax is available is you want more control. @@ -46,7 +47,7 @@ traffic TO... { node ID tls CERT KEY CA tls_servername NAME - } +} ~~~ * node **ID** is how *traffic* identifies itself to the control plane. This defaults to `coredns`. @@ -57,7 +58,7 @@ traffic TO... { * `tls` **CA** - no client authentication is used, and the file CA is used to verify the server certificate * `tls` **CERT** **KEY** - client authentication is used with the specified cert/key pair. The server certificate is verified with the system CAs. - * `tls` **CERT** **KEY** **CA** - client authentication is used with the specified cert/key pair. + * `tls` **CERT** **KEY** **CA** - client authentication is used with the specified cert/key pair. The server certificate is verified using the specified CA file. * `tls_servername` **NAME** allows you to set a server name in the TLS configuration. This is needed @@ -120,9 +121,9 @@ Multiple **TO** addresses is not implemented. ## TODO -* reconnecting the stream * acking responses * correctly tracking versions and pruning old clusters. * metrics? +* how to exactly deal with health status from the endpoints. * testing -* credentials (other than TLS) +* credentials (other than TLS) - how/what? diff --git a/plugin/traffic/traffic.go b/plugin/traffic/traffic.go index 3360be033..e611b0303 100644 --- a/plugin/traffic/traffic.go +++ b/plugin/traffic/traffic.go @@ -39,18 +39,20 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg return plugin.NextOrFailure(t.Name(), t.Next, ctx, w, r) } - addr := t.c.Select(cluster) - if addr != nil { - log.Debugf("Found endpoint %q for %q", addr, cluster) - } else { - log.Debugf("No healthy endpoints found for %q", cluster) - } - m := new(dns.Msg) m.SetReply(r) m.Authoritative = true + addr, ok := t.c.Select(cluster) + if !ok { + m.Ns = soa(state.Zone) + m.Rcode = dns.RcodeNameError + w.WriteMsg(m) + return 0, nil + } + if addr == nil { + log.Debugf("No (healthy) endpoints found for %q", cluster) m.Ns = soa(state.Zone) w.WriteMsg(m) return 0, nil diff --git a/plugin/traffic/xds/assignment.go b/plugin/traffic/xds/assignment.go index b4fce3406..fb2a6273a 100644 --- a/plugin/traffic/xds/assignment.go +++ b/plugin/traffic/xds/assignment.go @@ -54,10 +54,10 @@ func (a *assignment) clusters() []string { // Select selects a backend from cla, using weighted random selection. It only selects // backends that are reporting healthy. -func (a *assignment) Select(cluster string) net.IP { +func (a *assignment) Select(cluster string) (net.IP, bool) { cla := a.clusterLoadAssignment(cluster) if cla == nil { - return nil + return nil, false } total := 0 @@ -81,7 +81,7 @@ func (a *assignment) Select(cluster string) net.IP { // continue // } if r == i { - return net.ParseIP(lb.GetEndpoint().GetAddress().GetSocketAddress().GetAddress()) + return net.ParseIP(lb.GetEndpoint().GetAddress().GetSocketAddress().GetAddress()), true } i++ } @@ -98,9 +98,9 @@ func (a *assignment) Select(cluster string) net.IP { // } r -= int(lb.GetLoadBalancingWeight().GetValue()) if r <= 0 { - return net.ParseIP(lb.GetEndpoint().GetAddress().GetSocketAddress().GetAddress()) + return net.ParseIP(lb.GetEndpoint().GetAddress().GetSocketAddress().GetAddress()), true } } } - return nil + return nil, false } diff --git a/plugin/traffic/xds/client.go b/plugin/traffic/xds/client.go index aacbf61be..c965b39ea 100644 --- a/plugin/traffic/xds/client.go +++ b/plugin/traffic/xds/client.go @@ -216,5 +216,6 @@ func (c *Client) Receive(stream adsStream) error { } } -// Select returns an address that is deemed to be the correct one for this cluster. -func (c *Client) Select(cluster string) net.IP { return c.assignments.Select(cluster) } +// 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) (net.IP, bool) { return c.assignments.Select(cluster) }