Services & Networking Basics

Kubernetes Fundamentals

Chapter 6 · Services & Networking Basics

Chapter 5's rolling updates and self-healing constantly create and destroy pods, each with a new IP address. This chapter covers the abstraction that solves the resulting problem — directly closing the loop on Chapter 3's warning: never hardcode a pod IP.

The Problem Services Solve, Restated

Pod IPs change constantly — a rolling update, a self-healing replacement, any pod recreation event changes it. An application can't reasonably track and update which specific IPs to talk to every time this happens. What's needed is a stable address that always routes to whichever healthy pods currently exist, regardless of their individual identities.

What a Service Actually Is

A Service provides a single, stable IP address and DNS name that automatically routes to a dynamic, changing set of pods. It uses the exact same label-selector mechanism as Chapter 5's ReplicaSets — a Service doesn't care about individual pod names or IPs, it continuously watches for pods matching its selector labels and load-balances traffic across whichever currently match and are healthy. This is another instance of the reconciliation loop pattern: the Service's list of backing pods (its Endpoints) is kept continuously up to date automatically.

Service Types — ClusterIP, NodePort & LoadBalancer

TypeReachable fromTypical use
ClusterIP (default)Inside the cluster onlyInternal service-to-service traffic — e.g. web tier → backend tier
NodePortOutside, via a static port on every node's own IPA blunt mechanism, less commonly used directly in production
LoadBalancerOutside, via a provisioned cloud load balancerThe common way to expose a service to the public internet on a managed provider (cloud1-5's load balancer material)

In-Cluster DNS

Every Service automatically gets a DNS name within the cluster — typically <service-name>.<namespace>.svc.cluster.local, or just <service-name> from within the same namespace. This means application code can simply use the service name as a hostname, needing no IP address at all — cluster or pod. This is the actual mechanism that closes the loop on Chapter 3's warning: an application should talk to my-backend-service, never a pod IP directly.

Endpoints — How a Service Tracks Its Pods

An Endpoints object (or EndpointSlice in modern Kubernetes) is automatically maintained by Kubernetes, listing the current IPs of pods matching a Service's selector. When a pod matching the selector is created or destroyed — Chapter 5's rolling updates and self-healing — the Endpoints list updates automatically and near-instantly, and the Service starts or stops routing traffic to it accordingly. This is genuinely the "glue" making the whole abstraction work — a direct Kubernetes-side parallel to cloud2-2's own load-balancer-health-check material from Cloud Platforms.

A Complete Service YAML, Explained

apiVersion: v1 kind: Service metadata: name: web-service spec: selector: app: demo ports: - port: 80 targetPort: 8080 type: ClusterIP

Services use plain v1, not apps/v1 — a nice, direct contrast to Chapter 5's own apiVersion warning, worth reinforcing rather than assuming it always follows the same pattern. spec.selector uses the same labels as Chapter 5's Deployment's pod template — that shared label is the connecting thread between the two resources. port is what the Service itself listens on; targetPort is what the container actually listens on — a genuinely easy point of confusion.

Testing Service Discovery

From any pod in the cluster, curl http://web-service just works — resolving via in-cluster DNS and load-balancing across whichever matching pods are currently healthy. A genuinely satisfying, concrete way to see the whole Chapter 3-through-6 arc pay off in one working example.

Never hardcode a pod IP — now fully explained
Chapter 3 warned against this without yet explaining the fix. Now it's concrete: always connect via a Service's stable DNS name. The Service's Endpoints mechanism transparently handles every pod replacement behind the scenes — the application code never needs to know or care.
port vs. targetPort — a genuinely common early mistake
Getting these backwards — or forgetting that the container's actual listening port must match targetPort exactly — is a frequent, confusing source of "why can't I reach my service" issues. port is what clients connect to; targetPort must match what the container itself is genuinely listening on.

Hands-On Exercises

Exercise 1

Explain why an application should connect to a Service's DNS name rather than a specific pod's IP address, tying directly to Chapter 3's pod disposability material.

📄 View solution
Exercise 2

Explain the difference between ClusterIP, NodePort, and LoadBalancer, and recommend which is appropriate for (a) a backend database only the app tier should reach, and (b) a public-facing web frontend on a managed cloud provider.

📄 View solution
Exercise 3

A Service's spec defines port: 80 and targetPort: 8080, but the container is actually listening on port 3000. Explain what would go wrong, and how to fix it.

📄 View solution

Chapter 6 Quick Reference

  • A Service gives a stable IP/DNS name routing to a dynamic, changing set of pods via the same label-selector mechanism as ReplicaSets
  • ClusterIP (internal only) · NodePort (static port on every node) · LoadBalancer (provisions a real cloud LB, the common public-facing choice)
  • In-cluster DNS lets code use a service name as a hostname — no IP knowledge needed at all
  • Endpoints — automatically tracks which pod IPs currently back a Service, updated the instant pods come or go
  • Services use v1, not apps/v1; port (what clients connect to) vs. targetPort (what the container listens on) is a common confusion
  • Chapter 3's "never hardcode a pod IP" is now fully explained — always use the Service's DNS name instead
  • Next chapter: ConfigMaps & Secrets — externalizing configuration, mounting as env vars/volumes