Skip to content

05: Envoy Gateway

5.1 Introduction

Envoy Gateway is the modern, standardized, Kubernetes-native gateway built on top of the Envoy Proxy. Unlike traditional ingress controllers, Envoy Gateway uses the Gateway API specification—a more powerful, expressive, extensible API created by the Kubernetes networking SIG.

In LocalCloudLab, Envoy Gateway is responsible for:

• Handling all inbound HTTP/HTTPS traffic into the cluster
• Terminating TLS for your public domains
• Routing requests to Search API and Checkin API
• Enforcing routing rules and security policies
• Integrating with cert-manager for automatic SSL certificates
• Providing a clear separation between application logic and traffic management

Envoy Gateway transforms your cluster into a production-grade platform with:

• Host-based routing
• Path-based routing
• TLS configuration
• Request/response transformations
• Extensible policies
• High-performance data plane (Envoy Proxy)

This section is one of the most important in LocalCloudLab because it is the entry point for all external clients accessing your APIs—including real users, test tools, browser requests, and mobile apps.

You will learn how to install Envoy Gateway using supported Helm charts, configure Gateway API resources, issue certificates using cert-manager, and validate the final routing setup.

5.2 Envoy Gateway vs Envoy Proxy vs Ingress Controller

Before installation, it is important to differentiate the three major concepts you will encounter:

5.2.1 Envoy Proxy

Envoy Proxy is a high-performance L7 proxy used widely in service meshes (e.g., Istio) and gateways.

It is a: • High-performance data plane • Proxy engine capable of advanced traffic operations • Foundation for many modern cloud-native networking tools

But by itself, Envoy Proxy does NOT include: • A Kubernetes-native API • Reconciliation controllers • CRDs for gateway resources • Automatic configuration management

Envoy Proxy alone requires manual config files—too low-level for Kubernetes.

5.2.2 Envoy Gateway

Envoy Gateway is: • A Kubernetes controller • A translation layer between Gateway API resources and Envoy configuration • A manager that deploys Envoy data-plane pods • A controller that reconciles Gateway, HTTPRoute, ReferenceGrant, etc.

In short: • Gateway API config → Envoy Gateway → Envoy Proxy dataplane

Envoy Gateway automates: • Deployment of Envoy proxies • Certificate wiring • Configuration management • Traffic routing • Error handling

This is perfect for LocalCloudLab.

5.2.3 Ingress Controller (NGINX, Traefik, etc.)

Traditional Ingress Controllers use the older Ingress API.

Limitations of the Ingress API: • Weak expressive power • No separation between listeners and routes • Not very extensible • Harder to model complex routing • Vendor-specific annotations everywhere

Gateway API solves these issues and is the future of Kubernetes ingress.

Envoy Gateway fully embraces Gateway API.

5.3 Why Envoy Gateway for LocalCloudLab?

There are several reasons why Envoy Gateway is chosen over alternatives:

✔ Modern, future-proof API (Gateway API)

Kubernetes Ingress is effectively being replaced by Gateway API.

Envoy Gateway is the reference implementation for Gateway API.

✔ Very high performance

Envoy is battle-tested at: • Lyft • Google • Apple • Cloudflare • Amazon AppMesh

It is one of the fastest proxies in the world.

✔ Easy integration with cert-manager

Envoy Gateway + cert-manager provide: • Automatic HTTPS • Automatic renewal • DNS-based or HTTP-based validation

✔ Clear separation of concerns

Gateway = listener configuration HTTPRoutes = application routing rules

✔ Perfect match for microservices

You will manage routes separately for: • Search API • Checkin API • Additional APIs in the future

✔ Production-grade capabilities

Envoy supports: • mTLS • JWT authentication • Rate limiting • Load balancing strategies • Timeout & retry policies • Response rewriting • Request header manipulations

LocalCloudLab doesn’t require all these features now, but the architecture supports them.

5.4 Helm Installation (Non-Deprecated Chart)

Next, we install Envoy Gateway using the official Helm chart.

We use: • Latest stable version • Recommended repository • Best-practice installation pattern

5.4.1 Add the Envoy Gateway Helm repo

helm repo add envoy-gateway https://gateway.envoyproxy.io/helm
helm repo update

5.4.2 Create namespace

kubectl create namespace envoy-gateway-system

5.4.3 Install Envoy Gateway

helm install eg envoy-gateway/envoy-gateway -n envoy-gateway-system

This installation deploys: • envoy-gateway controller • envoy proxy daemonset (or deployment depending on chart version) • Gateway API CRDs (if not already installed)

Check resources:

kubectl get pods -n envoy-gateway-system

You should see: • envoy-gateway controller • envoy-proxy pods

5.4.4 Verify CRDs were installed

kubectl get crds | grep gateway

You should see: • gateways.gateway.networking.k8s.io • httproutes.gateway.networking.k8s.io • referencegrants.gateway.networking.k8s.io • backendpolicies.gateway.envoyproxy.io • tlsroutes.gateway.networking.k8s.io • more depending on version

If CRDs are missing, the installation must be repeated.

(End of Part 1 — Part 2 will continue with Gateway architecture and creating the main Gateway resource.)

5.5 Envoy Gateway Architecture

To use Envoy Gateway effectively, it is essential to understand how its architecture is structured. Envoy Gateway consists of two major layers:

1. The **Control Plane** (Envoy Gateway controller)
2. The **Data Plane** (Envoy Proxy instances)

These work together to translate Gateway API resources into real routing behavior.

5.5.1 Control Plane: Envoy Gateway Controller

The controller is the brain of the system.

It performs the following responsibilities:

• Watches Kubernetes resources:
    - Gateway
    - HTTPRoute
    - ReferenceGrant
    - Service
    - Secrets (TLS certs)

• Validates configurations
• Creates Envoy Proxy bootstrap configurations
• Ensures Envoy pods reflect the desired routing state
• Updates configuration when new routes, certs, or domains appear

You can view the controller logs:

kubectl logs -n envoy-gateway-system deploy/envoy-gateway

5.5.2 Data Plane: Envoy Proxy

Envoy Proxy handles real network traffic.

Envoy performs:

• TLS termination
• Routing decisions
• Load balancing across backends
• HTTP/2 and gRPC support
• Retry and timeout policies
• Header manipulation
• Error handling
• Metrics emission

Envoy is deployed either as:

• a DaemonSet (one per node), or
• a Deployment (one or more pods)

Check Envoy pods:

kubectl get pods -n envoy-gateway-system -l app.kubernetes.io/name=envoy

5.5.3 Gateway API as the Configuration Layer

Gateway API CRDs give you a clean and modern configuration model.

Core resources include:

• Gateway
• HTTPRoute
• TLSRoute
• TCPRoute
• ReferenceGrant

Envoy Gateway specifically uses:

• Gateway
• HTTPRoute
• ReferenceGrant

This model separates:

Listener configuration (Gateway)
from
Routing logic (HTTPRoute)

Which is significantly cleaner than the old Ingress model.

5.5.4 Reconciliation Flow (Important)

The sequence for routing traffic is:

1. You apply a Gateway manifest
2. Envoy Gateway controller receives it
3. You apply HTTPRoutes referencing the Gateway
4. Controller validates routes and services
5. Controller generates Envoy configuration
6. Envoy proxies reload their dynamic config
7. Traffic immediately reflects the new rules

This architecture makes routing highly dynamic and robust.

5.6 Creating the Main Gateway Resource

The Gateway resource defines:

• Which ports Envoy listens on
• Which protocols (HTTP, HTTPS)
• Whether TLS termination is enabled
• Which routes may attach to it

This is the “front door” of your cluster.

5.6.1 Create gateway.yaml

You will store this in your Git repo, under:

k8s/gateway/gateway.yaml

Content:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: envoy-gateway-system
spec:
  gatewayClassName: envoy-gateway
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: All
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: tls-cert
            kind: Secret
      allowedRoutes:
        namespaces:
          from: All

Explanation:

• Listener 1: HTTP on port 80
• Listener 2: HTTPS on port 443 with TLS termination
• Envoy Gateway will read TLS certs from a Secret named tls-cert
• All routes in any namespace may attach to this Gateway

Apply it:

kubectl apply -f k8s/gateway/gateway.yaml

5.6.2 MetalLB will assign an External IP

Because the Gateway spawns a Service of type LoadBalancer, MetalLB assigns an IP from the pool:

kubectl get svc -n envoy-gateway-system

Expected:

NAME            TYPE           EXTERNAL-IP        PORT(S)
envoy-gateway   LoadBalancer   172.18.255.200     80, 443

This will be your public entry point.

5.7 Attaching Routes to the Gateway

Defining the Gateway is only part 1.

Now we attach HTTPRoutes for:

• Search API
• Checkin API

Each route maps:

• Hostnames (e.g., search.hershkowitz.co.il)
• Paths (e.g., /health, /search)
• Backend services (Service objects)

We cover full route examples in the next section.

5.8 Creating HTTPRoutes for Search and Checkin APIs

Now that the Gateway is created and exposed via MetalLB, we attach routing rules to it. This is done through HTTPRoute resources.

Each HTTPRoute defines:

• Which hostnames it matches
• Which paths it matches
• Which Kubernetes Services receive the traffic
• Optional filters (headers, redirects, rewrites)

In LocalCloudLab, we create two routes:

1. Search API route
2. Checkin API route

5.8.1 Prerequisites

Before creating HTTPRoutes, ensure that:

• The Search API and Checkin API Deployments are running
• Each has a stable Kubernetes Service (ClusterIP)
• DNS records point to the Envoy external IP

Examples: search.hershkowitz.co.il → 172.18.255.200 checkin.hershkowitz.co.il → 172.18.255.200

5.8.2 Search API HTTPRoute

Create file:

k8s/gateway/search-api-route.yaml

Contents:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: search-api-route
  namespace: search
spec:
  parentRefs:
    - name: main-gateway
      namespace: envoy-gateway-system
  hostnames:
    - "search.hershkowitz.co.il"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: search-api-svc
          port: 80

Explanation:

• All requests to search.hershkowitz.co.il go to search-api-svc:80
• PathPrefix "/" means everything is routed
• No rewrites needed unless APIs require them

Apply:

kubectl apply -f k8s/gateway/search-api-route.yaml

5.8.3 Checkin API HTTPRoute

Create:

k8s/gateway/checkin-api-route.yaml

Contents:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: checkin-api-route
  namespace: checkin
spec:
  parentRefs:
    - name: main-gateway
      namespace: envoy-gateway-system
  hostnames:
    - "checkin.hershkowitz.co.il"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: checkin-api-svc
          port: 80

Apply:

kubectl apply -f k8s/gateway/checkin-api-route.yaml

5.8.4 Verifying Routes

Run:

kubectl get httproutes --all-namespaces

You should see:

search    search-api-route     Accepted
checkin   checkin-api-route    Accepted

Use describe for debugging:

kubectl describe httproute -n search search-api-route

5.9 Integrating cert-manager for TLS

To enable HTTPS termination at Envoy Gateway, you need certificates.

cert-manager automates:

• Certificate creation
• Renewal
• DNS validation
• Secret management

Envoy Gateway reads TLS certs from Kubernetes Secrets referenced in the Gateway resource.

5.9.1 Install cert-manager (non-deprecated Helm chart)

Add repo:

helm repo add jetstack https://charts.jetstack.io
helm repo update

Install:

helm install cert-manager jetstack/cert-manager       --namespace cert-manager       --create-namespace       --set crds.enabled=true

Verify:

kubectl get pods -n cert-manager

5.9.2 Create ClusterIssuer for Let's Encrypt (Production)

Create:

k8s/cert-manager/cluster-issuer.yaml

Contents:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: your-email@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: acme-private-key
    solvers:
      - http01:
          gatewayHTTPRoute:
            parentRef:
              name: main-gateway
              namespace: envoy-gateway-system

Apply:

kubectl apply -f k8s/cert-manager/cluster-issuer.yaml

5.9.3 Create Certificate resource for the Gateway

Create:

k8s/cert-manager/tls-cert.yaml

Contents:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: tls-cert
  namespace: envoy-gateway-system
spec:
  secretName: tls-cert
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - "search.hershkowitz.co.il"
    - "checkin.hershkowitz.co.il"

Apply:

kubectl apply -f k8s/cert-manager/tls-cert.yaml

Verify:

kubectl describe certificate -n envoy-gateway-system tls-cert

5.9.4 Envoy Gateway picks up TLS automatically

Envoy Gateway listens for Secrets referenced in Gateway spec.

Your main-gateway already contains:

  tls:
    mode: Terminate
    certificateRefs:
      - name: tls-cert
        kind: Secret

As soon as cert-manager populates the secret, Envoy Gateway reloads configuration.

5.10 Validating Envoy Gateway Routing

Now it’s time to validate that everything works end-to-end.

5.10.1 Validate Gateway status

kubectl get gateway -n envoy-gateway-system
kubectl describe gateway -n envoy-gateway-system main-gateway

5.10.2 Validate Envoy service external IP

kubectl get svc -n envoy-gateway-system

Expected:

envoy-gateway   LoadBalancer   172.18.255.200

5.10.3 Validate HTTP routing

From your PC:

curl http://search.hershkowitz.co.il/health
curl http://checkin.hershkowitz.co.il/health

Expected responses:

ok from Search
ok from Checkin

5.10.4 Validate HTTPS routing

curl -I https://search.hershkowitz.co.il
curl -I https://checkin.hershkowitz.co.il

Expected:

HTTP/2 200
server: envoy

5.10.5 Validate certificate issuance

kubectl get certificate -n envoy-gateway-system

Expected:

tls-cert   True   Ready

5.10.6 Inspect Envoy logs (optional)

kubectl logs -n envoy-gateway-system -l app=envoy -f

5.11 Troubleshooting Envoy Gateway

5.11.1 Route shows “NotAccepted”

Check:

kubectl describe httproute -n search search-api-route

Common issues:

• Wrong parentRef name
• Wrong namespace
• Service not found
• TLS misconfiguration

5.11.2 HTTPS returns 404

Likely cause:

Certificate dnsNames do not include the hostname.

5.11.3 Gateway has no External IP

MetalLB misconfiguration:

• IPAddressPool incorrect
• L2Advertisement missing
• MetalLB pods not running

5.11.4 Cert-manager challenges fail

Check:

kubectl describe challenges.acme.cert-manager.io

5.12 Summary of Section 5

In this section you learned how to:

• Install Envoy Gateway via Helm
• Understand the Envoy architecture (control plane + data plane)
• Create the main Gateway with HTTP and HTTPS listeners
• Attach HTTPRoutes for Search API and Checkin API
• Issue HTTPS certificates using cert-manager + Let’s Encrypt
• Validate routing and TLS termination
• Troubleshoot common issues

Envoy Gateway is the core entry point of LocalCloudLab. From here, all external traffic goes through a modern, cloud-native gateway with full observability and routing control.

Next section (Section 6) will cover: Prometheus, Grafana, Jaeger, Loki, and log/trace correlation.

(End of Section 05 — Complete)