Skip to main content
Every Kubernetes platform engineer faces the same challenge early on: pods are ephemeral. They are created and destroyed frequently, and each new pod receives a different IP address. Relying on pod IPs for connectivity doesn’t scale — services provide a stable abstraction for discovery and load balancing. This demo shows why Services are essential, how ClusterIP and NodePort services work, and how an Ingress + Ingress controller lets you route external traffic to multiple services through a single entry point.

1) Pods are ephemeral — deployment example

Create a Deployment named web (nginx) with three replicas:
List pods and their IPs:
Example output (IPs will vary):
If you delete a pod, the Deployment controller will create a replacement pod with a different IP:
Example replacement:
Any client using the old pod IP (for example 172.17.0.6) will lose connectivity. This is the primary reason we use Services.

2) ClusterIP service (internal cluster access)

Expose the web Deployment as a ClusterIP service named web-svc on port 80:
Key fields from kubectl describe svc web-svc:
  • ClusterIP is internal-only (accessible from inside the cluster).
  • The Service uses selectors (labels) to discover matching pods — the Deployment assigned the label app=web.
Check pod labels:
Example output:

3) NodePort service (external access for labs or single-node)

If you need external access in a lab or single-node environment (without a cloud load balancer), use NodePort:
Example:
Curl the NodePort (on the node IP or localhost if running locally):
You should receive the NGINX default welcome page HTML. Note: NodePort assigns a port in the 30000–32767 range. This is convenient for testing but not ideal for production (awkward ports, limited range, no TLS termination). For path-based routing, virtual hosts, and TLS termination, use Ingress (with an Ingress controller).
Ingress provides host-based and path-based routing, and TLS termination. It requires an Ingress controller to implement the routing (for example, nginx-ingress, Traefik, or other controllers).

4) Ingress controller — verify it’s running

This lab uses the nginx ingress controller in namespace ingress-nginx. Verify controller pods and service:
Example:
  • In cloud environments the controller’s Service is often type LoadBalancer with an external IP.
  • In labs it may be NodePort, which exposes controller ports on the node(s).
All external traffic for this demo will enter via the Ingress controller service.

5) Create a second service — api

Create an api Deployment using HashiCorp’s http-echo image to return a simple message. Use the --command flag to pass container arguments:
Example service:
Verify API pods:
You can test the API service from within the cluster or with kubectl port-forward to confirm it returns the message.

6) Create an Ingress resource to route to both services

Create an Ingress manifest (for example ingress.yaml) that routes /api to api-svc:5678 and / to web-svc:80. Example:
Apply the Ingress:
You should see the Ingress scheduled for sync by the nginx controller, and the two rules listed in the description.

7) Test routing via the ingress controller NodePort

Use the controller NodePort (for example 30080) to test both routes:
  • Root / should route to web-svc (NGINX welcome page).
  • /api should route to api-svc and return the echo message.
Example commands:
Expected responses:
  • curl localhost:30080/ returns the NGINX welcome HTML.
  • curl localhost:30080/api returns:
This demonstrates a single external entry point (the Ingress controller) routing to different internal services based on request path, without changing the application pods themselves.

8) The three-layer relationship

Understand the three-layer architecture and responsibilities:
  • Ingress: external routing, host/path matching, TLS termination (external entry point).
  • Service: stable internal discovery and load balancing (virtual IP / DNS for a set of pods).
  • Pod: the actual workload (ephemeral compute).
When debugging connectivity, walk the chain from outside in:
  • Can’t reach the app externally? Check the Ingress resource and the Ingress controller.
  • Ingress appears fine but routing is wrong? Re-check the Ingress rules and annotations.
  • Service has no endpoints? Verify pod labels/selectors and pod readiness.
  • Pod-level issues? Inspect pod logs and readiness/liveness probes.
Comparison: Service types Troubleshooting checklist
Ingress resources require a running Ingress controller. Creating an Ingress without a controller will not provide routing traffic. In cloud environments you may get a LoadBalancer service automatically for the controller; in labs you often use NodePort.
This walkthrough shows how Services and Ingress work together to provide stable discovery and flexible external routing, enabling reliable communication even as pods come and go.

Watch Video