ingress-nginx¶
ingress-nginx is the Kubernetes Ingress controller. It routes external HTTP/S traffic to services inside the cluster based on hostname and path rules.
See ADR-005 for the full decision record.
How It Works¶
graph LR
Browser -->|"http://grafana.local"| Tunnel["minikube tunnel\n127.0.0.1:80"]
Tunnel --> nginx["ingress-nginx\ncontroller pod"]
nginx -->|"matches Ingress rule\nhost: grafana.local"| Grafana["grafana Service\n(ClusterIP)"]
Minikube Setup: LoadBalancer + minikube tunnel¶
We use LoadBalancer type. On macOS with the Docker driver, the minikube IP (192.168.49.x) is inside Docker's bridge network and is not reachable from the host. minikube tunnel solves this by assigning 127.0.0.1 as the external IP.
| Mode | Access URL | Requires |
|---|---|---|
| LoadBalancer (current) | http://<hostname> (port 80) |
sudo minikube tunnel running |
| NodePort (old) | http://<minikube-ip>:30080 |
Works on Linux; broken on macOS Docker driver |
Start minikube tunnel¶
Run in a dedicated terminal and keep it open:
Expected output:
Verify the external IP is assigned:
kubectl get svc ingress-nginx-controller -n ingress-nginx
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# ingress-nginx-controller LoadBalancer 10.x.x.x 127.0.0.1 80:30080/TCP,443:30443/TCP
/etc/hosts¶
Point hostnames to 127.0.0.1 (not $(minikube ip)):
Add entries:
Defining an Ingress¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
cert-manager.io/cluster-issuer: "local-ca-issuer" # optional TLS
spec:
ingressClassName: nginx
rules:
- host: myapp.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 8080
tls: # optional
- hosts:
- myapp.local
secretName: myapp-tls
Add the hostname to /etc/hosts:
Then open http://myapp.local — no port suffix needed.
File Reference¶
infrastructure/controllers/ingress-nginx.yaml
Troubleshooting¶
Service unreachable / connection refused:
- Is minikube tunnel running? Check with ps aux | grep tunnel
- Is the hostname in /etc/hosts pointing to 127.0.0.1?
- Is there an Ingress object for the hostname? kubectl get ingress -A
404 from nginx:
- The tunnel is working but no Ingress matches the host — check the Ingress host: field
- Test: curl -H "Host: myapp.local" http://127.0.0.1/ should return your app
minikube tunnel drops:
- The tunnel process exits if the terminal is closed or the session times out
- Restart with sudo minikube tunnel