Lesson 4 of 6

Services & Networking

Every pod gets its own IP — and loses it the moment the pod is replaced, which Lesson 3 just taught Kubernetes to do constantly. So how does your frontend reliably reach "the API" when "the API" is three pods whose addresses change daily? Never by IP. You give the group a Service: one stable name and address in front of an ever-changing set of pods.

💡 The Bottom Line

A Service is a stable virtual IP + DNS name that load-balances across all pods matching its label selector. Pods come and go; the Service's address never changes. In-cluster traffic uses ClusterIP services and plain DNS names like http://api.

The manifest — and the label glue

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 3000

selector: app: web means: route to every pod labeled app: web — the same labels the Deployment stamped onto its pods. That's the whole wiring mechanism; no registration step, no config file listing pod addresses. A new pod with a matching label is behind the Service seconds after becoming ready. port is the Service's own port; targetPort is where the container actually listens.

DNS comes free: any pod in the same namespace can call http://web — Kubernetes' internal DNS resolves the Service name to its stable ClusterIP.

The three main Service types

🙋 There Are No Dumb Questions

Q: So is a LoadBalancer Service how big clusters expose dozens of apps?
A: Usually not one per app — cloud load balancers cost money each. The common pattern is one LoadBalancer in front of an Ingress controller (often Nginx!), which then routes by hostname and path to many ClusterIP services: api.example.com → api service, www.example.com → web service. Ingress is beyond this track's scope, but knowing this is where the story goes keeps the Service types from feeling incomplete.

⚠️ Watch Out

A Service whose selector matches no pods silently accepts connections and refuses them all. If http://web times out, the first check is kubectl get endpoints web — an empty ENDPOINTS column means the selector and your pods' labels don't match (typo, or the pods aren't ready). This is the #1 Service bug, and it's a one-character typo away at all times.

🔧 Try It Yourself

With the web Deployment from Lesson 3 running (nginx image, targetPort: 80), apply the Service manifest above, then prove the stable-name claim from inside the cluster:

kubectl apply -f service.yaml
kubectl get endpoints web           # three pod IPs listed
kubectl run test --rm -it --image=busybox -- sh
wget -qO- http://web                # nginx answers, by name
exit

Then delete a pod (Lesson 3 style), re-check endpoints, and note the Service never blinked while the pod IPs behind it changed.

✅ Quick Check

How does a Service know which pods to send traffic to?


Next up: getting configuration and credentials out of your images — ConfigMaps and Secrets.

← Back to
Next →