Envoy Gateway Core Concepts: Gateway, Listener, Proxy, and the Route Family Explained

7 min read

A lot of people's first impression of Gateway API is something like: "The term count isn't that high, but my brain feels like it's watching a cast list full of characters with similar names — I can't tell who's the protagonist and who's a side character." This post is here to cut through that confusion, and cover the common route types along the way.

The Overall Architecture

The official Envoy Gateway concepts break the system into three layers:

  • User Configuration: The Gateway API resources and Envoy Gateway extension CRDs you write
  • Envoy Gateway Controller: Reads resources, validates them, and translates config
  • Envoy Proxy: The data plane that actually handles traffic

This means what you're usually editing is not Envoy Proxy itself — you're "declaring what you want." Envoy Gateway translates those declarations into config that Envoy Proxy can execute. That's what makes it nicer than writing proxy config by hand.

The Key Roles

Just remember these for now:

  • GatewayClass: Defines "which Gateway implementation to use in this cluster"
  • Gateway: Defines "where the ingress is and what protocol it speaks"
  • Listener: Defines a specific port/protocol/hostname ingress slot
  • Route: Defines "which requests go to which Service"
  • Envoy Proxy: The actual Gateway Proxy that receives and forwards traffic

In plain English:

  • GatewayClass is the spec sheet
  • Gateway is the building's front entrance
  • Listener is the front desk
  • Route is the signage inside the building
  • Envoy Proxy is the security system doing access control and escorting

Without any one of these, traffic won't get where you want it to go.

A Minimal YAML That Shows the Full Picture

Here's the smallest understandable example:

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000

Chained together, the logic is:

  1. GatewayClass says the Envoy Gateway controller is in charge
  2. Gateway declares one HTTP ingress on port 80
  3. HTTPRoute says requests for www.example.com should go to backend:3000
  4. Envoy Gateway translates all of this for Envoy Proxy

Understanding Each Field

GatewayClass

This is a cluster-level ingress type definition. The most critical field is usually:

spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

This simply means: "This GatewayClass is managed by the Envoy Gateway controller."

If the controllerName doesn't match, it's like ordering delivery to the wrong company — nobody picks it up.

Gateway

This defines "what the ingress looks like." The most-referenced field is listeners:

listeners:
  - name: http
    protocol: HTTP
    port: 80

This means:

  • Open a listener named http
  • Accept HTTP traffic
  • Listen externally on port 80

For HTTPS, you'd typically add another listener with protocol: HTTPS and attach TLS config.

Gateway commonly manages:

  • External port and protocol
  • Per-listener hostname
  • TLS termination location
  • Which namespaces' routes can attach

Gateway is more of a platform-layer concern — its ownership typically sits with the platform team.

Listener

This is the most commonly overlooked role for beginners, but it's actually crucial.

A listener is an outward-facing ingress slot on the Gateway. It defines:

  • name
  • port
  • protocol
  • hostname
  • tls
  • allowedRoutes

Example:

listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: api.example.com

This means:

  • This slot is named https
  • Accepts HTTPS
  • Listens on port 443
  • Dedicated to api.example.com

If you have multiple listeners like:

  • http for port 80
  • https for port 443
  • grpc for port 50051

You're opening multiple ingress slots on the same Gateway, each capable of attaching different routes.

Envoy Proxy

Many people focus only on the YAML and forget that Envoy Proxy is what actually handles live traffic.

Its role is:

  • Receiving client requests
  • Matching against config pushed by Envoy Gateway
  • Forwarding traffic to the appropriate backend
  • Handling TLS, headers, timeouts, retries, and other data-plane behaviors

So think of Envoy Gateway as the "control plane," and Envoy Proxy as the "data plane / Gateway Proxy."

The Route Family

Route isn't just HTTPRoute. The whole family is central to Gateway API's design.

HTTPRoute

This is what you'll write and modify most often. Three key fields:

spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000
  • parentRefs: Which Gateway to attach to
  • hostnames: Which Host header triggers this rule
  • backendRefs: Where to send matched requests

The most common confusion: Gateway is not where you write fine-grained routing — HTTPRoute is what actually decides "how to split traffic."

GRPCRoute

If you're handling gRPC, GRPCRoute is more natural than forcing it into HTTPRoute.

It can match on:

  • gRPC hostname
  • gRPC service
  • gRPC method
  • headers

Example:

matches:
  - method:
      service: com.example.User
      method: Login

This semantics aligns naturally with gRPC — you're not just matching URL paths, you're matching directly against the gRPC service/method model.

The official docs also note: if GRPCRoute and HTTPRoute share the same listener and have conflicting hostnames, implementations should reject one. Basically, don't let HTTP and gRPC fight over the same hostname.

TCPRoute

TCPRoute handles raw TCP traffic. Unlike HTTPRoute, it doesn't understand path or header semantics at L7 — it's closer to L4 forwarding.

Appropriate scenarios:

  • Non-HTTP protocol services
  • Pure TCP services
  • Routing connections to different backends based only on listener port

Databases with custom protocols or proprietary TCP protocols are typical TCPRoute use cases.

TLSRoute

TLSRoute handles TLS traffic and is particularly common in TLS passthrough scenarios.

Core concept:

  • The Gateway doesn't necessarily terminate TLS
  • It may route traffic based solely on the SNI hostname in the TLS handshake
  • Encrypted traffic is preserved all the way to the backend

This matters for scenarios requiring end-to-end encryption, or where you don't want TLS terminated at the Gateway.

How to Choose a Route Type

Requirement Use This
Websites, REST APIs, general web traffic HTTPRoute
gRPC service/method routing GRPCRoute
Raw TCP traffic TCPRoute
TLS passthrough / SNI-based routing TLSRoute

This table matters because many people instinctively write HTTPRoute for everything. But if you're actually dealing with gRPC or TCP, forcing it into HTTPRoute just makes the YAML increasingly awkward.

Why Routes Are Easier to Reason About Than Ingress

Old Ingress configs often squeezed too many responsibilities into a single resource, leading to some persistent pain points:

  • Platform config and app routing mixed together
  • Advanced features expressed via annotations with poor readability
  • Limited expressiveness for non-HTTP protocols

Gateway API's approach is to split responsibilities:

  • Platform teams manage GatewayClass / Gateway
  • App teams manage their own HTTPRoute

This separation works well for multi-person collaboration. You don't need to touch the entire ingress layer just to change a path — team stepping-on-each-other rates drop significantly.

Start Paying Attention to Status

Beyond spec, gradually build the habit of checking status. Especially for HTTPRoute and Gateway:

kubectl get gateway eg -o yaml
kubectl get httproute backend -o yaml

Start by checking:

  • Whether the route was Accepted
  • Whether the gateway listener is Ready
  • Whether an address was successfully assigned

It's like checking exam results. Don't just verify that you submitted — verify that it was graded and passed.

One-Line Summary

Think of GatewayClass, Gateway, Listener, Route, and Envoy Proxy as "who manages it, how the ingress opens, how each slot connects, how traffic splits, and who executes it" — and you've already grasped 80% of the core concepts.

💡 Beginners often dive straight into CRD details. Don't rush — get these roles straight first, and the YAML will stop feeling like meeting strangers every time.

Next Step

Now that concepts are in place, the next post digs into the most common HTTP routing scenarios — host, path, header, and traffic splitting: 👉 HTTP Routing in Practice