Ingress: Routing HTTP Into the Cluster
Article 5 left one rough edge: NodePort opens a port like 30080, 30081... for each service — ugly and hard to manage when you have many services. LoadBalancer gives each service its own public IP, which is costly. What we really want: one entry point, routing by domain and path to the right service behind it — like a reverse proxy. That's Ingress.
The problem Ingress solves
Without Ingress (one port/IP per service):
shop.com:30080 ──► Service A
shop.com:30081 ──► Service B (weird ports, hard to remember, hard to do TLS)
With Ingress (one entry point, smart routing):
┌─► / ──► Service web
shop.com:80/443 ──► │ /api ──► Service api
(Ingress) └─► blog.shop.com ──► Service blog
+ terminates TLS here
Ingress gives you: a standard HTTP/HTTPS address (80/443), routing by host (domain) and path to different services, and one central place to configure TLS. This is how you expose a web application to the outside in production.
Ingress needs an Ingress Controller
This is an easy place to trip up. An Ingress object is just routing rules — it's useless if no one enforces those rules. The enforcer is the Ingress Controller: a real reverse proxy (ingress-nginx, Traefik, HAProxy...) running in the cluster, reading the Ingress rules and configuring itself accordingly.
Ingress (rules) ──read by──► Ingress Controller (real nginx running in the cluster)
│ routes the actual traffic
▼
Service → Pod
A blank cluster does not come with an Ingress Controller — you have to install one. On minikube, just enable the addon:
minikube addons enable ingress
* Verifying ingress addon...
* The 'ingress' addon is enabled
It installs ingress-nginx into the ingress-nginx namespace. Wait for the controller to be ready:
kubectl wait --namespace ingress-nginx \
--for=condition=Ready pod -l app.kubernetes.io/component=controller --timeout=120s
pod/ingress-nginx-controller-596f8778bc-smchl condition met
Write an Ingress rule
Route every request with host web.local to the service web (Article 5):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: web.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web # points to Service "web" (Article 5)
port:
number: 80
kubectl apply -f ingress.yaml
kubectl get ingress web-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
web-ingress nginx web.local 80 5s
Notice the chain of links: Ingress → Service web → (via selector) → the Pods web. Ingress doesn't talk to pods directly; it always points through a Service. Every piece from Articles 4–6 links up into a complete path from the internet to the pod.
Test Host-based routing
Ingress chooses the service based on the Host header. Send a request with the right host to the cluster's IP:
minikube ssh "curl -s -H 'Host: web.local' http://localhost/ | grep title"
<title>Welcome to nginx!</title>
The request enters the Ingress Controller's port 80, the controller sees Host: web.local matching the rule, forwards to Service web, and the Service load-balances down to an nginx pod. The whole chain works.
Docker driver note (macOS/Windows): with the Docker driver, the minikube IP can't be called straight from the host machine, so we test from inside the node (
minikube ssh). To access from your real machine, runminikube tunnel(opens a path to the cluster), then add the line127.0.0.1 web.localto/etc/hosts, thencurl http://web.local. On Linux (default driver),curl -H 'Host: web.local' http://$(minikube ip)/works directly.
Routing multiple services and TLS
Ingress's real power shows up when you have multiple rules — routing by path or by subdomain:
rules:
- host: shop.local
http:
paths:
- path: /api # shop.local/api → service api
pathType: Prefix
backend: { service: { name: api, port: { number: 8080 } } }
- path: / # shop.local/ → service web
pathType: Prefix
backend: { service: { name: web, port: { number: 80 } } }
And TLS is declared compactly by pointing to a Secret holding the certificate (remember mounting a Secret as a file in Article 7):
spec:
tls:
- hosts: ["shop.local"]
secretName: shop-tls # a tls-type Secret holding cert + key
In production, people usually pair Ingress with cert-manager to automatically obtain and renew Let's Encrypt certificates — TLS becomes almost "automatic". This part is out of scope for the fundamentals, but worth knowing to picture the full picture.
Wrap-up
Ingress is a single HTTP/HTTPS entry point, routing by host and path to multiple Services behind it, with one central place to configure TLS — far cleaner than opening many NodePorts. The key thing to remember: the Ingress object is just rules; you must have an Ingress Controller (ingress-nginx, Traefik...) running in the cluster to enforce them — on minikube, enable it with minikube addons enable ingress. Ingress always points to pods through a Service, closing the chain internet → Ingress → Service → Pod.
The "connectivity & configuration" part is complete here. From Article 10 we move into operations: how Kubernetes knows a pod is truly healthy and ready to receive traffic — via liveness and readiness probes.