Type to search…
Skip to content

Envoy

Envoy is the proxy that takes care of locating services, distributing requests and retrying them, so that the application doesn't have to.

Taught in
Seguretat i alta disponibilitatServidors ProxyASIX

Introduction

A service that uses another has a problem before sending any request: knowing where it is.

And once it’s solved that, it has a few more.

If there are three copies of the service, which one do you call? If one is down, how does it find out? If the request fails, does it retry it? How many times?

You can write all of this inside the application. Each application, in its own language, with its own bugs.

Or you can take it out, and put a proxy in front that knows how to do it.

Envoy is that proxy: a proxy designed to sit between services, not between the user and the web.

Working environment

Create the envoy directory and, inside it, the compose.yaml file:

yaml
services:
  envoy:
    image: envoyproxy/envoy:v1.39.0
    ports:
      - 10000:10000
      - 9901:9901
    volumes:
      - ./envoy.yaml:/etc/envoy/envoy.yaml

  web:
    image: nginx
    deploy:
      replicas: 3

Three identical web servers and an Envoy in front.

The configuration

Envoy separates two things that in ordinary proxies go together: where a request comes in and where it goes out.

  • A listener is a port where it listens, with the rules that say which request goes where.
  • A cluster is a group of servers doing the same job.

Create envoy.yaml:

yaml
static_resources:
  listeners:
    - name: listener_http
      address:
        socket_address: { address: 0.0.0.0, port_value: 10000 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                route_config:
                  virtual_hosts:
                    - name: web
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route: { cluster: web }
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
    - name: web
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: web
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: web, port_value: 80 }

admin:
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

The type: STRICT_DNS is the part that solves the problem from the beginning.

Envoy doesn’t have a list of IPs: it has a name, web, and it resolves it again every so often.

Compose registers the three replicas under that name, so Envoy discovers three.

shell
docker compose up -d
curl localhost:10000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

Envoy leaves its signature on the response:

shell
curl -sI localhost:10000
HTTP/1.1 200 OK
server: envoy
x-envoy-upstream-service-time: 0

Keep reading — it's free.

The rest of this page is open to anyone with a free account. Nothing is sold here and nothing is charged for: the account exists so we know who agreed to the terms, and so we can send you the newsletter if you want it.

Create a free account

You will be asked to accept the Terms · Privacy Policy