Statement — Project 11: Kubernetes Services (ClusterIP, NodePort, LoadBalancer)

3 min

Practice · Module 07 — Kubernetes: basic concepts · Level intermediate

Try alone first! Complete the project with this brief only. The solution (commented manifests + commands) is in the README.md, folded. Open it only after you have tried.


Prerequisites

  • The Docker Desktop Kubernetes cluster enabled (type Kubeadm) — see project 10.
  • The demo-k8s:1.0 image already built (otherwise: docker build -t demo-k8s:1.0 ./app).

Goal

Understand what a Service is for and master the three main types:

  • ClusterIPinternal cluster access + service discovery by DNS name;
  • NodePortexternal access via a machine port;
  • LoadBalancerexternal access via a “public” IP (localhost with Docker Desktop).

All of that on top of the same Deployment: one set of Pods, three ways to expose them.


The problem to solve

Pods are ephemeral: they are born, they die, they change IP. You therefore cannot rely on a Pod’s IP. You need a stable address that distributes traffic to the right Pods: that is the role of the Service, which finds its Pods thanks to labels.


Work to do

Part 1 — The Deployment (the Pods to expose)

  1. Deploy an app in 3 replicas that displays the Pod name (reuse demo-k8s:1.0).
  2. Give the Pods a clear label (e.g. app: demo-back).

Part 2 — ClusterIP + service discovery

  1. Create a ClusterIP Service named demo-clusterip (port 80 → 5000).
  2. Demonstrate DNS discovery: start a temporary client Pod and call the service by its name:
    curl http://demo-clusterip
  3. Reload several times and see that the Pod name changes (internal load balancing).

Part 3 — NodePort (external access)

  1. Create a NodePort Service named demo-nodeport (nodePort 30082).
  2. Open http://localhost:30082 from your browser.

Part 4 — LoadBalancer (“cloud” external access)

  1. Create a LoadBalancer Service named demo-lb (port 8090).
  2. Check the EXTERNAL-IP (kubectl get svc) and open http://localhost:8090.

Part 5 — Observe and understand

  1. List the Services (kubectl get svc) and identify: TYPE, CLUSTER-IP, EXTERNAL-IP, PORT(S).
  2. Look at the Endpoints (kubectl get endpoints demo-clusterip): those are the Pod IPs behind the Service.
  3. Change a Pod label (or the selector) and observe that it leaves the Endpoints.

Reflection questions

  • Why can we not simply use a Pod IP?
  • Which Service type for: (a) an internal database, (b) a public website in local dev, (c) a public API in cloud production?
  • How does a Pod find another service by its name? (role of CoreDNS)
  • What does a Service’s Endpoints list contain, and who updates it?
  • What happens if no Pod matches the Service selector?

Deliverables

  • k8s/deployment.yaml and the three Services (service-clusterip.yaml, service-nodeport.yaml, service-loadbalancer.yaml).
  • A screenshot of kubectl get svc showing the 3 types.
  • A screenshot of DNS discovery (curl http://demo-clusterip from a client Pod) with 2 different Pod names.
  • A screenshot of kubectl get endpoints demo-clusterip.

Success criteria

CriterionExpected
ClusterIPReachable by DNS name from another Pod
NodePortReachable at http://localhost:30082
LoadBalancerEXTERNAL-IP = localhost, reachable at http://localhost:8090
DistributionThe Pod name changes between two requests
EndpointsThe 3 Pod IPs appear behind the Service

Stuck? The README.md contains the full solution, the ideas are detailed in 01-CONCEPTS-SERVICES.md, and 02-COMMANDES.md lists every useful kubectl — read them after you have tried.