Gateway API vs Ingress: Complete Comparison Guide for Kubernetes Networking

Gateway API vs Ingress: Complete Comparison Guide

Introduction

Kubernetes networking has evolved significantly since the introduction of Ingress. While Ingress served as a good starting point for exposing HTTP applications, it had limitations that became apparent as Kubernetes usage grew more complex. Gateway API is the next-generation specification designed to address these limitations and provide a more expressive, extensible, and role-oriented networking interface.

Ingress: The First Generation

What is Ingress?

Ingress is a Kubernetes resource that manages external access to HTTP/HTTPS services in a cluster. It provides routing rules, SSL termination, and load balancing capabilities.

Key Components:

# Basic Ingress Example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

# TLS Configuration
  tls:
  - hosts:
    - myapp.example.com
    secretName: tls-secret
                

Limitations of Ingress:

  • HTTP-Centric: Primarily designed for HTTP/HTTPS traffic
  • Vendor Annotations: Heavy reliance on implementation-specific annotations
  • Limited Expressiveness: Basic routing capabilities
  • No Role Separation: Single resource for all concerns
  • No Cross-Namespace Support: Can't reference services in other namespaces
  • Limited Protocol Support: Poor support for TCP/UDP, gRPC, WebSocket

Gateway API: The Next Generation

What is Gateway API?

Gateway API is an open-source project managed by Kubernetes SIG-Network. It's designed as an evolution of Ingress, providing a more expressive, extensible, and role-oriented interface for service networking in Kubernetes.

Core Components:

  • GatewayClass: Defines a class of Gateways that can be instantiated
  • Gateway: Describes how traffic is translated to Services
  • HTTPRoute/TCPRoute/UDPRoute/TLSRoute: Protocol-specific routing rules
  • ReferenceGrant: Controls cross-namespace references

Key Features:

# Gateway API Architecture Example
┌─────────────────────────────────────┐
│           GatewayClass              │
│  (e.g., "istio", "nginx", "contour")│
└─────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│             Gateway                 │
│  (Infrastructure Provider managed)  │
└─────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│          HTTPRoute/TCPRoute         │
│       (Application Developer)        │
└─────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│            Services                 │
└─────────────────────────────────────┘
                

Direct Comparison: Gateway API vs Ingress

Feature Comparison Table:

Feature Ingress Gateway API
Protocol Support Primarily HTTP/HTTPS (limited TCP/UDP via annotations) Multi-protocol native (HTTP, TCP, UDP, TLS, gRPC)
Role-Oriented Design Single resource for all roles Explicit separation: Infrastructure, Admin, App Developer
Cross-Namespace Not supported Native support with ReferenceGrant
Traffic Splitting Basic via annotations Native weighted routing
Header/Query Matching Limited via annotations Native rich matching capabilities
Request/Response Modifications Basic via annotations Native filters (headers, redirects, rewrites)
Backend Selection Only Services Services, ExternalNames, Direct Pod IPs
Extensibility Limited to annotations Rich extension points and custom resources
Portability Low (vendor-specific annotations) High (standard specification)

Architecture Comparison:

# Ingress: Monolithic Approach
┌─────────────────────────────────┐
│           Ingress               │
│  (Contains all configuration)   │
├─────────────────────────────────┤
│ • Host/path routing             │
│ • TLS termination               │
│ • Load balancing                │
│ • All vendor annotations        │
└─────────────────────────────────┘

# Gateway API: Layered Approach
┌─────────────────────────────────┐
│         GatewayClass            │
│  (Infrastructure capabilities)  │
├─────────────────────────────────┤
│           Gateway               │
│    (Listener configuration)     │
├─────────────────────────────────┤
│         HTTPRoute               │
│   (Application routing rules)   │
└─────────────────────────────────┘
                

When to Use Each

Use Ingress When:

  • Simple HTTP routing: Basic host/path-based routing
  • Legacy applications: Applications using older Kubernetes versions
  • Limited requirements: No need for advanced traffic management
  • Quick setup: Need something working immediately
  • Single team/role: Same team manages infrastructure and applications

Use Gateway API When:

  • Multi-protocol needs: Need TCP, UDP, or gRPC support
  • Role separation: Different teams manage infrastructure vs applications
  • Multi-tenant environments: Need namespace isolation with cross-namespace routing
  • Advanced traffic management: Need canary deployments, traffic splitting
  • Future-proofing: Building new applications on modern standards
  • Portability: Want to avoid vendor lock-in

Specific Scenarios:

# Scenario 1: Canary Deployment
# Ingress (using nginx annotations)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        backend:
          service:
            name: canary-service
            port:
              number: 80

# Gateway API (native support)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: canary-route
spec:
  parentRefs:
  - name: my-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: main-service
      port: 80
      weight: 90
    - name: canary-service
      port: 80
      weight: 10

# Scenario 2: Cross-Namespace Routing
# Ingress: NOT POSSIBLE
# Services must be in same namespace as Ingress

# Gateway API: Supported with ReferenceGrant
# 1. Create ReferenceGrant in backend namespace
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-cross-namespace
  namespace: backend-ns
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: frontend-ns
  to:
  - group: ""
    kind: Service

# 2. Create HTTPRoute referencing cross-namespace service
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: cross-ns-route
  namespace: frontend-ns
spec:
  parentRefs:
  - name: my-gateway
  rules:
  - backendRefs:
    - name: backend-service
      namespace: backend-ns
      port: 8080
                

Migration Guide: Ingress to Gateway API

Migration Strategy:

  1. Assessment: Evaluate current Ingress usage and requirements
  2. Pilot Project: Start with a non-critical application
  3. Parallel Run: Run both Ingress and Gateway API side-by-side
  4. Gradual Migration: Move applications incrementally
  5. Validation: Test thoroughly before full migration
  6. Cleanup: Remove old Ingress resources

Migration Example:

# Step 1: Current Ingress Configuration
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

# Step 2: Equivalent Gateway API Configuration
# Gateway (infrastructure team)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: app-gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    hostname: "app.example.com"
    tls:
      mode: Terminate
      certificateRefs:
      - name: app-tls
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
          matchLabels:
            gateway-access: "true"

# HTTPRoute (application team)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: app-namespace
  labels:
    gateway-access: "true"
spec:
  parentRefs:
  - name: app-gateway
    namespace: infrastructure-ns
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefix
          replacePrefixMatch: /api
    backendRefs:
    - name: api-service
      port: 8080
  - matches:
    - path:
        type: PathPrefix
        value: /web
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefix
          replacePrefixMatch: /web
    backendRefs:
    - name: web-service
      port: 80
                

Migration Tools:

# Using kwctl for Gateway API validation
# Install kwctl
curl -L https://github.com/kubewarden/kwctl/releases/download/v1.8.0/kwctl-linux-x86_64 -o kwctl
chmod +x kwctl

# Validate Gateway API resources
kwctl annotate -m gatekeeper-policy.yaml gateway.yaml
kwctl annotate -m gatekeeper-policy.yaml httproute.yaml

# Using kustomize for migration
# Create kustomize patch to transform Ingress to Gateway API
apiVersion: builtin
kind: PatchTransformer
metadata:
  name: ingress-to-gateway
patch: |-
  - op: replace
    path: /apiVersion
    value: gateway.networking.k8s.io/v1beta1
  - op: replace
    path: /kind
    value: HTTPRoute
  # Add additional transformations...

# Migration script example
#!/bin/bash
# migrate-ingress.sh
INGRESS_FILE=$1
NAMESPACE=$(yq eval '.metadata.namespace' $INGRESS_FILE)
GATEWAY_NAME="migrated-gateway"

echo "Migrating Ingress in namespace: $NAMESPACE"

# Extract host rules
HOSTS=$(yq eval '.spec.rules[].host' $INGRESS_FILE)

# Generate Gateway
cat > gateway.yaml <
            

Implementation Examples

Istio with Gateway API:

# Install Istio with Gateway API support
istioctl install --set profile=demo -y

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

# Create HTTPRoute with Istio features
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: bookinfo-route
spec:
  parentRefs:
  - name: istio-gateway
    namespace: istio-system
  hostnames:
  - "bookinfo.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /productpage
    - path:
        type: PathPrefix
        value: /static
    - path:
        type: PathExact
        value: /login
    - path:
        type: PathExact
        value: /logout
    - path:
        type: PathPrefix
        value: /api/v1/products
    backendRefs:
    - name: productpage
      port: 9080
  - matches:
    - headers:
      - name: end-user
        value: "jason"
    - queryParams:
      - name: test
        value: "true"
    backendRefs:
    - name: reviews
      port: 9080
      weight: 90
    - name: reviews-v2
      port: 9080
      weight: 10
                

NGINX Ingress Controller with Gateway API:

# Install NGINX Ingress Controller with Gateway API
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --set controller.ingressClassResource.name=nginx \
  --set controller.ingressClassResource.controllerValue="k8s.io/ingress-nginx" \
  --set controller.watchIngressWithoutClass=true \
  --set controller.enableGatewayAPI=true

# Create GatewayClass
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: nginx
spec:
  controllerName: nginx.org/gateway-controller

# Create Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: nginx-gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: Same

# Advanced routing with filters
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: advanced-route
spec:
  parentRefs:
  - name: nginx-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /shop
    filters:
    - type: RequestHeaderModifier
      requestHeaderModifier:
        add:
        - name: X-Shop-Version
          value: "v2"
        set:
        - name: X-User-ID
          value: "12345"
        remove:
        - "X-Old-Header"
    - type: ResponseHeaderModifier
      responseHeaderModifier:
        add:
        - name: X-Cache-Hit
          value: "true"
    - type: RequestRedirect
      requestRedirect:
        scheme: https
        port: 8443
        statusCode: 301
    backendRefs:
    - name: shop-service
      port: 8080
                

TCP/UDP Routing Example:

# TCPRoute for database access
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: postgres-route
spec:
  parentRefs:
  - name: tcp-gateway
  rules:
  - backendRefs:
    - name: postgres-primary
      port: 5432
    - name: postgres-replica
      port: 5432

# UDPRoute for DNS service
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: UDPRoute
metadata:
  name: dns-route
spec:
  parentRefs:
  - name: udp-gateway
  rules:
  - backendRefs:
    - name: coredns
      port: 53

# TLSRoute for passthrough TLS
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: tls-passthrough-route
spec:
  parentRefs:
  - name: tls-gateway
  hostnames:
  - "secure-api.example.com"
  rules:
  - backendRefs:
    - name: secure-api-service
      port: 8443
                

Best Practices

Gateway API Best Practices:

  • Use Role Separation:
    • Infrastructure team manages Gateway/GatewayClass
    • Application teams manage HTTPRoutes
  • Namespace Strategy:
    • Place Gateway in infrastructure namespace
    • Use namespace selectors for access control
    • Use ReferenceGrant for cross-namespace access
  • Security:
    • Use TLS termination at Gateway when possible
    • Implement network policies for Gateway
    • Regularly rotate TLS certificates
  • Monitoring:
    • Monitor Gateway and Route status conditions
    • Set up alerts for configuration errors
    • Track traffic metrics per route

Performance Optimization:

# Optimize Gateway configuration
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: optimized-gateway
  annotations:
    # Implementation-specific optimizations
    nginx.ingress.kubernetes.io/proxy-buffering: "on"
    nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    # Connection limits
    connectionLimits:
      count: 10000
      delay: 100ms
    # Rate limiting
    rateLimits:
      standard:
        requests: 100
        unit: second
        burst: 50

# Optimize HTTPRoute with caching
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: cached-route
  annotations:
    nginx.ingress.kubernetes.io/proxy-cache-path: "/tmp/nginx/cache"
    nginx.ingress.kubernetes.io/proxy-cache-valid: "200 302 10m"
spec:
  parentRefs:
  - name: optimized-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /static
    filters:
    - type: ResponseHeaderModifier
      responseHeaderModifier:
        add:
        - name: Cache-Control
          value: "public, max-age=31536000"
    backendRefs:
    - name: static-service
      port: 80
                

Future Outlook

Gateway API Roadmap:

  • GAMMA Initiative: Gateway API for Mesh Management and Administration
  • Service Mesh Integration: Better integration with service meshes
  • Enhanced Observability: Standardized metrics and tracing
  • Policy Framework: Built-in policy enforcement
  • Wider Adoption: More implementations and ecosystem tools

Migration Timeline:

Recommended Migration Timeline:

Phase 1: Evaluation (Now)
├── Understand Gateway API concepts
├── Evaluate current Ingress limitations
├── Identify pilot project
└── Test with development clusters

Phase 2: Pilot (Q1-Q2 2024)
├── Implement Gateway API for pilot project
├── Train teams on new concepts
├── Develop migration patterns
└── Create monitoring and alerting

Phase 3: Gradual Migration (Q3-Q4 2024)
├── Migrate non-critical applications
├── Refine processes and tooling
├── Update CI/CD pipelines
└── Document lessons learned

Phase 4: Full Adoption (2025)
├── Migrate remaining applications
├── Deprecate Ingress usage
├── Optimize Gateway API configurations
└── Contribute to ecosystem
                

Key Recommendations:

  • Start Learning Now: Gateway API is the future of Kubernetes networking
  • Begin with Non-Critical Workloads: Gain experience safely
  • Leverage Both Temporarily: Run Ingress and Gateway API in parallel
  • Contribute to the Ecosystem: Help shape the future of the standard
  • Stay Updated: Follow SIG-Network developments and releases

Quick Reference Cheat Sheet

Ingress Commands:

# Basic Ingress operations
kubectl get ingress
kubectl describe ingress 
kubectl apply -f ingress.yaml
kubectl delete ingress 

# Check Ingress controller
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx 
        

Gateway API Commands:

# Gateway API operations
kubectl get gatewayclasses
kubectl get gateways
kubectl get httproutes
kubectl get tcproutes
kubectl get udproutes
kubectl get tlsroutes

# Describe resources
kubectl describe gateway 
kubectl describe httproute 

# Check status conditions
kubectl get gateway  -o jsonpath='{.status.conditions}'
kubectl get httproute  -o jsonpath='{.status.parents[*].conditions}'
        

Conversion Table:

Ingress Concept Gateway API Equivalent
Ingress Gateway + HTTPRoute
IngressClass GatewayClass
spec.rules[].host spec.hostnames[]
spec.rules[].http.paths[] spec.rules[].matches[]
spec.tls[] Gateway listeners with TLS config
annotations spec.filters[] or implementation-specific

Additional Resources

© 2025 Kubernetes Networking Comparison Guide. All rights reserved.

Comments

Popular posts from this blog

Real-world Terraform scenarios to test and improve your Infrastructure as Code skills

Azure Kubernetes Service (AKS) Complete Guide

Automate Your DevOps Documentation: `iac-to-docs` Lands on PyPI with AI Power