root-07-m03-services-and-service-discovery — a new, full gold-standard- pattern module: the Service/Endpoints/DNS request path, choosing the right Service type. Lesson, demonstration (a Service with zero Endpoints — the single fastest diagnostic check for this failure class), knowledge check, guided exercise (ClusterIP vs. NodePort vs. LoadBalancer for three real components), a real Lab (expose-service-basics), and a reflection. root-07-m04-ingress-networkpolicy-foundations — a new PARTIAL module: Ingress and NetworkPolicy at the architectural level (the security- control framing of NetworkPolicy is deliberately deferred to ROOT 09). Lesson + knowledge check + real Labs (ingress-task, network-policy). Co-Authored-By: Claude Sonnet 5 <[email protected]>
4.2 KiB
The Service/Endpoints/DNS Request Path
The problem: Pod IPs are not stable
Every Pod gets its own IP address, but that IP is NOT durable — when a Pod is replaced (a
rollout, a crash recovery, a reschedule), the new Pod gets a brand new IP. If another part of
your application had that old IP hardcoded, it would silently start talking to nothing. This is
the exact problem in expose-service-basics's scenario: "other pods cannot reliably connect
because pod IPs change when they restart."
A Service: a stable address in front of a moving set of Pods
A Service is a stable virtual IP and DNS name that automatically routes to whichever Pods currently match its label selector — regardless of how many there are or how often they change. You never talk to a Pod's IP directly in normal operation; you talk to the Service, and the Service's Endpoints (a live, continuously-updated list of the matching Pods' IPs) determines where traffic actually goes.
apiVersion: v1
kind: Service
metadata:
name: redis-svc
spec:
selector:
app: redis # <- matches Pods by label, same mechanism from ROOT 05
ports:
- port: 6379
This is the same label-selector mechanism you learned in ROOT 05 — a Service doesn't know or care about specific Pod names, only which Pods currently carry a matching label.
The three Service types you'll use most
- ClusterIP (the default) — reachable only from inside the cluster. Use this for internal-only communication, like one microservice talking to another or to a database.
- NodePort — additionally exposes the Service on a static port on every node's own IP, reachable from outside the cluster. Mostly used for development/testing or when there's no cloud load balancer available.
- LoadBalancer — asks the cloud provider to provision a real external load balancer pointed at the Service. This is the standard way to expose something to the public internet on a cloud-hosted cluster.
Choosing wrong isn't just a style preference — a ClusterIP Service is architecturally unreachable from outside the cluster no matter how correctly everything else is configured.
DNS: how Pods actually find a Service by name
Every Service automatically gets a DNS name inside the cluster
(<service-name>.<namespace>.svc.cluster.local, or usually just <service-name> from within
the same Namespace) — this is why application code can use a plain hostname like redis-svc
instead of an IP address at all. Kubernetes' internal DNS resolves that name to the Service's
stable virtual IP, which then routes to whichever Pods are currently healthy.
The full request path, end to end
Client -> DNS lookup "redis-svc" -> Service's stable virtual IP
-> Service consults its Endpoints (live list of matching, ready Pods)
-> traffic forwarded to one of those Pod IPs
Every one of these steps can fail independently, which is exactly why "the app can't reach redis" requires checking each layer rather than guessing — the next activity shows you what that looks like when the Endpoints layer is empty.
Instructor Notes
Approximate timing: 15 minutes read, 10-12 minutes live with the request-path diagram.
Demo plan: Before the next activity, it's worth live-running kubectl get endpoints <service-name> against a healthy Service so students see a populated Endpoints list before
they see an empty one in the demonstration.
Likely misconceptions to watch for:
- Students often think a Service "is" a load balancer process running somewhere. It's closer to
a routing rule maintained by
kube-proxyon every node — worth clarifying that there's no single "Service Pod" to go find and debug. - ClusterIP vs. NodePort vs. LoadBalancer is sometimes memorized without the "why" — the knowledge check's Service-type question is designed to test the underlying reasoning, not just recall.
Discussion question: "If a Service's selector matches zero Pods, does the Service itself fail to exist?" (Answer: no — the Service object exists fine; its Endpoints list is just empty, which looks like connection failure from the client's side without any error at the Service level itself. This is exactly the next activity's topic.)