Kubernetes Services: ClusterIP vs NodePort vs LoadBalancer vs ExternalName
Video: Day 9/40 — Kubernetes Services Explained • https://www.youtube.com/watch?v=tHAQWLKMTB0 • Duration: ~46 min
Key terms
| Term | Meaning |
|---|---|
| Service | Stable network endpoint for a set of pods |
| ClusterIP | Internal-only virtual IP (default type) |
| NodePort | Exposes a port on every node |
| LoadBalancer | Provisions an external cloud load balancer |
| ExternalName | Maps a Service to an external DNS CNAME |
| Selector | Labels picking the backend pods |
| Endpoints | The pod IPs currently behind a Service |
| port/targetPort/nodePort | Service / container / node port numbers |
Problem & solution
Pods are ephemeral and get a new IP each time they are recreated, so nothing can reliably address them. We need a stable virtual IP and DNS name that load-balances across a constantly changing set of matching pods.
Solution: Put a Service (ClusterIP/NodePort/LoadBalancer) in front of pods for a stable IP/DNS that load-balances to healthy pods.
The analogy
At our port, the actual ships come and go constantly, different vessels tie up at
different spots every day. If you told a customer "your goods are on the ship currently
at the third buoy," they'd be lost the moment it sailed. So the port gives each route a
permanent pier number: customers always go to "Pier 7," and the port quietly directs
them to whichever ships are berthed there right now. A Kubernetes Service is that
permanent pier number, a stable IP and DNS name, while the pods behind it are the
ever-changing ships. The Service's selector is the rule "all ships flying the
app=web flag dock at this pier."
Where this fits in the cluster
The same cluster entities appear in every day's notes; the <== marks what this day touches.
Why Services exist
Pods are ephemeral — they die and get recreated with new IPs. You can't rely on a pod IP. A Service gives a stable virtual IP + DNS name and load-balances across the matching pods.
Pods run on nodes. Each pod gets its own IP; the container listens on a
containerPort (e.g. 8080). Nodes have their own IPs too.
How a Service finds its pods: labels & selectors
A Service has no hard-coded pod list — its selector matches pod labels, and the matching pod IPs become the Service's Endpoints.
kubectl get endpoints <svc> # the actual pod IPs behind a service
The 4 Service types
1) ClusterIP (default) — internal only
Gives a stable virtual IP reachable only inside the cluster.
Use for pod-to-pod / internal microservice traffic.
2) NodePort — expose on every node's IP at a high port
Opens the same high port on every node, forwarding outside traffic to the pods.
3) LoadBalancer — cloud external LB
Asks the cloud provider for a public IP and front-ends the service with a managed load balancer.
4) ExternalName — DNS alias to an external host
Maps the service name to an external DNS host via a CNAME — no pods, no proxying.
Layering (each type builds on the previous)
Each type wraps the one below it: LoadBalancer sits on NodePort, which sits on ClusterIP.
Service YAML examples
Minimal manifests for the two types you create most often.
ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
selector:
app: web
ports:
- port: 80 # service port
targetPort: 80 # container port
NodePort:
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 30007 # optional; auto-assigned if omitted
port vs targetPort vs nodePort
These three ports map the hop from node, to service, to container — keep them straight.
Example mapping: 192.168.0.11:30007 (NodeIP:nodePort) to 10.96.0.5:80 (svc:port) to 10.1.1.8:8080 (podIP:targetPort).
Commands
Everyday commands to expose a Deployment, inspect the Service, and test it from inside the cluster.
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
kubectl get svc
kubectl get svc web -o wide
kubectl describe svc web
# test internal DNS from another pod
kubectl run tmp --image=busybox -it --rm -- wget -qO- web:80
Service DNS name
Every Service gets an in-cluster DNS name built from its name, namespace, and the cluster domain.
web . default . svc . cluster.local ─── ─────── ─── ───────────── service namespace type cluster name marker domain e.g. web.default.svc.cluster.local
End-to-end flow
A request reaches a stable Service and is load-balanced across the healthy pods picked by its selector.
Key takeaways
- Services give a stable IP/DNS + load balancing over ephemeral pods.
- ClusterIP internal, NodePort node IPs, LoadBalancer cloud public, ExternalName DNS alias.
- Remember the port / targetPort / nodePort trio.
Checklist
- [ ] Exposed a Deployment as ClusterIP and reached it from another pod
- [ ] Created a NodePort and hit it on a node IP
- [ ] Inspected
kubectl get endpoints - [ ] Can explain port vs targetPort vs nodePort