Ingress and TLS
Expose the control plane (and optionally Prometheus) outside the cluster with
ingress-nginx and cert-manager — no kubectl port-forward required.
What gets exposed
Section titled “What gets exposed”| Service | Default host | Backend | Notes |
|---|---|---|---|
| Control plane (API + UI) | test-scale.local |
test-scale-ctrl-plane:8080 |
Primary entry point |
| Prometheus | prometheus.test-scale.local |
test-scale-prometheus:9090 |
Opt-in via Helm values |
Postgres, NATS, workers, and the OTLP aggregator port are not exposed.
Quick start (kind / local)
Section titled “Quick start (kind / local)”1. Bring up the cluster with Ingress enabled
Section titled “1. Bring up the cluster with Ingress enabled”make k8s-ingress-up# orINGRESS_ENABLED=1 deploy/kubernetes/scripts/up.shThis installs:
- ingress-nginx (NodePort
30080/30443) - cert-manager + CRDs
- self-signed ClusterIssuer (
test-scale-selfsigned) - Helm release with
ingress.enabled=true
2. Add a hosts entry
Section titled “2. Add a hosts entry”echo '127.0.0.1 test-scale.local' | sudo tee -a /etc/hosts3. Open the UI
Section titled “3. Open the UI”open https://test-scale.local:30443# Browsers will warn about the self-signed cert — proceed or use HTTP:open http://test-scale.local:300804. Run the smoke test through Ingress
Section titled “4. Run the smoke test through Ingress”make k8s-ingress-smoke# orCONTROL_PLANE_URL=https://test-scale.local:30443 INSECURE_TLS=1 \ deploy/kubernetes/scripts/smoke.shFull loop:
make k8s-ingress-verifyNote: Existing
make k8s-verifystill uses port-forward and keepsingress.enabled=false— CI stays unchanged.
Helm values
Section titled “Helm values”ingress: enabled: true className: nginx ctrlPlane: enabled: true host: test-scale.example.com path: / pathType: Prefix prometheus: enabled: false # set true to expose Prometheus UI host: prometheus.test-scale.example.com tls: enabled: true secretName: "" # defaults to <release>-tls certManager: enabled: true createCertificate: true clusterIssuer: letsencrypt-prodInstall on an existing cluster:
helm upgrade test-scale deploy/kubernetes/helm/test-scale \ --namespace test-scale \ --set ingress.enabled=true \ --set ingress.ctrlPlane.host=test-scale.example.com \ --set ingress.tls.certManager.clusterIssuer=letsencrypt-prodProduction TLS (Let’s Encrypt)
Section titled “Production TLS (Let’s Encrypt)”Prerequisites
Section titled “Prerequisites”- A real DNS name pointing to your ingress load balancer
- ingress-nginx installed with a LoadBalancer or public NodePort (not kind)
- cert-manager installed
1. Install the ingress stack (without kind NodePort overrides)
Section titled “1. Install the ingress stack (without kind NodePort overrides)”helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginxhelm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx --create-namespace
helm repo add jetstack https://charts.jetstack.iohelm upgrade --install cert-manager jetstack/cert-manager \ --namespace cert-manager --create-namespace \ --set crds.enabled=true2. Configure the issuer
Section titled “2. Configure the issuer”Edit deploy/kubernetes/manifests/clusterissuer-letsencrypt-prod.yaml with your
email, then apply:
kubectl apply -f deploy/kubernetes/manifests/clusterissuer-letsencrypt-prod.yaml3. Deploy test-scale with Ingress
Section titled “3. Deploy test-scale with Ingress”helm upgrade --install test-scale deploy/kubernetes/helm/test-scale \ --namespace test-scale \ --set ingress.enabled=true \ --set ingress.ctrlPlane.host=test-scale.example.com \ --set ingress.tls.certManager.clusterIssuer=letsencrypt-prodcert-manager creates a Certificate and stores the TLS secret referenced by the
Ingress. Check status:
kubectl get certificate -n test-scalekubectl describe certificate test-scale-tls -n test-scaleArchitecture
Section titled “Architecture”flowchart LR
User[Browser / CLI] --> ING[ingress-nginx]
ING -->|TLS secret| CM[cert-manager]
CM -->|ClusterIssuer| LE[Let's Encrypt / self-signed]
ING -->|test-scale.local| CP[ctrl-plane :8080]
ING -.->|optional| PROM[prometheus :9090]
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
If make k8s-down or make k8s-ingress-up fails with connection refused, |
|
| the kind cluster container may have stopped. Recreate it: |
kind delete cluster --name test-scalemake k8s-ingress-upup.sh auto-detects stale clusters and recreates them, but a manual delete
is fastest if Docker was restarted.
| Certificate stuck Pending | Check kubectl describe certificate; verify DNS and ClusterIssuer |
| 404 from ingress | Confirm ingress.ctrlPlane.host matches the URL hostname |
| Browser TLS warning (local) | Expected with self-signed issuer; use -k curl or HTTP on :30080 |
| ACME challenge fails (prod) | DNS must resolve to ingress; port 80 must reach ingress-nginx |
| Path | Purpose |
|---|---|
helm/test-scale/templates/ingress.yaml |
Ingress rules |
helm/test-scale/templates/certificate.yaml |
cert-manager Certificate |
manifests/clusterissuer-selfsigned.yaml |
Local/kind issuer |
manifests/clusterissuer-letsencrypt-prod.yaml |
Production issuer template |
scripts/install-ingress.sh |
Installs nginx + cert-manager + issuer |
See also 05-phase3-kubernetes.md for the full K8s walkthrough.