Lesson 5 · Workloads, config & networking

Services & cluster DNS

A stable name in front of ever-changing Pods — so nothing ever chases a Pod IP.

Your win: explain why Services exist, the four types (ClusterIP / NodePort / LoadBalancer / headless), and how in-cluster DNS lets one service reach another by name.

The problem Services solve

Lesson 3 and 4 left you with a fact: Pods are ephemeral, and their IPs change every time a ReplicaSet replaces one. So you can never hard-code a Pod IP. A Service is the fix: a stable name and virtual IP that fronts a dynamic set of Pods, chosen by label selector. Pods come and go behind it; the Service address never changes, and it load-balances across whichever Pods are currently ready.1

Selector + readiness = the magic A Service selects Pods by label (app: bob) and routes only to the ones passing their readiness probe (Lesson 8). That's how a rolling update (Lesson 4) stays seamless: a new Pod joins the Service's pool only once it's ready, and a terminating Pod is removed from the pool first. The Service is the moving target's stable handle.

The four Service types

TypeReachable fromUse
ClusterIP (default)inside the cluster onlyservice-to-service — the norm
NodePorta fixed port on every nodesimple external access / dev
LoadBalanceran external IP (cloud LB)expose to the internet
headless (clusterIP: None)DNS returns Pod IPs directlystable per-Pod addressing (StatefulSets, L7)

Cluster DNS — reach a service by name

Kubernetes runs an in-cluster DNS. Every Service gets a name: <service>.<namespace>.svc.cluster.local, and within the same namespace you can use just <service>.2 This is the exact idea you already know from Course 1 — Docker Compose let containers reach each other by service name on a shared network — scaled to the whole cluster.

Anchor — every service here is a ClusterIP Service The library chart generates one Service per app from deployments/helm/libs/util/templates/_service.tpl:4, and type: ClusterIP is hard-coded at line 12 — with named http and grpc ports (:14-25). So all ~25 backend services talk to each other over ClusterIP + cluster DNS, never Pod IPs. The only LoadBalancer in the backend is backend/zeus/templates/lb_service.yaml:13 (a static IP for sftpgo); there are no NodePorts. External traffic doesn't come in through Services at all here — it enters via the Istio ingress gateway (Course 4), which routes to these ClusterIP Services.
A twist you'll revisit in Lesson 7 Normally a StatefulSet pairs with a headless Service for stable per-Pod DNS. This repo doesn't do that — tom and conversationmgmt reuse the normal ClusterIP Service (its serviceName points there). Worth noting now; it makes sense once you see why in Lesson 7.
Read this next

Kubernetes docs — Service & DNS

Service types, selectors and endpoints, and how DNS names resolve for Services and Pods.

kubernetes.io — Service
kubernetes.io — DNS for Services and Pods

Check yourself (from memory)

Q1. A Service is needed because Pods…

A Service gives a stable name/VIP in front of a shifting set of Pods, selected by label and gated on readiness.

Q2. The default Service type, reachable only inside the cluster, is…

ClusterIP is the default and the repo's norm; LoadBalancer is external (only zeus), NodePort exposes a node port (none here).

Q3. Service bob in namespace ns resolves in-cluster as…

service.namespace.svc.cluster.local; same namespace can shorten to just bob. Cluster DNS resolves it.
Why Services, the four types, and how cluster DNS works.
recall, then click to reveal
A SERVICE = a stable name + virtual IP fronting a dynamic set of Pods (chosen by LABEL SELECTOR), load-balancing only to READY pods — the fix for ephemeral Pod IPs. TYPES: CLUSTERIP (in-cluster, default), NODEPORT (port on every node), LOADBALANCER (external IP), HEADLESS (clusterIP: None → DNS returns Pod IPs, for StatefulSets). CLUSTER DNS: reach a service at service.namespace.svc.cluster.local (or just service in-namespace) — like Course 1's Docker service-name resolution, cluster-wide. Repo: every service is a ClusterIP from _service.tpl:4 (type hard-coded :12); only zeus is a LoadBalancer; no NodePorts; external traffic enters via Istio (Course 4), not Services.
Want to see how Endpoints track ready Pods, or how kube-proxy actually routes a ClusterIP? Ask me.

1. Kubernetes — Service.

2. Kubernetes — DNS for Services and Pods.