๐Ÿ“– Read-only preview โ€” lessons, diagrams, and quizzes only. The hands-on labs, live grading, and progress tracking require running the real course locally against a Kubernetes cluster.Run it locally โ†’

Module 8 ยท Lesson 8.1

Ingress

One entry point, many backends

So far, reaching an app meant a Service โ€” one ClusterIP per app, or in cloud reality, one LoadBalancer (and one real cloud load balancer, one real bill) per app. That doesn't scale past a handful of services: you don't want ten public IPs for ten apps on one domain.

Ingress solves this: one object describing host- and path-based HTTP(S) routing rules ("api.example.com โ†’ api-svc:8080", "/blog โ†’ blog-svc:80"), sitting in front of many backend Services, needing exactly one real entry point (one LoadBalancer or NodePort) for all of them.

One Ingress, many backends

client

โ†’

Traefik

Ingress controller

โ†’
/api โ†’ api-svc:8080
/blog โ†’ blog-svc:80
Matched rule "/api" โ†’ routed to api-svc:8080.

The resource/controller split โ€” again

Here's the same pattern you met with Services in Module 4: an Ingress object is just a declaration. Nothing routes anything until an Ingress controller โ€” a separate piece of software watching Ingress objects and programming an actual proxy โ€” is running in your cluster. Create an Ingress with zero controllers installed, and kubectl get ingress will happily show it with no address, doing nothing. This cluster runs Traefik as its controller.

Why Traefik, not ingress-nginx? For years, ingress-nginx was the default answer. In March 2026, Kubernetes SIG Network officially retired it โ€” best-effort maintenance only, no further releases or CVE patches, the repo archived read-only days later. It had been maintained by one or two volunteers, and a serious CVE earlier that year (dubbed "IngressNightmare") made the unsustainable maintenance load impossible to ignore. SIG Network's own guidance: migrate to Gateway API, or to another actively maintained controller (Traefik, HAProxy, Kong, NGINX Gateway Fabric). This is worth remembering for your own production decisions โ€” "the thing everyone uses" and "the thing that's maintained" aren't always the same thing, and that gap can open up fast.

What Ingress actually configures

An Ingress object names an ingressClassName (which controller should handle it โ€” traefik here), then a list of rules: a host, and under it, paths mapped to a backend Service + port. Nothing here is Traefik-specific โ€” that's the appeal of the base Ingress API. The catch, and it's a real one: almost everything beyond basic host/path routing (rewrites, auth, rate limiting, TLS details) is exposed through controller-specific annotations, not the portable spec. Switch controllers, and those annotations silently stop working. That portability gap is exactly what Gateway API, next lesson, was built to close.

In the lab, you'll route two paths to two backend Services through one Ingress, verified the way you'll verify most things on a cluster with no real external load balancer: from inside the cluster, not from a browser.

๐Ÿงช Lab: lab-16-ingress

Preview only

Goal

Route two paths on one host to two different backend Services through a single Ingress โ€” and fix a wrong-backend bug along the way.

Tasks

  1. Apply the starting manifests: kubectl apply -f manifests/
  2. Confirm everything is up: kubectl get pods,svc,ingress -n lab-16-ingress
  3. From inside the cluster, test the /blog path (this one's already correct) โ€” exec into the client pod and curl Traefik's in-cluster Service with the right Host header:
    kubectl exec -n lab-16-ingress client -- wget -q -O- \
      --header="Host: shop.example.com" \
      http://traefik.traefik-system.svc.cluster.local/blog
    
    You should see hello from blog-backend.
  4. Now test /api the same way (swap the path at the end to /api). You should see hello from blog-backend again โ€” that's the bug. /api is supposed to reach api-backend.
  5. Open manifests/ingress.yaml, find the comment marking the bug, and point the /api rule at the correct Service and port.
  6. Re-apply: kubectl apply -f manifests/ingress.yaml
  7. Re-test /api โ€” you should now see hello from api-backend.

Check

Run the check once both paths return their correct backend's text.

This lab runs against a real local Kubernetes cluster with an automated grader โ€” clone the repo and run make start to do it for real.

๐Ÿ“ Quiz

1. What's the main problem Ingress solves compared to giving every app its own LoadBalancer Service?

2. You create an Ingress object in a cluster with no Ingress controller installed. What happens?scenario

3. Why did Kubernetes SIG Network retire ingress-nginx in March 2026?

4. You configure a rate-limiting annotation specific to one Ingress controller, then switch your cluster to a different controller. What happens to that rate limit?scenario

5. On a local kind cluster with no real cloud load balancer, how do you realistically verify an Ingress is routing correctly?

Progress isn't saved in this preview โ€” run the course locally to track completion and grade labs for real.