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
ClusterIP(default) — reachable only inside the cluster. The right choice for service-to-service traffic: databases, internal APIs.NodePort— additionally opens a fixed port (30000–32767) on every node's IP. Crude but dependency-free — handy for local clusters and quick demos.LoadBalancer— asks the cloud provider (AWS/GCP/Azure) to provision a real external load balancer pointing at the Service. The standard way traffic from the internet enters a cloud cluster.
🙋 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.