Kubernetes Ingress: NGINX vs Traefik vs Istio vs ALB
Every request to your Kubernetes cluster enters through an ingress controller. It is the front door — handling TLS termination, routing, rate limiting, and load balancing. Choosing and configuring the right one is critical.
What an Ingress Controller Does#
Without ingress, you expose services via NodePort or LoadBalancer — one load balancer per service, no shared routing logic. Ingress consolidates external access:
Internet → Ingress Controller (single LB)
├── /api/* → api-service:8080
├── /app/* → frontend:3000
└── /docs/* → docs-service:4000
The controller watches Ingress resources (or Gateway resources in the Gateway API) and configures its underlying proxy accordingly.
NGINX Ingress Controller#
The most widely deployed ingress controller. Battle-tested and feature-rich.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 3000
Strengths: Mature, extensive annotations, large community, well-documented. Weaknesses: Config via annotations can become unwieldy, reload-based config updates.
Traefik#
Auto-discovery and dynamic configuration make Traefik popular for fast-moving teams.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: app-ingress
spec:
entryPoints:
- websecure
routes:
- match: "Host(`app.example.com`) && PathPrefix(`/api`)"
kind: Rule
services:
- name: api-service
port: 8080
middlewares:
- name: rate-limit
- name: strip-prefix
- match: "Host(`app.example.com`)"
kind: Rule
services:
- name: frontend
port: 3000
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 100
burst: 50
period: 1m
Strengths: Auto Let's Encrypt, dashboard, middleware chains, fast reloads. Weaknesses: CRD-heavy config, smaller community than NGINX.
Istio Gateway (Service Mesh Ingress)#
If you already run Istio, its gateway replaces a standalone ingress controller.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: app-gateway
spec:
gatewayClassName: istio
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: app-tls-secret
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-routes
spec:
parentRefs:
- name: app-gateway
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend
port: 3000
Strengths: mTLS everywhere, traffic shifting, deep observability, Gateway API support. Weaknesses: Heavy resource footprint, complex operations, overkill without a service mesh.
AWS ALB Ingress Controller#
Native integration with AWS Application Load Balancers.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456:certificate/abc-123"
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/group.name: "shared-alb"
spec:
ingressClassName: alb
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 3000
Strengths: Native AWS integration, WAF support, shared ALB across ingresses, no proxy pod to manage. Weaknesses: AWS-only, slower propagation (ALB changes take 30-60s), limited transformation.
Controller Comparison#
| Feature | NGINX | Traefik | Istio Gateway | AWS ALB |
|---|---|---|---|---|
| TLS termination | Yes | Yes + auto LE | Yes + mTLS | Yes (ACM) |
| Rate limiting | Annotations | Middleware | EnvoyFilter | WAF rules |
| Path routing | Yes | Yes | Yes | Yes |
| WebSocket | Yes | Yes | Yes | Yes |
| gRPC | Yes | Yes | Native | Yes |
| Config model | Annotations | CRDs | Gateway API | Annotations |
| Resource usage | Low-medium | Low | High | None (managed) |
TLS Termination Patterns#
Edge termination — decrypt at the ingress, plain HTTP to pods:
Client --TLS--> Ingress --HTTP--> Pod
Simplest model. Fine when the cluster network is trusted.
Re-encrypt — decrypt at ingress, re-encrypt to pods:
Client --TLS--> Ingress --TLS--> Pod
Required for compliance in some environments.
Passthrough — ingress forwards raw TLS to the pod:
Client --TLS--> Ingress --TLS--> Pod (pod terminates TLS)
Used when pods need to see the original certificate (mTLS, client certs).
Rate Limiting at Ingress#
Rate limiting at the ingress layer protects all backend services:
# NGINX - per-IP rate limiting
metadata:
annotations:
nginx.ingress.kubernetes.io/limit-rps: "50"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"
nginx.ingress.kubernetes.io/limit-whitelist: "10.0.0.0/8"
For more granular control, combine ingress-level rate limiting with application-level limits:
Ingress rate limit: 1000 req/s per IP (DDoS protection)
└── API gateway rate limit: 100 req/s per API key (business logic)
└── Service rate limit: 50 req/s per user (resource protection)
Production Checklist#
- Health checks — configure readiness and liveness probes on the controller pods
- Pod disruption budgets — ensure at least 2 replicas survive during node drains
- Resource requests/limits — size based on connection count and throughput
- Access logs — enable structured JSON access logs for debugging
- Metrics — export to Prometheus (request rate, latency, 5xx rate)
- Timeouts — set connect, read, and send timeouts per backend
- CORS — configure allowed origins at the ingress level
- Security headers — add HSTS, X-Frame-Options, CSP via annotations or middleware
Conclusion#
Your choice of ingress controller shapes your cluster's networking capabilities. NGINX works for most teams. Traefik suits dynamic environments with auto-TLS needs. Istio Gateway makes sense if you already have a service mesh. AWS ALB Controller is ideal for AWS-native teams wanting managed infrastructure. Start simple and evolve as your routing needs grow.
Article #402 — part of the Codelit engineering blog. Explore all articles at codelit.io.
Try these templates
Continue learning
Kubernetes Service Types — ClusterIP, NodePort, LoadBalancer, ExternalName, and Headless Services
7 min readkubernetesKubernetes Network Policies — Default Deny, Namespace Isolation, and Zero-Trust Networking
7 min readkubernetesKubernetes ConfigMaps & Secrets — Configuration Management Done Right
8 min readGo deeper on infrastructure and delivery
As an Amazon Associate I earn from qualifying purchases. Codelit may receive a commission at no extra cost to you.
The DevOps Handbook
Gene Kim, Jez Humble · 2021
Case studies from Etsy, Amazon, and Target on rewiring deployment pipelines and org structure.
Terraform: Up and Running
Yevgeniy Brikman · 2022
Working modules, state locking, and testing patterns for teams past the single-workspace stage.
4.6 (260)Network Programmability and Automation
Christian Adell, Scott Lowe, Matt Oswalt, Jason Edelman · 2023
Treats network config as code: APIs, source control and CI applied to routers and switches.
4.9 (24)Learning Domain-Driven Design
Vlad Khononov · 2021
Turns bounded contexts and aggregates into decision rules for where service boundaries actually go.
4.6 (400)