Ingress (Caddy + nginx-ingress + Traefik)
The edge routing model — *.office.ilab.zone via Caddy, port 80 via Traefik, in-cluster via nginx.
R2-D2's edge layer is three components doing different jobs. Get the mental model straight before touching any of them.
Layer-by-layer
flowchart LR
Internet --> Caddy["Caddy (*.office.ilab.zone)"]
Caddy -->|HTTPS, host header preserved| Nginx["nginx-ingress on 192.168.3.211–214:8080"]
Internet --> Traefik["Traefik (port 80)"]
Nginx --> Svc[Service VIPs via kube-vip]
Traefik --> Svc| Component | Role | Notes |
|---|---|---|
| Caddy | Public-facing reverse proxy for *.office.ilab.zone hostnames | Terminates TLS, forwards to nginx-ingress |
| nginx-ingress | In-cluster ingress controller for the dashboard + most services | Lives behind a fixed set of VIPs |
| Traefik | Handles port-80 traffic | Distinct from nginx — different ruleset, easy to confuse |
The Caddy → nginx convention
*.office.ilab.zone Caddy always proxies to nginx-ingress at
192.168.3.211–214:8080. It never points at kube-vip LBs. This is a
load-bearing convention: the kube-vip LBs are for L4 exposure; nginx is the L7
ingress; Caddy is the public edge. Mixing them produces ingress paths that look
like they work but bypass the dashboard's host-routing rules.
When adding a new *.office.ilab.zone hostname:
- Add a Caddy site directive pointing to
192.168.3.211:8080(or any of the four — nginx is replicated) withHostheader preserved. - Add an
Ingressresource in the relevant namespace (nginx class). - Do not also create a LoadBalancer Service for the same hostname.
Port 80 vs everything else
Port 80 traffic is Traefik, not nginx. Two ingress controllers exist because the port-80 ruleset historically lived in Traefik and detaching it has been deferred.
If you're adding HTTPS routing, you want nginx. If you're handling a port-80-specific case (HTTP-only legacy app, ACME HTTP-01 challenge), you want Traefik.
The kube-vip relationship
nginx-ingress sits behind LB VIPs allocated by kube-vip.
The four IPs 192.168.3.211–214 are kube-vip-assigned; Caddy points at them directly
rather than at a DNS name so it doesn't depend on cluster-DNS for edge routing.
Operator quick-reference
| Symptom | First check |
|---|---|
*.office.ilab.zone returns 502 | Caddy → nginx path; check nginx pod logs first |
| HTTPS works, HTTP redirect loops | Traefik vs nginx confusion — confirm which controller owns the route |
New Ingress resource not picked up | ingressClassName — must be the nginx class, not the Traefik class |
| LB IP not responding | kube-vip lease — see kube-vip |