Gateway API (Envoy) with EKS Network Load Balancer

Kubernetes Gateway API is the official next-generation standard for routing, load balancing, and service mesh management in Kubernetes.
This guide demonstrates how to implement North/South ingress traffic on Amazon EKS using Envoy Gateway integrated with an AWS Network Load Balancer (NLB) in IP-target mode.
📁 Source Code: aws-eks-terraform / EKS-Envoy-Gateway
📺 Video Walkthrough
Gateway API Resource Hierarchy
graph TD
GC["GatewayClass (Cluster Operator / Infrastructure Definition)"]
EP["EnvoyProxy (AWS NLB Annotations & Proxy Settings)"]
GW["Gateway (Network Admin / NLB Listener Definition)"]
HR["HTTPRoute (Application Developer / Routing Rules)"]
Svc["Kubernetes Service (Backend Workload)"]
EP -.-> GC
GC --> GW
GW --> HR
HR --> Svc
GatewayClass: Defines the gateway controller implementation (Envoy Gateway) and references provider configurations.EnvoyProxy: Provider-specific CRD used to inject AWS Load Balancer Controller annotations onto the generated Envoy Service.Gateway: Declares listeners (ports, protocols, TLS certificates) and triggers the creation of the AWS NLB.HTTPRoute: Defines HTTP routing rules, path prefixes, hostnames, and backend Services.
Step-by-Step Implementation
Step 1. Prerequisites
- Amazon EKS cluster (v1.30+) with VPC-CNI and AWS Load Balancer Controller installed.
- Subnets tagged with
"kubernetes.io/role/elb" = "1"(public) and"kubernetes.io/role/internal-elb" = "1"(private).
Step 2. Install Envoy Gateway via Helm
helm install gateway oci://docker.io/envoyproxy/gateway-helm \
--version v1.2.0 \
-n gateway-system \
--create-namespace
Step 3. Create EnvoyProxy to Configure AWS NLB
The EnvoyProxy CRD customizes the Envoy proxy deployment and its associated Kubernetes Service. We add AWS Load Balancer Controller annotations to create an internet-facing NLB in ip target mode with client IP preservation.
external-envoy-proxy.yaml
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: external-proxy-config
namespace: gateway-system
spec:
provider:
type: Kubernetes
kubernetes:
envoyService:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: preserve_client_ip.enabled=true
Step 4. Create GatewayClass
Link the GatewayClass to the EnvoyProxy configuration defined above.
external-gatewayclass.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: external-gatewayclass
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: external-proxy-config
namespace: gateway-system
Step 5. Create Gateway and Listeners
Instantiating a Gateway triggers Envoy Gateway to create the Envoy proxy pods and the AWS NLB.
external-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: external-gateway
namespace: gateway-system
spec:
gatewayClassName: external-gatewayclass
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
Step 6. Create HTTPRoute for Workload Routing
Define routing rules mapping incoming requests to your application Service.
echoserver-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: echoserver-route
namespace: default
spec:
parentRefs:
- name: external-gateway
namespace: gateway-system
sectionName: http
hostnames:
- "demo.vettom.pages.dev"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: echoserver-svc
port: 80