segmentio / emissary

Multi-backend Envoy xDS service.
MIT License
8 stars 7 forks source link

[WIP] : initial EDS implementation #1

Closed rjenkins closed 5 years ago

rjenkins commented 5 years ago

This is a bit early but there is a lot of work that can be done in parallel and @Pryz is chomping at the bit to help :joy: so I'm getting this up for early review.

main.go - simple conf loader with commands. Currently only supports the eds command. Launches a gRPC server and registers an eds.go - EdsService eds.go - gRPC and REST implementation of StreamEndpoints and FetchEndpoints respectively. eds_test.go - NOTE: we need much more testing here and I will continue on that shortly.

eds.go is an implementation of the Envoy v2 API EndpointDiscoveryService. If you are not familiar with the Envoy v2 xDS protocol this link is very helpful. https://github.com/envoyproxy/data-plane-api/blob/master/XDS_PROTOCOL.md.

EdsService implements the StreamEndpoints API which provides the entry point for a bi-directional HTTP2/gRPC connections. Each client that connects spawns an edsStreamHandler. The edsStreamHandler composes the main looping logic to send and receive auto-discovered endpoint information to Envoy.

After an envoy is connected to emissary on the EDS gRPC API the envoy sends a DiscoveryRequest. We retrieve that request by calling receive on our gRPC endpoint. request, err := e.server.Recv(). The request contains a TypeURL indicating the type of request, a list of ResourceNames and a VersionInfo and RequestNonce (note: on the first request the VersionInfo and Nonce are empty.ResourceNamescontains services that the envoy is interested. These correspond to services in consul. TheedsStreamHandler` then launches a goroutine to fetch the initial service information from consul (task id, ip address, az) and monitor for any changes.

After we send our first reply to the envoy, it immediately responds echoing the config and the new VersionInfo and Nonce. We then wait for any changes to occur and send over the gRPC connection as they occur.

Notes:

  1. We are not using consul watches, for performance and simplicity, we are just polling consul and checking for changes.
  2. We are purposefully skipping a key optimization (pub/sub consul changes to envoys). Instead we spawn a goroutine PER bidi gRPC connection to poll consul. This means that we'd be duplicating consul polling work if we have N emissary gRPC connections. We will move this out into a subscriber/publish model to eliminate duplication of work.
  3. Might want to switch to events.Log, had some issues wiring it up to stdout over the weekend and just worked with apex logs.
  4. Lots of metrics needed but as mentioned, up for early review