
- Reproduce pod churn and observe changing pod IPs.
- Expose the app inside the cluster using a ClusterIP Service.
- Expose it externally with a NodePort.
- Add an Ingress (with an NGINX ingress controller) to demonstrate path-based routing to multiple backends.
- Kubernetes cluster with sufficient permissions.
- NGINX Ingress Controller installed (see the NGINX Ingress Controller docs: https://kubernetes.github.io/ingress-nginx/).
- Docker images: NGINX (https://hub.docker.com/_/nginx) and HashiCorp http-echo (https://hub.docker.com/r/hashicorp/http-echo).
Create a deployment and observe pod churn
Create a Deployment namedweb using the NGINX image with three replicas, then inspect the pods:
Expose the Deployment as a ClusterIP Service
Expose theweb deployment as a ClusterIP Service (the default type) named web-svc:
Expose the app externally with NodePort
Create a NodePort Service namedweb-nodeport:
localhost with the assigned NodePort:
NodePort opens high-numbered ports (typically in the 30000–32767 range) on every node. It’s simple, but not user-friendly for end users, and it doesn’t provide host- or path-based routing or TLS termination. For host/path routing and easier external access, use an Ingress with an ingress controller.
Use Ingress for host/path-based routing (NGINX ingress controller)
Ingress is a cluster resource that defines routing rules (host/path) and optionally TLS termination. An ingress controller (e.g., NGINX) watches Ingress objects and programs a reverse proxy accordingly. Check that an NGINX ingress controller is running in theingress-nginx namespace and that its Service is present:
Add a second backend (api) for path-based routing
Create a second backend deploymentapi using HashiCorp’s http-echo image so it returns a simple response, then expose it as api-svc:
Create an Ingress resource with path-based rules
Save the following asingress.yaml (it rewrites paths to / and routes /api to api-svc:5678 and / to web-svc:80):
Summary: the three routing layers
Ingress routes to Services, and Services route to Pods. Remember these three layers:Debugging checklist (outside → inside)
- Can’t reach the app externally?
- Verify the ingress controller pod(s) and Service are running.
- Confirm the ingress controller Service exposes ports (NodePort or LoadBalancer).
- Ingress reachable but wrong backend?
- Inspect the Ingress resource:
kubectl describe ingress <name>. - Check annotations (e.g., rewrite rules) and ingressClassName.
- Inspect the Ingress resource:
- Service has no endpoints?
- Check Service selectors and Pod labels:
kubectl describe svc <svc>andkubectl get pods --show-labels. - Confirm pods are listening on the expected
targetPort.
- Check Service selectors and Pod labels:
When troubleshooting, always follow the chain: Ingress → Service → Pod. Verify the ingress-controller is running, the Ingress rules point to the correct services, and the Services select the appropriate Pods (labels and ports).
Further reading and references
- Kubernetes Services: https://kubernetes.io/docs/concepts/services-networking/service/
- Kubernetes Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/
- NGINX Ingress Controller: https://kubernetes.github.io/ingress-nginx/
- NGINX image on Docker Hub: https://hub.docker.com/_/nginx
- HashiCorp http-echo image: https://hub.docker.com/r/hashicorp/http-echo