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. An Ingress is an HTTP router at the edge of the cluster: it matches hostnames and forwards to Services. CORS is a browser rule that decides whether a page from one origin may call an API on another. DNS / hosts mapping tells your computer which IP belongs to those hostnames.

Ingress routes browser requests to the frontend and backend

Last updated: 2026-07-20

Audience

Who this chapter is for

This chapter is for beginners who ran the two containers locally in Chapter 8 and have a Ready Minikube cluster. You will enable the ingress addon and edit hosts or use curl --resolve.

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

After this chapter, you will be able to:

  • Build frontend and backend images into Minikube
  • Enable the nginx ingress controller and wait until it is Ready
  • Map test hostnames for browser access
  • Trace browser-to-API traffic
  • Diagnose CORS separately from networking
Step by step

Build images where Minikube can use them

We build inside Minikube so the cluster nodes see the same tags the chart requests.

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)'

You should see both image names in the list.

Step by step

Enable ingress and deploy

We enable the addon because the Ingress objects need a controller Pod that actually routes traffic.

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

Expected: both app Pods 1/1 Running, and Ingress objects listing simple-app.test and api.simple-app.test. The controller wait should complete without timeout.

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. We do this because curl --resolve proves routing independently of your hosts file.

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

You should get HTML from the frontend host, health JSON from the API host, and a preflight response that includes access-control-allow-origin: http://simple-app.test.

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.
Practice

Recap and practice

Recap: Ingress routes hostnames; hosts/--resolve maps names to Minikube; CORS is a separate browser check on the API response.

Try to explain in your own words:

  1. Why can curl succeed when the browser still reports a CORS error?
  2. What does the ingress controller do that a Service alone does not?

Exercise: Break CORS by temporarily removing the frontend origin from values, upgrade, reload the page, then restore the correct origin.

Stretch: Capture the OPTIONS preflight in the browser Network panel and list three response headers that matter for CORS.

Reference

Official references

Just started Saved in this browser.