Files
k8s-starter-pack/docs/11-ingress.md
T
2026-09-03 04:37:04 +01:00

3.4 KiB

11 — Ingress: many hostnames, one address

So far, every app that needs to be reachable gets its own dedicated address from MetalLB's BGP pool (docs/05-metallb.md) — Argo CD at 10.10.60.10, the demo app at 10.10.60.11. That's fine for a handful of apps, but doesn't scale: every app eats another address out of a pool that's only so big, and there's no way to route by hostname (blog.ahmza.com vs photos.ahmza.com sharing one address on port 443).

What Ingress actually is

An Ingress controller is a reverse proxy that sits behind one MetalLB address and reads Ingress resources — small manifests that say "requests for this hostname go to that Service." Instead of every app declaring its own type: LoadBalancer Service, most apps go back to a plain internal ClusterIP Service, and get an Ingress resource pointing at it. One address, many hostnames.

ingress-nginx is the controller this cluster uses — the most common, most documented choice, distributed as a Helm chart just like MetalLB and Longhorn (see apps/ingress-nginx/Chart.yaml).

What's already running

apps/ingress-nginx.yaml → one Application, pointing at apps/ingress-nginx, pulling in the upstream chart. apps/ingress-nginx/values.yaml gives its Service a fixed address from the MetalLB pool (10.10.60.12 — see docs/network.md) and marks its IngressClass as the cluster default, so an Ingress resource that doesn't name a class explicitly still uses it — the same convenience Longhorn gives PVCs that don't name a storageClassName.

Unlike MetalLB and Longhorn, ingress-nginx needed no Pod Security exemption: it only needs the NET_BIND_SERVICE capability to bind ports 80/443, which Kubernetes' baseline profile already permits (unlike hostNetwork or hostPath, which it forbids).

Verify it's actually running

argocd app get ingress-nginx
kubectl -n ingress-nginx get svc

EXTERNAL-IP should show 10.10.60.12.

kubectl get ingressclass

Should show one IngressClass, marked as the default via annotation.

Routing a real app through it

Converting an app from its own MetalLB address to Ingress means:

  1. Change its Service from type: LoadBalancer back to the implicit default, ClusterIP — it no longer needs its own address.
  2. Add an Ingress resource naming a real hostname and pointing at that Service.
  3. Point that hostname at ingress-nginx's address, 10.10.60.12 — either a real DNS record (safe even for a LAN-only cluster: a public DNS record pointing at a private address just won't resolve to anything reachable from outside your LAN yet, which is fine until you actually expose this cluster publicly) or a local override for testing.

This is exactly what docs/12-cert-manager.md builds on next — a real hostname is what a TLS certificate actually gets issued for.

Checklist

  • ingress-nginx Application Synced/Healthy
  • kubectl -n ingress-nginx get svc shows EXTERNAL-IP 10.10.60.12
  • kubectl get ingressclass shows the default class
  • (Optional, hands-on) Converted one app to route through Ingress with a real hostname instead of its own MetalLB address

Continue to docs/12-cert-manager.md for real HTTPS certificates on that hostname.