Skip to content

Lab · Intermediate

Lab: Ingress Returns 404

Ingress issues are rarely mystical. Debug from the edge inward: controller → ingress rule → service → endpoints → pods.

Prerequisites

What you should have before you begin.

IngressNetworkingOperations
  • A cluster with an ingress controller
  • kubectl installed
  • Basic Service/Ingress knowledge

Lab text

Follow the sequence. Change one thing at a time.

Goal

You will learn a stable diagnostic sequence for Ingress 404s that avoids the common mistake of editing YAML blindly.

You will confirm whether the controller is receiving the request, whether routing rules match, and whether the backend is healthy.

  • Confirm controller exists and is healthy.
  • Confirm ingressClassName and routing rules.
  • Confirm backend service has endpoints.

Start at the edge: the controller

If the controller is unhealthy, every downstream investigation is wasted.

  • Look for route reconciliation errors.
  • Confirm the controller watches the correct ingress class.

kubectl

shell

kubectl get pods -A | rg -n "ingress|gateway" || true
kubectl get ingressclass
kubectl logs -n <ingress-ns> deploy/<controller> --tail=200

Ingress rule match

404 can mean “no rule matched” or “backend returned 404.” Distinguish them.

  • Confirm host/path match the request you’re making.
  • Confirm the backend service name/port are correct.
  • Confirm pathType semantics (Prefix vs Exact) match your intent.

kubectl

shell

kubectl describe ingress <ing> -n <ns>
kubectl get ingress <ing> -n <ns> -o yaml

Backend service and endpoints

Ingress is only a router. If the Service is empty, routing cannot succeed.

  • If endpoints are empty: selector mismatch or pods not Ready.
  • If endpoints exist: test the service directly (port-forward).

kubectl

shell

kubectl get svc,ep,endpointslices -n <ns>
kubectl describe svc <svc> -n <ns>

Verify

Verify the backend without ingress. Then verify ingress after.

  • Backend returns expected response.
  • Ingress routes to the same backend when re-tested.

kubectl

shell

kubectl port-forward svc/<svc> 8080:<port> -n <ns>
# curl http://127.0.0.1:8080/healthz

Canonical link

Canonical URL: /labs/ingress-returns-404