Appendix: DNS, HTTP, and TCP/IP
Build a practical mental model for names, addresses, ports, connections, requests, and Kubernetes networking.
When a page cannot reach an API, “the network” is too broad a diagnosis. Work layer by layer: name resolution, IP reachability, TCP connection, HTTP exchange, then browser policy.
Download this chapter's files
Use your browser to download either ivia-chapter-11.tar.gz or ivia-chapter-11.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-11.tar.gz
cd ivia-chapter-11
All remaining relative paths in this chapter start from that extracted directory.
The challenge
Challenge: trace one request to the backend from DNS name through TCP connection to HTTP response and identify the layer of any failure.
Prerequisites
- A terminal with
kubectlandcurl. - A running Minikube cluster; the package includes a full-stack release to deploy if needed.
nslookupordigfor host DNS checks.
Learning goals
- Distinguish DNS from routing
- Distinguish IP addresses from ports
- Distinguish TCP from HTTP
- Distinguish cluster DNS from public DNS
- Distinguish HTTP failures from CORS enforcement
Prepare a traceable release
If simple-app is not already deployed, create it from this package:
minikube addons enable ingress
kubectl label node minikube ivia.ch/nodetype=app --overwrite
minikube image build -t simple-backend:local fullstack-app/backend
minikube image build -t simple-frontend:local fullstack-app/frontend
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
A layered request
- DNS maps a name such as
api.simple-app.testto an IP address. - IP routes packets between network interfaces.
- TCP establishes an ordered byte stream to a port such as 80 or 8080.
- HTTP sends a method, path, headers, and optional body over that connection.
- CORS is a browser policy applied to cross-origin HTTP responses; curl does not enforce it.
Kubernetes adds two useful abstractions. A Service has a stable virtual IP and DNS name despite changing Pod IPs. Ingress examines HTTP hostnames and paths, then forwards to a Service.
Trace from your computer
MINIKUBE_IP=$(minikube ip)
printf 'Minikube IP: %s\n' "$MINIKUBE_IP"
nslookup api.simple-app.test || true
curl --verbose --resolve api.simple-app.test:80:$MINIKUBE_IP \
http://api.simple-app.test/health
--resolve supplies a temporary DNS answer for curl. In verbose output, find the chosen IP, Connected to, the request line GET /health, the Host header, the response status, and JSON body.
Test raw TCP availability without sending HTTP:
nc -vz "$MINIKUBE_IP" 80
If nc is unavailable, curl's connection lines provide the same practical checkpoint.
Trace inside Kubernetes
Start a temporary DNS client Pod:
kubectl run dns-check -n tutorial --rm -it --restart=Never \
--image=registry.k8s.io/e2e-test-images/dnsutils:1.3 -- \
nslookup simple-app-backend.tutorial.svc.cluster.local
The complete Service name means: Service simple-app-backend, namespace tutorial, Service zone svc, cluster domain cluster.local.
Forward the Service and bypass ingress:
kubectl port-forward service/simple-app-backend 8080:8080 -n tutorial
In another terminal:
curl --verbose http://localhost:8080/health
If direct Service forwarding works but ingress does not, investigate Ingress, host resolution, or its controller—not the backend process.
Expected validation
The host trace connects to Minikube port 80 and receives HTTP 200 from /health. Cluster DNS returns a Service address. Port forwarding also returns 200. You should be able to name the first failed layer if one check differs.
Troubleshooting and common pitfalls
- DNS answer exists but connection is refused: naming worked; inspect the destination port, process, Service endpoints, and firewall.
- TCP connects but HTTP is 404: transport worked; check Host header, route, and path.
- HTTP succeeds in curl but browser fails: inspect CORS, mixed content, certificates, and browser console.
- Pod IP used directly: Pod IPs are replaceable. Use a Service name inside the cluster.
localhostambiguity: it always refers to the current network namespace—the host, a container, or a Pod depending on where the command runs.- ICMP ping fails: many systems block ping while TCP/HTTP works; test the protocol you actually need.
Layered debugging replaces guesswork with small proofs. That skill transfers to every distributed application you will build.