17 - Ingress & Load Balancing

Why Ingress?

LoadBalancer Services give each service its own external IP/load balancer. With many services, this gets expensive and hard to manage. Ingress provides:

  • Single entry point for multiple services
  • Host-based and path-based routing
  • TLS termination
  • Centralized load balancing
Without Ingress:                    With Ingress:
                                    
LB ($) → svc-api                   Single LB ($)
LB ($) → svc-web                        │
LB ($) → svc-admin                      ▼
LB ($) → svc-docs                  Ingress Controller
                                     ├─ api.example.com → svc-api
3-4 load balancers = $$$             ├─ example.com → svc-web
                                     ├─ admin.example.com → svc-admin
                                     └─ docs.example.com → svc-docs
                                    
                                    1 load balancer = $

Ingress Components

  1. Ingress Resource: YAML defining routing rules
  2. Ingress Controller: The actual reverse proxy (nginx, traefik, etc.)
  3. IngressClass: Links Ingress resources to a specific controller

Ingress Controller

An Ingress resource does nothing without a controller. You must install one:

ControllerDescriptionBest For
NGINX IngressMost popular, battle-testedGeneral purpose
TraefikAuto-discovery, Let's EncryptSimple setups
HAProxyHigh performanceHeavy traffic
AWS ALB ControllerNative AWS ALBEKS
GCE IngressNative GCP LBGKE
Istio GatewayService mesh gatewayIstio users
ContourEnvoy-basedAdvanced routing
bash
# Install NGINX Ingress Controller kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.5/deploy/static/provider/cloud/deploy.yaml # Or with Helm helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx --create-namespace

Basic Ingress Resource

Host-Based Routing

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-host annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 80 - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 - host: admin.example.com http: paths: - path: / pathType: Prefix backend: service: name: admin-service port: number: 80

Path-Based Routing

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: path-routing spec: ingressClassName: nginx rules: - host: example.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 80 - path: /admin pathType: Prefix backend: service: name: admin-service port: number: 80 - path: / pathType: Prefix backend: service: name: web-service port: number: 80

Path Types

TypeBehaviorExample
PrefixMatches URL path prefix/api matches /api, /api/users
ExactExact URL path match/api matches only /api
ImplementationSpecificController decidesDepends on controller

TLS/HTTPS

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" spec: ingressClassName: nginx tls: - hosts: - example.com - api.example.com secretName: tls-secret # Must contain tls.crt and tls.key rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80
bash
# Create TLS secret kubectl create secret tls tls-secret \ --cert=server.crt \ --key=server.key

Automatic TLS with cert-manager

bash
# Install cert-manager kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
yaml
# ClusterIssuer for Let's Encrypt apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx --- # Ingress with auto-TLS apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: auto-tls annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: ingressClassName: nginx tls: - hosts: - example.com secretName: example-com-tls # cert-manager creates this rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80

Common Annotations (NGINX)

yaml
metadata: annotations: # Rewrite URL path nginx.ingress.kubernetes.io/rewrite-target: /$2 # Rate limiting nginx.ingress.kubernetes.io/limit-rps: "10" # Request body size nginx.ingress.kubernetes.io/proxy-body-size: "50m" # Timeouts nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" # CORS nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com" # Authentication nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth # WebSocket support nginx.ingress.kubernetes.io/proxy-http-version: "1.1" nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr" # Redirect HTTP → HTTPS nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

Gateway API (The Future of Ingress)

Gateway API is the successor to Ingress with more features:

yaml
# Gateway (replaces Ingress Controller config) apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: main-gateway spec: gatewayClassName: nginx # or istio, envoy, etc. listeners: - name: http port: 80 protocol: HTTP - name: https port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: tls-secret --- # HTTPRoute (replaces Ingress rules) apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route spec: parentRefs: - name: main-gateway hostnames: - "api.example.com" rules: - matches: - path: type: PathPrefix value: /v1 backendRefs: - name: api-v1 port: 80 weight: 90 - name: api-v2 port: 80 weight: 10 # Canary: 10% to v2

Gateway API advantages over Ingress:

  • Native traffic splitting (canary/blue-green)
  • Header-based routing
  • TCP/UDP routing (not just HTTP)
  • Role-based resource model
  • Cross-namespace references

Default Backend

Handle requests that don't match any rule:

yaml
spec: defaultBackend: service: name: default-backend port: number: 80

kubectl Commands

bash
# List ingresses kubectl get ingress kubectl get ing # Describe kubectl describe ingress my-ingress # Get ingress controller IP kubectl get svc -n ingress-nginx # Check ingress class kubectl get ingressclass # Test curl -H "Host: api.example.com" http://<ingress-ip>/

FAANG Interview Angle

Common questions:

  1. "How do you expose HTTP services in Kubernetes?"
  2. "What's the difference between Ingress and LoadBalancer Service?"
  3. "How do you handle TLS in Kubernetes?"
  4. "What is an Ingress Controller?"
  5. "How would you do path-based routing in K8s?"

Key answers:

  • Ingress for HTTP(S) routing with host/path rules; LoadBalancer for L4 (TCP/UDP)
  • LoadBalancer = one LB per service ($$$). Ingress = one LB for many services via routing rules
  • TLS Secret + Ingress TLS config, or cert-manager for automatic Let's Encrypt
  • Ingress Controller is the reverse proxy (nginx, traefik) that implements Ingress rules
  • Ingress with path-based rules or Gateway API HTTPRoute for advanced routing

Official Links