mirror of
https://github.com/coredns/coredns.git
synced 2025-11-15 16:32:23 -05:00
@@ -2,47 +2,39 @@
|
||||
|
||||
## Name
|
||||
|
||||
*traffic* - handout addresses according to assignments.
|
||||
*traffic* - handout addresses according to assignments from Envoy's xDS.
|
||||
|
||||
## Description
|
||||
|
||||
The *traffic* plugin is a load balancer that allows traffic steering, weighted responses and
|
||||
draining of endpoints. The use case for this plugin is when a service is running in multiple
|
||||
(Kubernetes?) clusters and need to steer traffic to (or away) from these, i.e. cluster A needs to be
|
||||
upgraded, so all traffic to it is drained, while cluster B now takes on all the extra load. After
|
||||
the maintenance cluster A is simply undrained.
|
||||
The *traffic* plugin is a balancer that allows traffic steering, weighted responses
|
||||
and draining of clusters. The cluster information is retrieved from a service
|
||||
discovery manager that implements the service discovery protocols that Envoy
|
||||
[implements](https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol).
|
||||
|
||||
*Traffic* discovers the endpoints via the Envoy xDS protocol, specifically messages of the type
|
||||
"envoy.api.v2.ClusterLoadAssignment", these contain endpoints and an (optional) weight for each.
|
||||
The `cluster_name` or `service_name` for a service must be a domain name. (TODO: check is this is
|
||||
already the case). The plugin hands out responses that adhere to these assignments.
|
||||
Assignments will need to be updated frequently, as discussed the [Envoy xDS
|
||||
protocol](https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol) documentation.
|
||||
A Cluster is defined as: "A cluster is a group of logically similar endpoints that Envoy connects
|
||||
to. Each cluster has a name, which *traffic* extends to be a domain name.
|
||||
|
||||
Multiple endpoints for a service may exist; for every query *traffic* will hand out exactly one
|
||||
address. When there are no assignments for a service name (yet), the responses will also be modified
|
||||
(see below).
|
||||
The use case for this plugin is when a cluster has endpoints running in multiple
|
||||
(Kubernetes?) clusters and you need to steer traffic to (or away) from these endpoints, i.e.
|
||||
endpoint A needs to be upgraded, so all traffic to it is drained. Or the entire Kubernetes needs to
|
||||
upgraded, and *all* endpoints need to be drained from it.
|
||||
|
||||
*Traffic* will load balance A and AAAA queries. As said, it will return precisely one record in a
|
||||
response. If a service should be load balanced, but no assignment can be found a random record from
|
||||
the *answer section* will be choosen.
|
||||
|
||||
Every message that is handled by the *traffic* plugin will have its TTLs set to 5 seconds, the
|
||||
authority section, and all RRSIGs are removed from it.
|
||||
*Traffic* discovers the endpoints via Envoy's xDS protocol. Endpoints and clusters are discovered
|
||||
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.
|
||||
|
||||
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
|
||||
assignment yet, it will still include this endpoint address in responses.
|
||||
|
||||
Findign the xDS endpoint.
|
||||
|
||||
## Syntax
|
||||
|
||||
~~~
|
||||
traffic
|
||||
~~~
|
||||
|
||||
The extended syntax:
|
||||
The extended syntax (not implemented; everything is hard-coded at the moment):
|
||||
|
||||
~~~
|
||||
traffic {
|
||||
@@ -53,74 +45,35 @@ traffic {
|
||||
|
||||
* id **ID** is how *traffic* identifies itself to the control plane.
|
||||
|
||||
This enables traffic load balancing for all (sub-)domains named in the server block.
|
||||
|
||||
## Examples
|
||||
|
||||
~~~ corefile
|
||||
example.org {
|
||||
traffic
|
||||
forward . 10.12.13.14
|
||||
debug
|
||||
log
|
||||
}
|
||||
~~~
|
||||
|
||||
This will add load balancing for domains under example.org; the upstream information comes from
|
||||
10.12.13.14; depending on received assignments, replies will be let through as-is or are load balanced.
|
||||
|
||||
## Assignments
|
||||
|
||||
Assignments are streamed for a service that implements the xDS protocol, *traffic* will bla bla.
|
||||
TODO.
|
||||
|
||||
Picking an endpoint is done as follows: (still true for xDs - check afer implementing things)
|
||||
|
||||
* include spiffy algorithm.
|
||||
|
||||
On seeing a query for a service, *traffic* will track the reply. When it returns with an answer
|
||||
*traffic* will rewrite it (and discard of any RRSIGs). Using the assignments the answer section will
|
||||
be rewritten as such:
|
||||
|
||||
* A endpoint will be picked using the algorithm from above.
|
||||
* The TTL on the response will be 5s for all included records.
|
||||
* According to previous responses for this service and the relative weights of each endpoints the
|
||||
best endpoint will be put in the response.
|
||||
* If after the selection *no* endpoints are available an NODATA response will be sent. An SOA
|
||||
record will be synthesised, and a low TTL (and negative TTL) of 5 seconds will be set.
|
||||
|
||||
Authority section will be removed.
|
||||
If no assignment, randomly pick an address
|
||||
other types then A and AAAA, like SRV - do the same selection.
|
||||
|
||||
## Limitations
|
||||
|
||||
Loadreporting via xDS is not supported; this can be implemented, but there are some things that make
|
||||
this difficult. A single (DNS) query is done by a resolver. Behind this resolver there may be many
|
||||
clients that will use this assignment.
|
||||
|
||||
|
||||
## Bugs
|
||||
|
||||
This plugin does not play nice with DNSSEC - if the endpoint returns signatures with the answer; they
|
||||
will be stripped. You can optionally sign responses on the fly by using the *dnssec* plugin.
|
||||
Priority from ClusterLoadAssignments is not used. Locality is also not used. Health status of the
|
||||
endpoints is ignore (for now).
|
||||
|
||||
Load reporting via xDS is not supported; this can be implemented, but there are some things that make
|
||||
this difficult. A single (DNS) query is done by a resolver. Behind this resolver there may be many
|
||||
clients that will use this reply, the responding server (CoreDNS) has no idea how many clients use
|
||||
this resolver. So reporting a load of +1 on the CoreDNS side can be anything from 1 to 1000+, making
|
||||
the load reporting highly inaccurate.
|
||||
|
||||
## Also See
|
||||
|
||||
The following documents provide some background on Envoy's control plane.
|
||||
|
||||
* https://github.com/envoyproxy/go-control-plane
|
||||
* https://blog.christianposta.com/envoy/guidance-for-building-a-control-plane-to-manage-envoy-proxy-based-infrastructure/
|
||||
* https://github.com/envoyproxy/envoy/blob/442f9fcf21a5f091cec3fe9913ff309e02288659/api/envoy/api/v2/discovery.proto#L63
|
||||
* This is a [post on weighted random selection](https://medium.com/@peterkellyonline/weighted-random-selection-3ff222917eb6).
|
||||
|
||||
# TODO
|
||||
|
||||
* wording: cluster, endpoints, assignments, service_name are all used and roughly mean the same
|
||||
thing; unify this.
|
||||
const (
|
||||
HealthStatus_UNKNOWN HealthStatus = 0
|
||||
HealthStatus_HEALTHY HealthStatus = 1
|
||||
HealthStatus_UNHEALTHY HealthStatus = 2
|
||||
HealthStatus_DRAINING HealthStatus = 3
|
||||
HealthStatus_TIMEOUT HealthStatus = 4
|
||||
HealthStatus_DEGRADED HealthStatus = 5
|
||||
)
|
||||
|
||||
https://www.envoyproxy.io/docs/envoy/v1.11.2/api-docs/xds_protocol
|
||||
|
||||
Reference in New Issue
Block a user