Following the interest from readers of my previous blog post Kubernetes Gateway API on AKS Exposed via Azure Application Gateway, I've put together the AWS equivalent.
This post focuses on implementing the equivalent solution where web applications on EKS are exposed via AWS Application Load Balancer (ALB). In the real world, you don't always get a greenfield opportunity to design the cleanest and most optimal architecture. More often, you need to retrofit the best possible solution to existing standards and platforms. This blog post examines exactly that situation where Kubernetes-hosted workloads need to be exposed via an existing platform with Load Balancers and WAF (or a WAF sandwich architecture). This approach is particularly relevant for organisations that already have ALBs with WAF implementation in place and need to leverage these existing platform capabilities to expose applications to the internet securely. I'll discuss the optimised reference architecture for greenfield deployments in a separate blog post.
In addition to the AWS-specific implementation, this POC introduces a couple of improvements to bring it closer to a reference architecture:
- ArgoCD for GitOps-style deployments – Kubernetes customisations and application deployments are now managed through ArgoCD, enabling declarative, version-controlled infrastructure
- Separate node pools – Introduction of dedicated System node pools (for critical add-ons like ArgoCD, Istio, and the LB Controller) and User node pools (for application workloads), providing better resource isolation and operational control
- Well-defined architecture layers – Clear separation between Cloud foundations, Kubernetes cluster setup, Kubernetes customisations, and application deployment, making the solution easier to understand, maintain, and extend
I have developed a POC to demonstrate how to set up K8s Gateway API on EKS with Istio Ambient Mesh. The complete solution is available at GitHub.
The Challenge
Integrating Kubernetes Gateway API with AWS load balancers in an EKS cluster requires understanding the interaction between multiple AWS and Kubernetes components:
- Coordinating AWS ALB, Internal NLB, and Istio Gateway
- Configuring the AWS Load Balancer Controller for Gateway API
- Setting up proper health checks through the load balancer chain
- Implementing end-to-end TLS termination
This POC documents the solution to these challenges, providing a working reference architecture for teams facing similar requirements.
The POC Solution
The POC deploys sample applications in an EKS cluster, exposed via Kubernetes Gateway API and accessed through AWS ALB.
| Component | Description |
|---|---|
| sample-app-1 | Nginx pod returning "Hello from App 1" on path /app1 |
| sample-app-2 | Nginx pod returning "Hello from App 2" on path /app2 |
| users-api | Sample API service on path /api/users |
| health-responder | Dedicated pod for ALB health probes on /healthz |
| Istio Gateway | Shared Gateway resource implementing K8s Gateway API |
| HTTPRoutes | Per-path routing rules in application namespaces |
Each application has its own HTTPRoute in its namespace, demonstrating the self-service routing model where application teams manage their own routes while sharing a common gateway infrastructure.
Note: To keep this POC simple and focused on the AWS integration, app1 and app2 simulate applications running in two separate tenants inside the EKS cluster. I am planning a separate blog post on how to set up multi-tenancy on Kubernetes with Capsule and K8s Gateway API.
Architecture Overview
Note: The diagram shows "Public Subnet" and "Private Subnet" as single boxes for simplicity, but the actual implementation creates multiple subnets across Availability Zones (default: 2 AZs) for high availability.
| Component | Purpose |
|---|---|
| AWS ALB | Public entry point (Internet-facing, Layer 7) |
| Internal NLB | Connects ALB to EKS cluster (Layer 4), Logically a part of the Gateway API |
| Istio Gateway | Kubernetes Gateway API implementation |
| HTTPRoutes | Per-namespace routing rules for tenants |
| Istio Ambient Mesh | mTLS between services without sidecars |
Architecture Layers
This POC follows a well-defined layered architecture that separates concerns and makes the solution easier to understand, maintain, and extend.
| Layer | Tool | What It Creates |
|---|---|---|
| Layer 1 | Terraform | VPC, Subnets (Public/Private), NAT/IGW, Route Tables |
| Layer 2 | Terraform | EKS, Node Groups (System/User), IAM, ArgoCD, LB Controller, ALB |
| Layer 3 | ArgoCD | Gateway API CRDs, Istio Ambient, Gateway, HTTPRoutes |
| Layer 4 | ArgoCD | Applications (app1, app2, users-api, health-responder) |
This layered approach provides clear boundaries between infrastructure provisioning (Terraform) and Kubernetes configuration (ArgoCD), making it easier for different teams to own and manage their respective layers.
Traffic Flow
EKS Cluster Architecture
The EKS cluster uses a node pool separation strategy:
| Node Pool | Taint | Workloads |
|---|---|---|
| System Nodes | CriticalAddonsOnly | ArgoCD, Istio components, AWS LB Controller |
| User Nodes | None | Application workloads (app1, app2, users-api) |
Critical Fix for Health Probes
During implementation, I discovered that proper health probe routing is essential for this integration to work.
HTTPRoute for Health Probes
Problem: ALB health probes to /healthz/ready returned 404 because Istio Gateway (Envoy) didn't know how to route health check requests.
Solution: Create a dedicated HTTPRoute that routes /healthz/* to a health-responder service.
HTTPRoute Configuration:
# Health probe routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: health-route
namespace: gateway-health
spec:
parentRefs:
- name: mtkc-gateway
namespace: istio-ingress
rules:
- matches:
- path:
type: PathPrefix
value: /healthz
backendRefs:
- name: health-responder
port: 8080
This fix provides a more meaningful health check of the application stack rather than just checking if the load balancer is reachable.
Try It Yourself
The complete solution is available as a POC repository with:
- Terraform infrastructure as code
- Kubernetes manifests for Gateway API
- ArgoCD for GitOps deployments
- Automated deployment scripts
- Validation test suite
Repository: github.com/shanaka-versent/EKS-Istio-GatewayAPI-Deom
The README contains detailed prerequisites, step-by-step deployment instructions, and troubleshooting guide.
Note on Azure-Specific Fixes
If you've read my Azure AKS implementation, you'll notice that Azure required an additional fix for externalTrafficPolicy: Local to handle Direct Server Return (DSR) with Floating IP.
This fix is not required on AWS EKS. Here's why:
| Aspect | Azure Internal LB | AWS Internal NLB |
|---|---|---|
| Routing Mechanism | Direct Server Return (DSR) with Floating IP | IP target type with VPC routing |
| SNAT Behaviour | Requires externalTrafficPolicy: Local to prevent SNAT |
VPC routes traffic directly to pod IPs |
| Configuration | Needs patch after Gateway creation | Works with default settings |
AWS NLB with IP target type uses VPC routing directly to pod IPs, avoiding the SNAT issue entirely. This makes the AWS implementation slightly simpler.
Why Kubernetes Gateway API?
While the retirement of Ingress-NGINX is a catalyst for change, the real reason to adopt Kubernetes Gateway API is its superior design for building advanced platforms like multi-tenant Kubernetes clusters.
In nutshell, Kubernetes Gateway API provides a superior approach to multi-tenancy compared to legacy Ingress controllers:
- Role-Oriented Design: Clear separation between infrastructure providers (GatewayClass), cluster operators (Gateway), and application developers (HTTPRoute)
- Standardised Extensibility: Consistent way to extend functionality across implementations
- Self-Service Routing: Application teams manage their own HTTPRoutes while sharing common gateway infrastructure
- Reduced Overhead: Single shared Gateway eliminates need for separate Ingress controllers per tenant
Why Istio Ambient Mesh?
This solution uses Istio Ambient Mesh, which provides a Gateway API implementation. We chose Ambient mode over the traditional sidecar mode for the reasons outlined below.
| Aspect | Sidecar Mode | Ambient Mode |
|---|---|---|
| Containers per Pod | 2 (app + proxy) | 1 (app only) |
| Resource Overhead | Higher | Lower |
| Startup Latency | Higher | Lower |
| Mesh Updates | Pod restart required | Node-level update |
| Complexity | Sidecar injection management | Simplified operations |
| Security | Larger attack surface (full Envoy per pod) | Smaller attack surface (lightweight ztunnel) |
We chose Ambient mode for this POC because of its lower resource overhead, simplified operations, and improved security posture—no sidecar injection to manage, no pod restarts required for mesh updates, and a reduced attack surface.
Cloud Provider Comparison
For those working across multiple cloud providers, here's how the components map between Azure and AWS:
| Component | Azure (AKS) | AWS (EKS) |
|---|---|---|
| External L7 LB | Azure App Gateway | AWS ALB |
| Internal L4 LB | Azure Internal LB | AWS Internal NLB |
| LB Controller | cloud-controller-manager | AWS Load Balancer Controller |
| Service Mesh | Istio Gateway | Istio Gateway |
| Gateway API | Same (Kubernetes standard) | Same (Kubernetes standard) |
| GitOps | ArgoCD | ArgoCD |
Critical Fixes Comparison
| Fix | Description | AKS | EKS |
|---|---|---|---|
| Health Probe HTTPRoute | Route /healthz/* to health-responder |
Required | Required |
| externalTrafficPolicy: Local | Prevent SNAT for Azure DSR | Required | Not required |
Conclusion
This POC provides a working solution for implementing Kubernetes Gateway API on AWS EKS with Istio Ambient Mesh, exposed through AWS ALB.
Key takeaways:
- Kubernetes Gateway API is the right choice for building advanced platforms like multi-tenant clusters, offering role-oriented design, standardised extensibility, and self-service routing
- Istio Ambient Mesh provides a Gateway API implementation with operational and security advantages over sidecar mode
- HTTPRoute for health probes is required for proper ALB health checks through the Istio Gateway
- AWS implementation is simpler than Azure in one aspect—no externalTrafficPolicy fix needed due to how AWS NLB handles routing
This approach aligns with the broader ecosystem direction. With Ingress-NGINX being retired in March 2026, the patterns documented here position you well for the future.
Resources
- EKS POC Repository
- AKS POC Repository
- Kubernetes Blog: Ingress-NGINX Retirement
- Kubernetes Gateway API Documentation
- Istio Ambient Mesh Documentation
About the Author
Shanaka Jayasundera is a Solutions Architect specialised in Application Modernisation, Application Integration and cloud-native technologies. Connect on GitHub or via email at shanakaj@gmail.com.






Top comments (0)