Rotor: Connect your Service Discovery to Envoy

We’re excited to open-source an important piece of what we’ve built here at Turbine Labs. Rotor (available now on Github and Docker Hub) is a core part of the traffic management stack we’ve built on Envoy, and starting today, it’s 100% free to use.

Rotor is an easy way to connect Envoy to your existing service discovery registry. Running Envoy on your laptop is straightforward enough, but if you want to use Envoy in your environment, you’ll need a way to populate Envoy’s config files with the list of services and hosts running in your environment. Rotor builds on the open-source go-control-plane to serve clusters and endpoints via Envoy’s configuration APIs (specifically, CDS and EDS).

If you’re just starting out with an Envoy configuration server, or plan to put significant work into one, we’d love for you to try Rotor and see if it can save you some effort.

Background

Before we look too much more at what Rotor does, let’s take a step back and talk about Envoy.

Envoy is a building block for leveling up your production environment to make your engineers more productive. More specifically, it’s a modern proxy (or service mesh) that allows you to manage your traffic as a separate entity. In most microservice architectures, traffic management happens ad hoc, scattered between service implementations, load balancers, and webservers. Envoy allows engineers to pull the techniques behind all this machinery — automatic resilience, observability, and modern protocol support — into one place.

To manage configuration, Envoy defines a management service API to allow dynamic updating of routing configuration across an entire fleet of proxies. This central point of control allows you to build whatever workflows you need: blue/green releases, test in prod, shadow traffic, etc. Having these tools at your disposal can help you build confidence in your code faster, ultimately leading to shipping more.

Let’s get started.

Step One

For most people, the first step is pulling the information out of their service discovery and serving it to a single Envoy instance.

To some extent, modern service discovery systems do a lot of this work for you. Kubernetes will create environment variables for each service, so if you have a service named “auth,” you can make requests to $AUTH_SERVICE_IP and $AUTH_SERVICE PORT and it’ll work. Similarly, Consul creates redis.service.dc1.consul.

Both of these run over DNS, which comes with all the features of… DNS. Primarily, that all languages already speak it. Kube-proxy helps a bit here, but it’s still a purpose-built proxy. Envoy provides a clear path to adding:

  • Automatic retries, health checks, circuit breakers, and global rate limiters
  • URL routing that can send foo.com/bar to the “bar” service and foo.com/baz to the “baz” service
  • Metrics based on requests, or the ability to add distributed tracing
  • Protocol translation like HTTP/1.1 to HTTP/2

Making Envoy Easy

Our goal with Rotor is to make it as easy to run Envoy as it is to use DNS-based resolution from your service discovery.

In order to serve requests, Envoy requires four pieces of information:

  • The list of clusters that it can route to
  • This list of endpoints (hosts, containers, etc.) for all services
  • The ports to listen on
  • The list of of domains and routes to serve, and which services to connect them to

Out-of-the-box, Rotor configures a single listener on port 80. For each service, Rotor creates a domain with the same name as the service, and a single “/” route that sends all traffic for that domain to the service. For example, if you have a service called “auth.example.com,” served by 2 containers, auth0 and auth1, Rotor will create:

  • A cluster for CDS called auth.example.com
  • Two endpoints for EDS in the auth cluster, auth0, and auth1
  • A single listener for LDS, available at 0.0.0.0:80
  • A single route for http://auth.example.com:80/ that connects to the auth.example.com cluster

Broad Integration

Today, Rotor supports the following service discovery services:

  • Kubernetes
  • Consul
  • ECS
  • EC2
  • DC/OS
  • Envoy v1 CDS/SDS (experimental)
  • Envoy v2 CDS/EDS (experimental)

Simply pass the right environment variables and Rotor will do the rest. If you’re running something else, you can also configure Rotor to read from a flat file, allowing you to easily integrate with in-house services or SD flavors we haven’t integrated.

Open-Source Through and Through

Many people start with go-control-plane from the Envoy project, since it provides the reference implementation for the Envoy gRPC API. It’s a great idea, and we’ll continue to stay up-to-date with go-control-plane.

We’re always happy to accept patches from the community. In particular we’d love to support other mechanisms of service discovery. Please see Contributing to Turbine Labs Open Source Projects for more information.

If you need more than what we’ve written, feel free to fork the repo on Github and make any changes you need.

See Rotor in Action

Want to try Rotor on your laptop? We’ve put together an example with Consul to show you just how easy it is to bridge your service definitions to Envoy. Plus, it includes some pretty great ASCII art.

Moo!

Getting More

Rotor will remain a core part of our product offering, and it will stay free forever.

If you want more flexibility, you can sign up for a Turbine Labs account and add the API key to Rotor. This unlocks:

  • Houston’s easy-to-use UI for creating and modifying routes, including the ability to route traffic from a single domain to different services.
  • Full configuration of all of Envoy’s features: advanced load balancing, health checking, circuit breakers, and more.
  • Automatic collection of Envoy’s metrics for routes, clusters, and more, with easy integration into statsd, Prometheus, and other common dashboards.
  • Bridging of more than one type of service discovery, e.g. to help you migrate between EC2 and Kubernetes.

If you already have a Turbine Labs account, see the docs for how to get started with Rotor and Houston!