<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shanaka Jayasundera</title>
    <description>The latest articles on DEV Community by Shanaka Jayasundera (@shanaka_jayasundera).</description>
    <link>https://dev.to/shanaka_jayasundera</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3703290%2Fdd560ece-7153-4079-b083-57e663f83a61.jpeg</url>
      <title>DEV Community: Shanaka Jayasundera</title>
      <link>https://dev.to/shanaka_jayasundera</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shanaka_jayasundera"/>
    <language>en</language>
    <item>
      <title>Kubernetes Gateway API on EKS Exposed via ALB</title>
      <dc:creator>Shanaka Jayasundera</dc:creator>
      <pubDate>Tue, 03 Feb 2026 06:45:22 +0000</pubDate>
      <link>https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-eks-exposed-via-alb-1fka</link>
      <guid>https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-eks-exposed-via-alb-1fka</guid>
      <description>&lt;p&gt;Following the interest from readers of my previous blog post &lt;a href="https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-aks-exposed-via-azure-application-gateway-50bo"&gt;Kubernetes Gateway API on AKS Exposed via Azure Application Gateway&lt;/a&gt;, I've put together the AWS equivalent.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In addition to the AWS-specific implementation, this POC introduces a couple of improvements to bring it closer to a reference architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ArgoCD for GitOps-style deployments&lt;/strong&gt; – Kubernetes customisations and application deployments are now managed through ArgoCD, enabling declarative, version-controlled infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate node pools&lt;/strong&gt; – 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&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Well-defined architecture layers&lt;/strong&gt; – Clear separation between Cloud foundations, Kubernetes cluster setup, Kubernetes customisations, and application deployment, making the solution easier to understand, maintain, and extend&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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 &lt;a href="https://github.com/shanaka-versent/EKS-Istio-GatewayAPI-Deom/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;Integrating Kubernetes Gateway API with AWS load balancers in an EKS cluster requires understanding the interaction between multiple AWS and Kubernetes components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coordinating AWS ALB, Internal NLB, and Istio Gateway&lt;/li&gt;
&lt;li&gt;Configuring the AWS Load Balancer Controller for Gateway API&lt;/li&gt;
&lt;li&gt;Setting up proper health checks through the load balancer chain&lt;/li&gt;
&lt;li&gt;Implementing end-to-end TLS termination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This POC documents the solution to these challenges, providing a working reference architecture for teams facing similar requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The POC Solution
&lt;/h2&gt;

&lt;p&gt;The POC deploys sample applications in an EKS cluster, exposed via Kubernetes Gateway API and accessed through AWS ALB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86qacdwwwsqm3dyrc9jo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86qacdwwwsqm3dyrc9jo.png" alt=" " width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sample-app-1&lt;/td&gt;
&lt;td&gt;Nginx pod returning "Hello from App 1" on path /app1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sample-app-2&lt;/td&gt;
&lt;td&gt;Nginx pod returning "Hello from App 2" on path /app2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;users-api&lt;/td&gt;
&lt;td&gt;Sample API service on path /api/users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;health-responder&lt;/td&gt;
&lt;td&gt;Dedicated pod for ALB health probes on /healthz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Istio Gateway&lt;/td&gt;
&lt;td&gt;Shared Gateway resource implementing K8s Gateway API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPRoutes&lt;/td&gt;
&lt;td&gt;Per-path routing rules in application namespaces&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Architecture Overview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi2ip2bpv7fyl1fhidle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi2ip2bpv7fyl1fhidle.png" alt=" " width="800" height="979"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS ALB&lt;/td&gt;
&lt;td&gt;Public entry point (Internet-facing, Layer 7)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal NLB&lt;/td&gt;
&lt;td&gt;Connects ALB to EKS cluster (Layer 4), Logically a part of the Gateway API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Istio Gateway&lt;/td&gt;
&lt;td&gt;Kubernetes Gateway API implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPRoutes&lt;/td&gt;
&lt;td&gt;Per-namespace routing rules for tenants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Istio Ambient Mesh&lt;/td&gt;
&lt;td&gt;mTLS between services without sidecars&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Architecture Layers
&lt;/h3&gt;

&lt;p&gt;This POC follows a well-defined layered architecture that separates concerns and makes the solution easier to understand, maintain, and extend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftu6aex323bmuyk0bxgxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftu6aex323bmuyk0bxgxf.png" alt=" " width="800" height="838"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What It Creates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Terraform&lt;/td&gt;
&lt;td&gt;VPC, Subnets (Public/Private), NAT/IGW, Route Tables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Terraform&lt;/td&gt;
&lt;td&gt;EKS, Node Groups (System/User), IAM, ArgoCD, LB Controller, ALB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ArgoCD&lt;/td&gt;
&lt;td&gt;Gateway API CRDs, Istio Ambient, Gateway, HTTPRoutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ArgoCD&lt;/td&gt;
&lt;td&gt;Applications (app1, app2, users-api, health-responder)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traffic Flow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1var8jdhpxlb2hhwfvcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1var8jdhpxlb2hhwfvcc.png" alt=" " width="800" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  EKS Cluster Architecture
&lt;/h3&gt;

&lt;p&gt;The EKS cluster uses a node pool separation strategy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Pool&lt;/th&gt;
&lt;th&gt;Taint&lt;/th&gt;
&lt;th&gt;Workloads&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System Nodes&lt;/td&gt;
&lt;td&gt;CriticalAddonsOnly&lt;/td&gt;
&lt;td&gt;ArgoCD, Istio components, AWS LB Controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Nodes&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Application workloads (app1, app2, users-api)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Critical Fix for Health Probes
&lt;/h2&gt;

&lt;p&gt;During implementation, I discovered that proper health probe routing is essential for this integration to work.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTPRoute for Health Probes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; ALB health probes to /healthz/ready returned 404 because Istio Gateway (Envoy) didn't know how to route health check requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Create a dedicated HTTPRoute that routes /healthz/* to a health-responder service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsggk8czsfdy4qkbxq7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsggk8czsfdy4qkbxq7y.png" alt=" " width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HTTPRoute Configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Health probe routing&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPRoute&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;health-route&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-health&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parentRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mtkc-gateway&lt;/span&gt;
      &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;istio-ingress&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PathPrefix&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
      &lt;span class="na"&gt;backendRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;health-responder&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fix provides a more meaningful health check of the application stack rather than just checking if the load balancer is reachable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The complete solution is available as a POC repository with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform infrastructure as code&lt;/li&gt;
&lt;li&gt;Kubernetes manifests for Gateway API&lt;/li&gt;
&lt;li&gt;ArgoCD for GitOps deployments&lt;/li&gt;
&lt;li&gt;Automated deployment scripts&lt;/li&gt;
&lt;li&gt;Validation test suite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/shanaka-versent/EKS-Istio-GatewayAPI-Deom/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;github.com/shanaka-versent/EKS-Istio-GatewayAPI-Deom&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The README contains detailed prerequisites, step-by-step deployment instructions, and troubleshooting guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Note on Azure-Specific Fixes
&lt;/h3&gt;

&lt;p&gt;If you've read my &lt;a href="https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-aks-exposed-via-azure-application-gateway-50bo"&gt;Azure AKS implementation&lt;/a&gt;, you'll notice that Azure required an additional fix for &lt;code&gt;externalTrafficPolicy: Local&lt;/code&gt; to handle Direct Server Return (DSR) with Floating IP. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This fix is not required on AWS EKS.&lt;/strong&gt; Here's why:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Azure Internal LB&lt;/th&gt;
&lt;th&gt;AWS Internal NLB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Routing Mechanism&lt;/td&gt;
&lt;td&gt;Direct Server Return (DSR) with Floating IP&lt;/td&gt;
&lt;td&gt;IP target type with VPC routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNAT Behaviour&lt;/td&gt;
&lt;td&gt;Requires &lt;code&gt;externalTrafficPolicy: Local&lt;/code&gt; to prevent SNAT&lt;/td&gt;
&lt;td&gt;VPC routes traffic directly to pod IPs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;Needs patch after Gateway creation&lt;/td&gt;
&lt;td&gt;Works with default settings&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Kubernetes Gateway API?
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0sy8aiu3akfhq0xa31v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0sy8aiu3akfhq0xa31v.png" alt=" " width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In nutshell, Kubernetes Gateway API provides a superior approach to multi-tenancy compared to legacy Ingress controllers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role-Oriented Design:&lt;/strong&gt; Clear separation between infrastructure providers (GatewayClass), cluster operators (Gateway), and application developers (HTTPRoute)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardised Extensibility:&lt;/strong&gt; Consistent way to extend functionality across implementations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Service Routing:&lt;/strong&gt; Application teams manage their own HTTPRoutes while sharing common gateway infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Overhead:&lt;/strong&gt; Single shared Gateway eliminates need for separate Ingress controllers per tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Istio Ambient Mesh?
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Sidecar Mode&lt;/th&gt;
&lt;th&gt;Ambient Mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Containers per Pod&lt;/td&gt;
&lt;td&gt;2 (app + proxy)&lt;/td&gt;
&lt;td&gt;1 (app only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource Overhead&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startup Latency&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mesh Updates&lt;/td&gt;
&lt;td&gt;Pod restart required&lt;/td&gt;
&lt;td&gt;Node-level update&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity&lt;/td&gt;
&lt;td&gt;Sidecar injection management&lt;/td&gt;
&lt;td&gt;Simplified operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Larger attack surface (full Envoy per pod)&lt;/td&gt;
&lt;td&gt;Smaller attack surface (lightweight ztunnel)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud Provider Comparison
&lt;/h2&gt;

&lt;p&gt;For those working across multiple cloud providers, here's how the components map between Azure and AWS:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Azure (AKS)&lt;/th&gt;
&lt;th&gt;AWS (EKS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;External L7 LB&lt;/td&gt;
&lt;td&gt;Azure App Gateway&lt;/td&gt;
&lt;td&gt;AWS ALB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal L4 LB&lt;/td&gt;
&lt;td&gt;Azure Internal LB&lt;/td&gt;
&lt;td&gt;AWS Internal NLB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LB Controller&lt;/td&gt;
&lt;td&gt;cloud-controller-manager&lt;/td&gt;
&lt;td&gt;AWS Load Balancer Controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service Mesh&lt;/td&gt;
&lt;td&gt;Istio Gateway&lt;/td&gt;
&lt;td&gt;Istio Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway API&lt;/td&gt;
&lt;td&gt;Same (Kubernetes standard)&lt;/td&gt;
&lt;td&gt;Same (Kubernetes standard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitOps&lt;/td&gt;
&lt;td&gt;ArgoCD&lt;/td&gt;
&lt;td&gt;ArgoCD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Critical Fixes Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;AKS&lt;/th&gt;
&lt;th&gt;EKS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Health Probe HTTPRoute&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Route &lt;code&gt;/healthz/*&lt;/code&gt; to health-responder&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;externalTrafficPolicy: Local&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prevent SNAT for Azure DSR&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;Not required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This POC provides a working solution for implementing Kubernetes Gateway API on AWS EKS with Istio Ambient Mesh, exposed through AWS ALB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes Gateway API&lt;/strong&gt; is the right choice for building advanced platforms like multi-tenant clusters, offering role-oriented design, standardised extensibility, and self-service routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Istio Ambient Mesh&lt;/strong&gt; provides a Gateway API implementation with operational and security advantages over sidecar mode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTPRoute for health probes&lt;/strong&gt; is required for proper ALB health checks through the Istio Gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS implementation is simpler&lt;/strong&gt; than Azure in one aspect—no externalTrafficPolicy fix needed due to how AWS NLB handles routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/shanaka-versent/EKS-Istio-GatewayAPI-Deom/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;EKS POC Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shanaka-versent/AKS-Istio-GatewayAPI-Demo/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;AKS POC Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" rel="noopener noreferrer"&gt;Kubernetes Blog: Ingress-NGINX Retirement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gateway-api.sigs.k8s.io/" rel="noopener noreferrer"&gt;Kubernetes Gateway API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://istio.io/latest/docs/ambient/" rel="noopener noreferrer"&gt;Istio Ambient Mesh Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;br&gt;
Shanaka Jayasundera is a Solutions Architect specialised in Application Modernisation, Application Integration and cloud-native technologies. Connect on &lt;a href="https://github.com/shanaka-versent" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or via email at &lt;a href="mailto:shanakaj@gmail.com"&gt;shanakaj@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Kubernetes Gateway API on AKS Exposed via Azure Application Gateway</title>
      <dc:creator>Shanaka Jayasundera</dc:creator>
      <pubDate>Sat, 10 Jan 2026 06:53:39 +0000</pubDate>
      <link>https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-aks-exposed-via-azure-application-gateway-50bo</link>
      <guid>https://dev.to/shanaka_jayasundera/kubernetes-gateway-api-on-aks-exposed-via-azure-application-gateway-50bo</guid>
      <description>&lt;p&gt;We had a use case to expose Kubernetes Gateway API from a multi-tenant AKS cluster through Azure Application Gateway(With WAF). The integration wasn't straightforward, health probes failed, backends showed unhealthy, and traffic wouldn't flow. This post details a solution that addresses these integration challenges.&lt;/p&gt;

&lt;p&gt;Since this solution and POC is based on K8s Gateway API on AKS, as a bonus this approach aligns well with the broader Kubernetes ecosystem direction. With Ingress-NGINX being retired in March 2026 and &lt;a href="https://www.linkedin.com/posts/ahmedsabbour_azure-kubernetes-ingress-activity-7394971369727459328-kEE3?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAAF6efABtV-CVs7xqlcTRvzgVQIwfR1u0OA" rel="noopener noreferrer"&gt;Ahmed Sabbour&lt;/a&gt;, Principal PM Lead for Azure Kubernetes Service, confirming that &lt;a href="https://blog.aks.azure.com/2025/11/13/ingress-nginx-update" rel="noopener noreferrer"&gt;AKS Application Routing will be powered by Istio and Gateway API in H1 2026&lt;/a&gt;, adopting Gateway API now positions you well for the future.&lt;/p&gt;

&lt;p&gt;I have developed a POC to demonstrate how to set up K8s Gateway API on AKS and solve the integration challenges when exposing it via Azure Application Gateway in a multi-tenant environment. The complete solution is available at &lt;a href="https://github.com/shanaka-versent/AKS-Istio-GatewayAPI-Demo/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;Integrating Kubernetes Gateway API with Azure Application Gateway in a multi-tenant AKS cluster isn't as straightforward as it should be. When I attempted this integration, I encountered several issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health probes failing - Application Gateway couldn't verify backend health&lt;/li&gt;
&lt;li&gt;Backends marked unhealthy - Despite pods running correctly&lt;/li&gt;
&lt;li&gt;Connection timeouts - Traffic wouldn't flow through the expected path&lt;/li&gt;
&lt;li&gt;No clear documentation - Limited guidance for this specific architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This POC documents the solution to these challenges, providing a working reference architecture for teams facing similar requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The POC Solution
&lt;/h2&gt;

&lt;p&gt;The POC deploys two sample applications (app1 and app2) in an AKS cluster, exposed via Kubernetes Gateway API and accessed through Azure Application Gateway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2m5csbxzc8hhmigl1l8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2m5csbxzc8hhmigl1l8.png" alt="POC Solution overview" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Component&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;sample-app-1&lt;/td&gt;
      &lt;td&gt;Nginx pod returning "Hello from App 1" on path /app1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sample-app-2&lt;/td&gt;
      &lt;td&gt;Nginx pod returning "Hello from App 2" on path /app2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;health-responder&lt;/td&gt;
      &lt;td&gt;Dedicated pod for Application Gateway health probes on /healthz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Istio Gateway&lt;/td&gt;
      &lt;td&gt;Shared Gateway resource implementing K8s Gateway API&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTPRoutes&lt;/td&gt;
      &lt;td&gt;Per-path routing rules in application namespaces&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

  

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: To keep this POC simple and focused on the Azure integration challenges, app1 and app2 simulate applications running in two separate tenants inside the AKS cluster. I am planning a separate blog post on how to set up multi-tenancy on Kubernetes with Capsule and K8s Gateway API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Architecture Overview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freqp4552s1yw3ndh1zzy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freqp4552s1yw3ndh1zzy.png" alt="High-level Solutions Architecture" width="800" height="966"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Component&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Azure Application Gateway&lt;/td&gt;
      &lt;td&gt;Public entry point with WAF and TLS termination&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Internal Load Balancer&lt;/td&gt;
      &lt;td&gt;Connects App Gateway to AKS cluster&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Istio Gateway&lt;/td&gt;
      &lt;td&gt;Kubernetes Gateway API implementation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTPRoutes&lt;/td&gt;
      &lt;td&gt;Per-namespace routing rules for tenants&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Istio Ambient Mesh&lt;/td&gt;
      &lt;td&gt;mTLS between services without sidecars&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  End-to-End TLS Flow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5p9z7cptqr42ku1812y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5p9z7cptqr42ku1812y.png" alt="End-to-End TLS Flow" width="800" height="433"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Kubernetes Gateway API Components
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uho2ta54re2pz3xq8s7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uho2ta54re2pz3xq8s7.png" alt="Kubernetes Gateway API Components" width="800" height="866"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Network Architecture
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb9vgg3mzu81qpfl8a41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb9vgg3mzu81qpfl8a41.png" alt="Network Architecture" width="800" height="734"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  Critical Fixes for Azure Integration
&lt;/h2&gt;

&lt;p&gt;During implementation, I discovered two critical issues specific to Azure. These are the core fixes that make this integration work. They are expected to be resolved when AKS releases their managed Gateway API solution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Fix 1: HTTPRoute for Health Probes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; App Gateway health probes to /healthz/ready returned 404 because Istio Gateway (Envoy) didn't know how to route health check requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Create a dedicated HTTPRoute that routes /healthz/* to a health-responder service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwet9k79kw8g8ogm09xl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwet9k79kw8g8ogm09xl.png" alt="Health Probe" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
HTTPRoute Configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# From kubernetes/05-httproutes.yaml
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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 2: externalTrafficPolicy for Azure DSR
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Azure Internal Load Balancer uses Direct Server Return (DSR) mode. With DSR, inbound requests flow through the load balancer, but responses bypass it and return directly to the client (Application Gateway). The default externalTrafficPolicy: Cluster causes kube-proxy to apply SNAT when forwarding traffic across nodes, which breaks this asymmetric routing pattern and causes connection timeouts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Patch the Gateway service to use externalTrafficPolicy: Local. Ideally include in the automation scripts to patch after the K8s Gateway API is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl patch svc &amp;lt;gateway-service&amp;gt; -n istio-ingress \
  -p '{"spec":{"externalTrafficPolicy":"Local"}}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pm9epvosb5qswirvw3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pm9epvosb5qswirvw3k.png" alt="DSR" width="800" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  How DSR works with the fix
&lt;/h4&gt;

&lt;p&gt;Inbound: Request travels through App Gateway → Internal Load Balancer → directly to node with pod (no cross-node SNAT)&lt;br&gt;
Outbound: Response bypasses the Internal Load Balancer entirely and returns directly to App Gateway&lt;/p&gt;

&lt;p&gt;This asymmetric routing (different paths for request and response) is the key characteristic of DSR that improves performance but requires externalTrafficPolicy: Local to work correctly with Kubernetes. This fix ensures proper traffic flow between Azure Application Gateway and the Kubernetes Gateway API.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Kubernetes Gateway API?
&lt;/h3&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0sy8aiu3akfhq0xa31v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0sy8aiu3akfhq0xa31v.png" alt=" " width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In nutshell, Kubernetes Gateway API provides a superior approach to multi-tenancy compared to legacy Ingress controllers. With Gateway API, a single shared Gateway serves as the centralised entry point, while individual HTTPRoutes in each tenant's namespace define their own routing rules. This eliminates the need to deploy separate Ingress controllers per tenant, reducing infrastructure overhead, simplifying operations, and enabling consistent traffic policies across all tenants through a unified control plane. Stay tuned, I'll explore this further in my next post.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Istio Ambient Mesh?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Aspect&lt;/th&gt;
      &lt;th&gt;Sidecar Mode&lt;/th&gt;
      &lt;th&gt;Ambient Mode&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Containers per Pod&lt;/td&gt;
      &lt;td&gt;2 (app + proxy)&lt;/td&gt;
      &lt;td&gt;1 (app only)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Resource Overhead&lt;/td&gt;
      &lt;td&gt;Higher&lt;/td&gt;
      &lt;td&gt;Lower&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Startup Latency&lt;/td&gt;
      &lt;td&gt;Higher&lt;/td&gt;
      &lt;td&gt;Lower&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mesh Updates&lt;/td&gt;
      &lt;td&gt;Pod restart required&lt;/td&gt;
      &lt;td&gt;Node-level update&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Complexity&lt;/td&gt;
      &lt;td&gt;Sidecar injection management&lt;/td&gt;
      &lt;td&gt;Simplified operations&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Security&lt;/td&gt;
      &lt;td&gt;Larger attack surface (full Envoy per pod, proxy in app pod)&lt;/td&gt;
      &lt;td&gt;Smaller attack surface (lightweight Rust-based ztunnel, isolated from app pod)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note on AKS Istio Add-on: AKS fully supports custom Istio Ambient Mesh deployments, which is the approach used in this POC. The AKS Istio service mesh add-on is currently based on sidecar mode, which is a mature and well-supported option. It would be great to see AKS introduce Ambient mode support in their managed add-on in the future, giving users the choice between both approaches.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;The complete solution is available as a POC repository with:&lt;/p&gt;

&lt;p&gt;Terraform infrastructure as code&lt;br&gt;
Kubernetes manifests for Gateway API&lt;br&gt;
Automated deployment scripts&lt;br&gt;
Validation test suite&lt;br&gt;
Troubleshooting guide&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/shanaka-versent/AKS-Istio-GatewayAPI-Demo/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;github.com/shanaka-versent/AKS-Istio-GatewayAPI-Demo/tree/k8s-gateway-api-poc&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The README contains detailed prerequisites, step-by-step deployment instructions, and solutions to Azure-specific challenges.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We had a use case to expose Kubernetes Gateway API from a multi-tenant AKS cluster through Azure Application Gateway, and the integration wasn't straightforward. This POC provides a working solution that addresses the critical issues, specifically the HTTPRoute configuration for health probes and the externalTrafficPolicy: Local setting to ensure proper traffic flow with Azure's DSR.&lt;br&gt;
Key takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;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 that legacy Ingress controllers cannot match&lt;/li&gt;
&lt;li&gt;Istio Ambient Mesh provides a Gateway API implementation with operational and security advantages over sidecar mode, including lower resource overhead, simplified operations, and a reduced attack surface&lt;/li&gt;
&lt;li&gt;Azure-specific fixes (HTTPRoute for health probes and externalTrafficPolicy for DSR) are required for this integration today, and are expected to be resolved when AKS releases their managed Gateway API solution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach also aligns with the broader ecosystem direction. With Ingress-NGINX being retired and AKS planning to adopt Istio-powered Gateway API in H1 2026, the patterns documented here position you well for the future.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/shanaka-versent/AKS-Istio-GatewayAPI-Demo/tree/k8s-gateway-api-poc" rel="noopener noreferrer"&gt;PoC Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.aks.azure.com/2025/11/13/ingress-nginx-update" rel="noopener noreferrer"&gt;AKS Blog: Ingress-NGINX Update&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kubernetes.dev/blog/2025/11/12/ingress-nginx-retirement/" rel="noopener noreferrer"&gt;Ingress-NGINX Retirement Announcement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;br&gt;
Shanaka Jayasundera is a Solutions Architect specialised in Application Modernisation, Application Integration and cloud-native technologies. Connect on GitHub or via email at &lt;a href="mailto:shanakaj@gmail.com"&gt;shanakaj@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>kubernetes</category>
      <category>gatewayapi</category>
      <category>aks</category>
    </item>
  </channel>
</rss>
