TechLead
Lesson 13 of 25
5 min read
Cloud & Kubernetes

Ingress Controllers

Configure Kubernetes Ingress resources and controllers for HTTP routing, TLS termination, path-based routing, and load balancing

What is Ingress?

An Ingress is a Kubernetes resource that manages external access to services in a cluster, typically HTTP/HTTPS traffic. It provides load balancing, SSL/TLS termination, and name-based virtual hosting. Unlike LoadBalancer Services (which provision one LB per service), Ingress consolidates routing rules into a single resource backed by a single load balancer.

Ingress vs LoadBalancer Service

  • LoadBalancer Service: One cloud load balancer per service (~$20/month each). Simple but expensive at scale.
  • Ingress: One load balancer for many services. Routes based on hostname and path. Supports TLS termination, rewrites, rate limiting.

Ingress Controllers

An Ingress resource on its own does nothing — you need an Ingress Controller to fulfill the Ingress rules. The controller runs as Pods in your cluster and watches for Ingress resources, then configures the underlying proxy (NGINX, Envoy, Traefik, etc.) accordingly.

Installing NGINX Ingress Controller

# Install with Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.replicaCount=2 \
  --set controller.resources.requests.cpu=100m \
  --set controller.resources.requests.memory=128Mi

# Verify installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

# Get the external IP/hostname
kubectl get svc ingress-nginx-controller -n ingress-nginx

Basic Ingress Resource

# basic-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-frontend
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-server
            port:
              number: 8080
      - path: /docs
        pathType: Prefix
        backend:
          service:
            name: docs-service
            port:
              number: 3000

TLS Termination

# tls-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    - api.example.com
    secretName: app-tls-cert    # cert-manager auto-creates this
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-frontend
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-server
            port:
              number: 8080

cert-manager for Automatic TLS

# Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true
# cluster-issuer.yaml
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-key
    solvers:
    - http01:
        ingress:
          class: nginx

Advanced Ingress Annotations

# advanced-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  annotations:
    # Rate limiting
    nginx.ingress.kubernetes.io/limit-rps: "50"
    nginx.ingress.kubernetes.io/limit-connections: "10"

    # Request/response size limits
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"

    # Timeouts
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "120"

    # CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"

    # Websocket support
    nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";

    # Canary deployment (route 10% of traffic to canary)
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-frontend-canary
            port:
              number: 80

Key Takeaways

  • Ingress consolidates HTTP routing rules behind a single load balancer
  • You need an Ingress Controller (NGINX, Traefik, Envoy) to implement Ingress rules
  • cert-manager automates TLS certificate provisioning from Let's Encrypt
  • Annotations provide powerful configuration: rate limiting, CORS, canary deployments
  • Use path-based and host-based routing to serve multiple services from one entry point

Continue Learning