Full lesson
Explore the full explanation, examples, and visuals at your own pace.
Terminal: shop Ingress applied
The Ingress was created, yet the request just times out. Look at the terminal: kubectl accepted the shop Ingress with no error, but the ADDRESS column is empty, and curl can't connect. The cluster stored the rules. Nothing is actually serving them.
$ kubectl apply -f shop-ingress.yaml
ingress.networking.k8s.io/shop created
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
shop nginx shop.example.com 80 5m
$ curl http://shop.example.com
curl: (28) Failed to connect to shop.example.com port 80: Connection timed outRules are stored; the controller serves
When you run kubectl apply, the rules go to the API server, which is the cluster's database. It just stores them. A controller is a separate proxy that watches the API server, reads those rules, and routes traffic to shop-svc and its Pods. An Ingress is a rulebook. Only a controller enforces it.
shop-ingress.yaml
This is the whole Ingress, and it's pure data. Nothing here runs. ingressClassName nginx says which controller should act. The host and path say what to match: shop.example.com, anything under slash. The backend says where to forward, Service shop-svc on port 80. It's a rulebook, nothing more.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shop-svc
port:
number: 80Same Ingress, three clusters
Here's the same shop Ingress in three clusters. In the first, there's no controller, so nobody reads it and the rules sit unused. In the second, a controller exists but handles a different class, so it skips shop. Only in the third, where an nginx controller matches, does the Ingress get served.
Four pieces, four jobs
Four pieces, four jobs. The shop Ingress only holds the rules. IngressClass nginx is a label that says which controller should handle them. The nginx controller is the program that actually proxies traffic. And shop-svc, a Service, is a stable name that groups the ready Pods behind it.
Read the response you get
Each response tells you how far the request traveled. A timeout usually means it never reached a working controller, or got lost at the load balancer or DNS. A 404 means it arrived, but no rule matched. A 503 means a rule matched, but no ready endpoints.
- Timeout: controller, load balancer, or DNS
- 404: arrived, but no rule matched
- 503: rule matched, no ready endpoints
404: traffic arrived, no host matched
A 404 means the request reached the controller, but no rule matched. Here the client curls the controller by IP, so there's no Host header, the part of an HTTP request that names the site you want. The controller has nothing to match against shop.example.com. Add Host: shop.example.com, and the rule fires, shop-svc answers, and you get 200 OK.
503: rule matched, no ready Pods
Now the request carries the right host, so the controller finds the rule. Next it asks shop-svc for endpoints, which are the addresses of Pods that are ready to receive traffic. Here there are none ready, so the controller answers 503. Usually that means the Service selector doesn't match the Pod labels, or the readiness probe is failing.
What to check, in order
Work through these in order, one command per piece. First, does an IngressClass exist? Second, are the controller Pods running, and do the logs look healthy? Third, does describe on the shop Ingress show the controller picked it up? Fourth, does shop-svc list endpoints? Namespaces and names depend on your install.
# 1. Is there a class, and is one default?
kubectl get ingressclass
# 2. Is the controller running? (namespace varies)
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller
# 3. Did the controller pick up the Ingress?
kubectl describe ingress shop
# 4. Does the backend have ready endpoints?
kubectl get endpoints shop-svcStatus codes, ADDRESS, and annotations vary by controller; Gateway API splits the same way.
One caveat: exact status codes, when ADDRESS fills in, and annotations depend on your controller and environment. Gateway API follows the same split between resources and implementations.
An Ingress is a rulebook; only a matching controller enforces it.
An Ingress is a rulebook; only a matching controller enforces it. So when ADDRESS stays empty, check for a matching controller before you debug the rules.
