Kubernetes Security & Hardening›07 · Ingress controllers & TLS

Lesson 07 of 15 · Traffic Security

Ingress controllers & TLS

Expose HTTP services securely with Ingress: controllers and IngressClasses, TLS termination with cert-manager certificates, passthrough and re-encryption, secure defaults, and choosing a maintained controller.

Advanced
Key wordsIngressIngressClassTLS terminationpassthroughre-encryptionHSTScontroller choice

Ingress in one picture

An Ingress is a set of HTTP routing rules (host + path → Service). An ingress controller (a reverse proxy running in the cluster) reads them and does the actual work: accepting traffic, terminating TLS, and forwarding to pods.

client ──HTTPS──► load balancer ──► ingress controller (TLS, routing) ──► Service ──► pods

The Ingress controller is the receptionist of a large office building with one front door. Visitors say who they're visiting ("shop.example.com, the orders department"), the receptionist checks the building's security badge (the TLS certificate) and walks them to the right office (the Service). The Ingress rules are the receptionist's directory.

Choosing a controller

Many controllers implement Ingress: Traefik, HAProxy, NGINX-based controllers from vendors, Contour, cloud load-balancer controllers, and service meshes. The Ingress API itself is stable but frozen: new features go into the Gateway API (next lesson).

Check your controller is maintained

The community ingress-nginx controller, long the most common choice, was retired after an announcement in late 2025. If you run it, plan a migration to a maintained controller or a Gateway API implementation. For new platforms, prefer Gateway API where your controller supports it.

A secure Ingress with cert-manager

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
  namespace: shop
  annotations:
    cert-manager.io/cluster-issuer: platform-ca        # or letsencrypt-prod (lesson 02)
spec:
  ingressClassName: traefik
  tls:
    - hosts: [ "shop.example.com" ]
      secretName: shop-example-com-tls                  # cert-manager creates and renews it
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

Most controllers redirect HTTP → HTTPS when TLS is configured, or offer a setting or middleware for it. Also enable HSTS (Strict-Transport-Security) for public sites, via your controller's middleware or annotations.

Termination, passthrough, re-encryption

Mode TLS ends at Routing by Use when
Termination Ingress controller Host + path Most web apps
Re-encryption Controller, then TLS again to the backend Host + path Traffic inside the cluster must stay encrypted
Passthrough The backend pod Host only (SNI) The backend must hold the key (e.g. strict compliance)

Passthrough and backend-TLS settings are controller-specific (annotations, or CRDs such as Traefik's IngressRouteTCP). Gateway API standardises these (TLSRoute, backend TLS policy).

Secure defaults to check

  • TLS 1.2+ only, modern cipher suites (controller defaults are usually good; verify with a TLS scanner).
  • Certificates from cert-manager, monitored for expiry.
  • Request size and timeout limits to reduce abuse.
  • Only the controller is exposed publicly; backends are ClusterIP Services.
  • The controller's own admin dashboard or metrics endpoint is not exposed publicly.

Try it: HTTPS on kind with Traefik

  1. Install Traefik: helm repo add traefik https://traefik.github.io/charts && helm install traefik traefik/traefik -n traefik --create-namespace.
  2. Deploy the web app and Service from Kubernetes Administration (lessons 03–04) in namespace shop.
  3. With cert-manager and the platform-ca issuer from lesson 02, apply the Ingress above (host shop.example.com).
  4. Port-forward the controller: kubectl -n traefik port-forward svc/traefik 8443:443, then test: curl -vk --resolve shop.example.com:8443:127.0.0.1 https://shop.example.com:8443/. Which certificate subject do you see?
  5. Delete the TLS Secret and watch cert-manager recreate it; confirm the served certificate's dates changed.

Going deeper: ingress in production

  • Run the controller with multiple replicas, a PodDisruptionBudget, and anti-affinity across nodes and zones. It's in the path of every request.
  • Put a WAF or cloud edge (DDoS protection, bot filtering) in front of public ingress where risk justifies it.
  • Rate limiting and authentication (OIDC via an auth proxy) can be added at the ingress layer for internal tools.
  • Keep a clear ownership split: the platform team runs controllers and certificates; app teams own their Ingress or Route objects. Gateway API makes this split explicit.

Recap

  • Ingress = routing rules; the controller does the work; IngressClass decides which controller.
  • TLS: termination (common), re-encryption, or passthrough; certificates from cert-manager.
  • Test with --resolve and openssl s_client -servername to see what each host serves.
  • Pick a maintained controller; prefer Gateway API for new designs.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.