Ingress & Ingress Controllers
A website usually needs one public entry point that sends / to the frontend, /api to the API and admin.example.com to the admin panel, with HTTPS on top. Giving each Service its own cloud load balancer would be costly and clumsy. Ingress was Kubernetes' first answer: one object that describes HTTP routing rules, carried out by a program called an Ingress controller.
Ingress is still everywhere in existing clusters, so you need to read and write it. But it is now frozen, and the most popular controller has been retired. In this lesson you will learn Ingress properly, and learn the current state of things so you can make good choices.
Ingress and Ingress controllers
There are two parts, and beginners often expect the first to work without the second:
- An Ingress object is just a set of rules: "requests for
shop.example.com/apigo to the Serviceapion port 80". - An Ingress controller is a reverse proxy running in the cluster (usually behind a LoadBalancer Service) that reads Ingress objects and does the actual routing.
A cluster has no Ingress controller by default. Without one, Ingress objects do nothing at all. Each installed controller registers an IngressClass, and an Ingress picks one with ingressClassName:
kubectl get ingressclassAn Ingress with two paths and TLS
Priya's shop has two Services, web and api, both ClusterIP on port 80:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
spec:
ingressClassName: traefik # the class your controller registered
tls:
- hosts:
- shop.example.com
secretName: shop-tls # a Secret of type kubernetes.io/tls
rules:
- host: shop.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80rulesmatch the request's host name, then its path. A rule withouthostmatches every host.pathTypedecides how paths are compared:
| pathType | Matches |
|---|---|
Prefix | The path and anything below it, split on /: /api matches /api and /api/books, but not /apis |
Exact | Only that exact path |
ImplementationSpecific | Whatever the controller decides; avoid it for portable manifests |
- When several paths match, the longest one wins, so
/apibeats/. tlsnames a Secret holding the certificate and key. Many teams let cert-manager create and renew these certificates automatically.
kubectl apply -f shop-ingress.yaml
kubectl get ingress shopingress.networking.k8s.io/shop created NAME CLASS HOSTS ADDRESS PORTS AGE shop traefik shop.example.com 80, 443 10s
PORTS shows 80, 443 because the Ingress has a tls section. ADDRESS stays empty until the controller has processed the Ingress and reported the address of its load balancer. To test without changing DNS, send the host name in a header to the controller's address, for example after a port-forward to the controller's Service: curl -H "Host: shop.example.com" http://localhost:8080/api/books.
The annotation problem
The Ingress object only covers host and path routing plus TLS. Everything else, such as redirects, rewrites, timeouts, body size limits, rate limits or sending 10% of traffic to a new version, is configured with controller-specific annotations:
metadata:
annotations:
example-controller.io/rewrite-target: /
example-controller.io/proxy-body-size: 10mEach controller invented its own names and meanings, so an Ingress written for one controller rarely works unchanged on another. This lack of portability, plus the fact that one object mixes the cluster operator's concerns (TLS, the load balancer) with the app team's routes, is why the Kubernetes project designed the Gateway API.
The status of Ingress today
Be precise about names here. Ingress NGINX (the community project above) is different from the NGINX Ingress Controller made by F5/NGINX, which is a separate product and is not part of this retirement.
The Ingress API itself is a different matter. It is generally available, the Kubernetes project has said it has no plans to remove it, and many controllers still support it. But the API is frozen: it will get no new features, and the project recommends Gateway API for new work.
Controllers that implement Ingress include Traefik, HAProxy Ingress, Kong, Contour, Cilium, Istio and cloud-specific ones such as the AWS and GKE controllers. Most of them implement the Gateway API too, which makes them a natural migration path.
Migrating to Gateway API
You do not have to rewrite everything by hand. The Kubernetes SIG Network project ingress2gateway reads your existing Ingress objects (including some controller-specific annotations) and prints equivalent Gateway API objects, with warnings for anything it could not translate:
ingress2gateway print --providers=ingress-nginx -A > gateway-routes.yamlReview its output, test it next to the old setup, then switch DNS. The next lesson explains the objects it produces.
Common mistakes
- Creating an Ingress in a cluster with no controller. Nothing happens and
ADDRESSstays empty. Install a controller first. - Missing or wrong
ingressClassName. No controller picks the Ingress up, unless one IngressClass is marked as the default. - Copying annotations between controllers. Each controller has its own annotation names.
- Installing the retired Ingress NGINX in a new cluster because an old tutorial said so. Choose a maintained controller or, better, a Gateway API implementation.
Key points
- An Ingress describes HTTP routing by host and path to Services; an Ingress controller performs it.
ingressClassNameselects the controller;pathTypePrefixandExactare portable, and the longest matching path wins.- TLS uses a Secret of type
kubernetes.io/tls; features beyond routing need controller-specific annotations. - The community Ingress NGINX controller was retired in March 2026; the Ingress API remains supported but frozen.
- Gateway API is the recommended successor, and ingress2gateway helps convert existing Ingress objects.
Exercise
Kabir runs a school portal with three ClusterIP Services on port 80: portal-web, portal-api and portal-admin. Write an Ingress (class traefik) so that portal.example.com/ goes to portal-web, portal.example.com/api and everything below it goes to portal-api, and admin.portal.example.com goes to portal-admin. No TLS is needed.
Show solution
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal
spec:
ingressClassName: traefik
rules:
- host: portal.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: portal-api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: portal-web
port:
number: 80
- host: admin.portal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal-admin
port:
number: 80Each host gets its own rule. Within portal.example.com, /api is longer than /, so API requests go to portal-api and everything else goes to portal-web.
Quick Quiz
1. You create an Ingress in a fresh cluster and nothing happens. Why?
An Ingress is only a set of rules; a controller must implement them.
2. Which request does a Prefix path of /api match?
Prefix matching works on whole path segments separated by /.
3. What happened to the community Ingress NGINX controller?
Existing installs still run, but new clusters should not use it.
4. What is the status of the Ingress API itself?
Kubernetes has no plans to remove Ingress, but it gets no new features.
Learn Kubernetes with a mentor
Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
