Chapter 9

Connect Frontend, Backend, CORS, and Ingress

Deploy both images to Minikube, route two hostnames through ingress, and allow the browser origin explicitly.

Just started Saved in this browser.

Kubernetes Services solve Pod-to-Pod addressing, but a browser needs externally resolvable HTTP routes. The chart creates one ingress hostname per component: simple-app.test for React and api.simple-app.test for FastAPI.

Ingress routes browser requests to the frontend and backend

Step by step

Download this chapter's files

Use your browser to download either ivia-chapter-09.tar.gz or ivia-chapter-09.zip. The archive is self-contained; you do not need this tutorial repository.

Open a terminal after the browser download:

cd ~/Downloads
tar -xzf ivia-chapter-09.tar.gz
cd ivia-chapter-09

All remaining relative paths in this chapter start from that extracted directory.

Do this

The challenge

Challenge: deploy the full-stack snapshot and load the frontend through ingress with a successful cross-origin API request.

Prepare

Prerequisites

  • Running Minikube, kubectl, Helm, and Docker.
  • The node label ivia.ch/nodetype=app.
  • Ports 80 and 443 available to Minikube's ingress path.
  • The full-stack snapshot; no local frontend/backend containers should occupy ports needed for testing.
Outcome

Learning goals

  • Build frontend and backend images into Minikube
  • Enable nginx ingress
  • Map test hostnames
  • Trace browser-to-API traffic
  • Diagnose CORS separately from networking
Step by step

Build images where Minikube can use them

minikube image build -t simple-backend:local fullstack-app/backend
minikube image build -t simple-frontend:local fullstack-app/frontend
minikube image ls | grep -E 'simple-(frontend|backend)'
Step by step

Enable ingress and deploy

minikube addons enable ingress
kubectl wait --namespace ingress-nginx \
  --for=condition=Ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=180s
kubectl label node minikube ivia.ch/nodetype=app --overwrite
helm upgrade --install simple-app \
  oci://harbor.ivia.ch/ivia-generic-helm-chart/ivia-generic-helm-chart \
  --version 4.8.0 -n tutorial --create-namespace \
  --atomic --timeout 5m \
  -f fullstack-app/values.yaml
kubectl get pods,services,ingresses -n tutorial

Values mount a runtime config.js containing http://api.simple-app.test. Backend CORS_ORIGINS permits only http://simple-app.test. The ingress annotations disable HTTPS redirection for this local exercise; production should use valid TLS.

Step by step

Resolve local hostnames

First validate without changing DNS:

MINIKUBE_IP=$(minikube ip)
curl --fail --resolve simple-app.test:80:$MINIKUBE_IP http://simple-app.test/
curl --fail --resolve api.simple-app.test:80:$MINIKUBE_IP http://api.simple-app.test/health
curl --fail --resolve api.simple-app.test:80:$MINIKUBE_IP \
  -H 'Origin: http://simple-app.test' \
  -H 'Access-Control-Request-Method: GET' \
  -X OPTIONS -i http://api.simple-app.test/api/greeting

For browser access, append both names to /etc/hosts:

echo "$(minikube ip) simple-app.test api.simple-app.test" | sudo tee -a /etc/hosts

Open http://simple-app.test and inspect the browser Network panel. The document comes from the frontend host; /api/greeting comes from the API host.

Verify

Expected validation

Both Pods are 1/1 Running. Both Ingress objects list their host. The preflight response includes access-control-allow-origin: http://simple-app.test, and the browser displays Hello from a configured FastAPI pod!.

Troubleshoot

Troubleshooting and common pitfalls

  • Ingress has no address: wait for the addon controller and inspect kubectl get pods -n ingress-nginx.
  • Browser DNS error: verify both host entries and flush browser DNS cache; curl --resolve confirms routing independently.
  • HTTP redirects to HTTPS: ensure values include nginx.ingress.kubernetes.io/ssl-redirect: "false".
  • CORS failure despite HTTP 200: backend must permit the exact frontend origin, including scheme and port.
  • ImagePullBackOff: verify local images and IfNotPresent pull policy.
  • Docker-driver ingress unreachable: run minikube tunnel in a separate terminal if your platform requires it, then use 127.0.0.1 for hosts.
  • Editing frontend source for API URL: change the chart-managed runtime ConfigMap instead; one image should serve multiple environments.

You now have a complete request path from browser to ingress to two Kubernetes Services. That is real full-stack platform work.

Reference

Official references

Just started Saved in this browser.