Services & Service Networking
Stability atop ephemeral pods
Pods are ephemeral, so Services supply stable DNS + virtual IP: ClusterIP (indirect), NodePort (host-port), LoadBalancer (cloud LB), ExternalName. kube-proxy (iptables/ipvs/eBPF) wires ClusterIP; CoreDNS resolves names.
What you will learn
- Explain Service types and when each applies
- Trace kube-proxy + CoreDNS resolution to endpoints
- Use selectors and ports correctly for multi-port services
A Service = a stable label selector + a virtual IP (ClusterIP) + port mapping. kube-proxy programs the datapath (iptables/ipvs/eBPF) so ClusterIP:port → one of the Pod endpoints. CoreDNS names the service: my-svc.ns.svc.cluster.local.
What is this?
Service spec: selector → endpoints population (Endpoints object); ports (name, port, targetPort); type: ClusterIP, NodePort, LoadBalancer, ExternalName, Headless (clusterIP: None → DNS A records per pod). kube-proxy backends: iptables (default, SNAT), ipvs (scale, faster), eBPF/Cilium (offload). DNS: CoreDNS → service/cluster.local names; SRV for named ports. Service topologies/trafficPolicy, sessionAffinity for sticky, internalTrafficPolicy, plus multi-port and port names.
Why do you need it?
- A direct pod IP breaks on every reschedule — services carry the load when pods shuffle.
- DNS-based discovery lets services find each other by name, not IP archaeology.
- NodePort/LoadBalancer expose your workload without editing each pod.
- Headless services unlock StatefulSet member discovery (DB clustering) cleanly.
Mental model
A PBX switchboard: dial a fixed number, get whichever employee (whoever is free)
Service → endpoints
Customers dial the department number (ClusterIP:port); the switchboard (kube-proxy) connects to an available agent (ready Pod); the agent list (Endpoints) updates as staff change.
How it works
- You create Service → selector matches Pod labels → Endpoints controller fills pod IP:port set.
- Service' virtual IP lands in iptables/ipvs rules on every node.
- Traffic to clusterIP:port matches a rule → DNAT to a selected endpoint; conntrack returns.
- CoreDNS answers svc.ns.svc.cluster.local → ClusterIP (or per-pod A/AAAA for headless).
- LoadBalancer type asks the cloud provider to front NodePorts with an LB.
Service resolution path.
Examples
Multi-port service with named ports
apiVersion: v1kind: Servicemetadata: { name: api, namespace: prod }spec: selector: { app: api } ports: - name: http port: 80 targetPort: 8080 - name: metrics port: 9090 targetPort: 9090 type: ClusterIPTwo named ports expose HTTP and scraping; DNS name api.prod.svc.cluster.local routes to ready pods.
In production
- Front Service → Deployment (ClusterIP) fronted by an Ingress.
- DB read replicas behind a headless Service for client-side discovery.
- Standalone metrics Service scraped by Prometheus; NodePort only in legacy-onprem.
Best practices
- Name ports; never rely on positional port numbers.
- Let readiness decide membership — the Endpoints list is only as good as your probes.
- Prefer ClusterIP + Ingress/LB over NodePort spread.
- For StatefulSets, headless Services + stable DNS unlock member-to-member clustering.
- Set serviceAccount and network policies to bound cross-namespace reach.
Common mistakes
- Selector mismatches → empty Endpoints → the service has no backends
- targetPort pointing at the container's listen-but-not-route port.
- kube-proxy iptables vs ipvs perf assumptions — measure big clusters.
- Using NodePort for internal traffic and leaking host ports.
Debugging tips
- kubectl get endpoints <svc> first — if empty, the selector is the bug.
- Resolve the name: kubectl run --rm -it curl -- /bin/sh; nslookup api.prod.svc.cluster.local.
- From a pod, curl <svc>.<ns>.svc.cluster.local — not the raw ClusterIP you memorized.
- Check multiport: a curl to port 80 mapping wrong targetPort is a top reset offender.
Interview checkpoint
Hands-on lab
- Expose a Deployment via a Service
- Verify endpoint population and DNS resolution
- Hit the service across pods
Wire a Service and Resolve It by DNS
30 min · beginner
Quick quiz
Service with no matching labels →
Headless Service (clusterIP: None) primarily enables: