Frontend Labs
⋯

Chapter 56 — Services and how traffic finds a pod

In one sentence

Pods are ephemeral — they're created, destroyed, and rescheduled with new IP addresses constantly — so a Service provides a STABLE address and name that automatically, continuously routes traffic to whichever healthy pods currently match a label selector.

Why this matters

"How does anything reliably talk to my constantly-changing pods" is one of the first genuinely confusing questions for anyone new to Kubernetes, and Services are the entire, elegant answer.

How it actually works

   apiVersion: v1
   kind: Service
   metadata:
     name: web-app-svc
   spec:
     selector:
       app: web-app              # matches the SAME label from Chapter
                                # 55's Deployment's pod template
     ports:
     - port: 80                   # the Service's OWN port
       targetPort: 80              # the port on the PODS to send
                                # traffic to
     type: ClusterIP               # the default -- internal-only
                                # (Chapter 37's networking, one layer
                                # up)
   THE CORE MECHANISM: a Service doesn't point at specific PODS by
   name or IP -- it uses a LABEL SELECTOR, continuously, live. Whatever
   pods CURRENTLY have matching labels are automatically included as
   valid destinations -- as pods are created, destroyed, or rescheduled
   (each getting a NEW IP, Chapter 55), the Service's routing updates
   automatically, with no manual reconfiguration ever needed. This is
   EXACTLY Docker Compose's container-name DNS resolution (Chapter 50),
   but far more dynamic -- resolving to a live, continuously-updated SET
   of healthy pods, not one fixed container.

   SERVICE TYPES, briefly:
     ClusterIP (default)   reachable only FROM WITHIN the cluster --
                          the normal way services talk to EACH OTHER.
     NodePort                 additionally exposes the service on a
                          specific port on EVERY node's own IP --
                          simple, but rarely the final answer for real
                          external traffic.
     LoadBalancer              (on a cloud provider) provisions an
                          actual, external cloud load balancer pointing
                          at the service -- the standard way to expose
                          something to the real internet.

   EVERY SERVICE also gets a DNS NAME, automatically, resolvable from
   anywhere in the cluster: `web-app-svc.default.svc.cluster.local`
   (or just `web-app-svc` from within the same namespace) -- Chapter
   37's DNS resolution, provided automatically by Kubernetes' own
   internal DNS (CoreDNS, typically).

Real-world example

   The PROBLEM Services solve is explicit, foundational, and explained
   directly in Kubernetes' own official documentation: pods are, by
   design, EPHEMERAL. A pod can be deleted and recreated (a
   Deployment's rolling update, Chapter 60; a node failure and
   reschedule; a manual scale-down-then-up) and the REPLACEMENT pod
   gets a COMPLETELY NEW IP ADDRESS every time. Any system that tried
   to talk to "the web server" by remembering a specific pod's IP
   address would break constantly, unpredictably, every single time a
   pod was replaced for ANY reason -- a genuinely unworkable model at
   any real scale, and precisely the problem Kubernetes' designers
   (with the Borg lineage's years of real operational experience behind
   them, Chapter 53) built the Service abstraction specifically to
   solve from day one, not as a later addition.
   This is worth sitting with as a GENERAL PRINCIPLE that recurs
   throughout distributed systems, not just Kubernetes specifically:
   whenever INDIVIDUAL INSTANCES of something are expected to come and
   go, you need a STABLE LAYER OF INDIRECTION (a name, a label selector,
   a load balancer) in front of them -- pointing directly at an
   individual, ephemeral instance is a reliability bug waiting to
   happen, in Kubernetes or in any other real distributed system.

Try it yourself

# Continue from Chapter 55's deployment (recreate if needed)
kubectl apply -f deployment.yaml

cat > service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: web-app-svc
spec:
  selector:
    app: web-app
  ports:
  - port: 80
    targetPort: 80
EOF
kubectl apply -f service.yaml
kubectl get svc web-app-svc

# See the Service resolve to MULTIPLE pod IPs, live
kubectl get endpoints web-app-svc     # every pod IP currently backing
                                      # this service

# Prove it survives a pod being replaced
OLDPOD=$(kubectl get pods -l app=web-app -o jsonpath='{.items[0].metadata.name}')
test -n "$OLDPOD" && kubectl delete pod "$OLDPOD"
sleep 3
kubectl get endpoints web-app-svc      # a DIFFERENT set of IPs now --
                                       # the OLD pod's IP is gone, a
                                       # NEW pod's IP is present -- but
                                       # the SERVICE's own address/name
                                       # never changed at all

# Reach it from inside the cluster (DNS resolution in action)
kubectl run testcurl --image=curlimages/curl --rm -it --restart=Never -- \
  curl -s http://web-app-svc

kubectl delete -f service.yaml -f deployment.yaml

Common mistakes

  • Hardcoding a specific pod's IP anywhere. It WILL change — always go through a Service (or its DNS name) instead.
  • Forgetting the Service's selector must actually match the pod template's labels. A typo here silently results in a Service with ZERO healthy endpoints — always check kubectl get endpoints when traffic isn't reaching pods as expected.
  • Using NodePort as the default choice for external traffic. It works, but LoadBalancer (on a cloud provider) or an Ingress controller (Chapter 59-adjacent territory) is almost always the better real-world answer for actual internet-facing traffic.

Check yourself

  1. What problem does a Service solve, specifically?
  2. How does a Service know which pods to route traffic to, and does that update automatically?
  3. What's the difference between ClusterIP, NodePort, and LoadBalancer?

Further reading

  • Docs: Kubernetes' own official "Service" documentation — thorough, and the authoritative reference for every service type and field.
  • Reference: kubectl explain service.spec, kubectl get endpoints.
  • Concept: search "stable indirection ephemeral instances distributed systems" for the broader pattern this chapter's lesson generalises into.

Generated from real-life-os-guide.md · 8 Oct 2026 16:36