Skip to content
Menu

Networking5 min read

Ingress & Gateway API

L7 routing — exposing services to the outside world

The Ingress Resource

Ingress provides L7 (HTTP/HTTPS) routing into the cluster. Instead of one LoadBalancer per Service (expensive, wasteful), a single Ingress controller handles routing for many services based on hostname and path.

  1. Internet

    Client request

  2. Cloud LB / NodePort

    L4 entry point

  3. Ingress Controller

    L7 routing (nginx, envoy, etc.)

  4. ClusterIP Service

    Backend service

  5. Pod

    App container

Host-Based and Path-Based Routing

console
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls-cert       # K8s Secret with tls.crt + tls.key
  rules:
    # Host-based routing
    - host: app.example.com
      http:
        paths:
          # Path-based routing
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
    - host: admin.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 80

pathType Values

pathType Behavior Example
Exact URL path must match exactly /api matches only /api, not /api/v1
Prefix Matches URL path prefix split by / /api matches /api, /api/v1, /api/v1/users
ImplementationSpecific Up to the IngressClass Regex matching in nginx, etc.

Ingress Controllers

Warning

Critical: The Ingress resource does nothing without an Ingress controller. It's just a spec stored in etcd. You must deploy a controller that watches Ingress resources and configures the actual proxy.

Controller Proxy Key Strengths Notes
ingress-nginx NGINX Most popular, rich annotation set, battle-tested Community-maintained; different from NGINX Inc's controller
Traefik Traefik Auto-discovery, built-in Let's Encrypt, dashboard Popular in smaller clusters; CRD-based config too
Contour Envoy HTTPProxy CRD for advanced routing, multi-team support VMware/Tanzu project
Emissary (Ambassador) Envoy API gateway features, rate limiting, auth, gRPC CRD-based; Ingress support is secondary
AWS ALB Controller AWS ALB Native ALB integration, WAF, Cognito auth Provisions actual AWS ALBs from Ingress resources
GCE Ingress Google Cloud LB Native GCP LB, Cloud CDN, Cloud Armor Default in GKE

TLS Termination with cert-manager

cert-manager automates certificate provisioning. It watches Ingress resources for annotations and automatically provisions TLS certificates.

  1. Ingress created

    Has cert-manager annotation

  2. cert-manager sees it

    Creates Certificate CR

  3. ACME challenge

    HTTP-01 or DNS-01

  4. Cert issued

    Stored in K8s Secret

  5. Ingress uses cert

    TLS termination active

console
# ClusterIssuer — cluster-wide certificate authority
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: ops@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
      - http01:
          ingress:
            class: nginx

---
# Ingress with cert-manager annotation
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls            # cert-manager creates this Secret
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80

cert-manager Issuers

Issuer Type Source Use Case
ACME (Let's Encrypt) Let's Encrypt, ZeroSSL Public-facing services, free certs, auto-renewal
Vault HashiCorp Vault PKI Internal PKI, enterprise CA
SelfSigned Self-signed Dev/testing, bootstrapping internal CA
CA K8s Secret with CA cert/key Internal services, mTLS

Gateway API — The Ingress Successor

Why Replace Ingress?

The Ingress resource has fundamental design problems that annotations cannot fix:

Ingress Limitations

  • Too simple: Only supports host + path matching. Need header-based routing? Annotation. Need traffic splitting? Annotation. Need redirects? Annotation.
  • Annotation hell: Every advanced feature is a controller-specific annotation. nginx.ingress.kubernetes.io/... won't work on Traefik, and vice versa. Zero portability.
  • Single resource does too much: Infrastructure config (TLS, listeners) and routing rules (paths, backends) are mixed in one Ingress object. Infra team and app team both edit it.
  • No role separation: There's no way to give the app team control over their routes while restricting who manages the gateway/TLS config.
  • L4 is bolted on: TCP/UDP routing requires controller-specific CRDs. Ingress is HTTP-only.

Gateway API: Role-Oriented Design

Infrastructure Provider
GatewayClass
Which controller?
(e.g., istio, envoy, nginx)
Platform / Infra Team
Gateway
Listeners, ports, TLS
Shared across teams
Application Team
HTTPRoute
Routing rules
Host, path, headers

GatewayClass

Defines which controller implements the Gateway. Like StorageClass for volumes or IngressClass for Ingress.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: istio
spec:
  controllerName: istio.io/gateway-controller

Gateway

Declares the actual infrastructure: listeners, ports, TLS config. Managed by the platform team.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: production-gateway
  namespace: infra
spec:
  gatewayClassName: istio
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: wildcard-cert
      allowedRoutes:
        namespaces:
          from: All          # or Selector / Same
    - name: http
      protocol: HTTP
      port: 80

HTTPRoute

Defines L7 routing rules. Created by application teams, attached to a Gateway.

console
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-routes
  namespace: my-app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
  hostnames:
    - app.example.com
  rules:
    # Header-based routing (not possible with Ingress!)
    - matches:
        - headers:
            - name: x-canary
              value: true
      backendRefs:
        - name: app-v2
          port: 80

    # Traffic splitting — built-in canary!
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: app-v1
          port: 80
          weight: 90
        - name: app-v2
          port: 80
          weight: 10

    # HTTP redirect
    - matches:
        - path:
            type: PathPrefix
            value: /old-path
      filters:
        - type: RequestRedirect
          requestRedirect:
            path:
              type: ReplaceFullPath
              replaceFullPath: /new-path
            statusCode: 301

Ingress vs Gateway API

INGRESS
  • Resources: 1 (Ingress)
  • Matching: Host + path only
  • Traffic splitting: Annotation (non-portable)
  • Header routing: Annotation (non-portable)
  • Redirects/rewrites: Annotation
  • Protocols: HTTP/HTTPS only
  • Role separation: None — one resource
  • Portability: Basic fields only; annotations break
  • Status: GA, widely deployed, being superseded
GATEWAY API
  • Resources: GatewayClass, Gateway, *Route
  • Matching: Host, path, headers, query params, method
  • Traffic splitting: Built-in (weight field)
  • Header routing: Native (matches.headers)
  • Redirects/rewrites: Native (filters)
  • Protocols: HTTP, HTTPS, TCP, gRPC, TLS
  • Role separation: Infra owns Gateway, apps own Routes
  • Portability: All features are spec-level, not annotations
  • Status: GA (v1.0+), the future standard

Gateway API Route Types

Route Type Protocol Layer Use Case
HTTPRoute HTTP/HTTPS L7 Web apps, APIs, most services
GRPCRoute gRPC L7 gRPC services with method-level routing
TCPRoute TCP L4 Databases, message brokers, non-HTTP
TLSRoute TLS (SNI) L4+ TLS passthrough based on SNI hostname
UDPRoute UDP L4 DNS, gaming, VoIP

Tip

Migration path: Gateway API is the clear successor. New projects should use it. Existing Ingress resources continue to work — there's no rush to migrate. Most controllers (nginx, envoy, istio) already support both. The ingress2gateway tool can help convert Ingress YAML to Gateway API resources.

Key Takeaways

Ingress

  • L7 routing: host + path -> Service
  • Requires a controller (nginx, traefik, envoy)
  • TLS via Secrets, automated with cert-manager
  • Advanced config trapped in controller-specific annotations
  • Still works, but being superseded

Gateway API

  • Role-oriented: GatewayClass -> Gateway -> Routes
  • Native traffic splitting, header matching, redirects
  • Multi-protocol: HTTP, gRPC, TCP, TLS, UDP
  • Portable across implementations
  • GA since v1.0 — the future standard
Solidnines — solidnines.com