Service Discovery Lab (Interactive)
Crash pods, roll deploys, and lose registry quorum — then send 100 calls through client-side or kube-proxy routing. Model heartbeat registration, eviction after three missed beats, ephemeral pod IPs, and the stale-view failure window for both discovery patterns.
Service Discovery: Client-Side vs Server-Side
Pods are ephemeral with rotating IPs. Crash one, roll a deploy, or kill the registry — then send 100 calls.
Service Registry (Raft)
10.244.1.4
10.244.2.9
kube-proxy IPVS rules
10.244.1.4
10.244.2.9
Virtual IP 10.96.0.1, DNS: order-service.default
LAST CALL RESULTS
› Try: “Crash pod-b”, then immediately “Send 100 calls”, then tick heartbeats until eviction and retry.
Pattern anatomy
Client-side: Service A queries registry → gets [IPs] → runs local Round Robin → dials target directly. Zero LB hops; per-language SDK burden.
Server-side: Client calls static DNS name → kube-proxy/Envoy forwards to a healthy pod. Language-agnostic; +1 hop (~0.3ms).
How It Works Under the Hood
Container pods are ephemeral: every restart or autoscale hands a service a new private IP, so hardcoding addresses guarantees breakage. A distributed Service Registry (Consul, etcd, Eureka) keeps a live directory fed by self-registration heartbeats every 5 seconds, evicting instances after three missed beats under Raft-consistent views. Client-side discovery hands the caller the IP list and lets an SDK load-balance directly — zero extra hops but per-language coupling; server-side discovery gives a static DNS name or VIP and lets kube-proxy/EndpointSlice rules forward to healthy pods — language-agnostic at the cost of one hop. When the registry loses quorum, client lookups fail while kube-proxy keeps routing from cached rules.
Core Architectural Principles
- Self-registration heartbeats every 5s; registry evicts after 3 missed beats — a up-to-15s stale-view window.
- Client-side: SDK queries registry, load-balances locally, calls pod IPs directly (fast, polyglot burden).
- Server-side: CoreDNS name or VIP + kube-proxy/EndpointSlice rules route to healthy pods (portable, +1 hop).
Frame the problem first — ephemeral pod IPs make static config impossible — then name both patterns with products: Eureka/Ribbon client-side versus Kubernetes Service server-side via CoreDNS and iptables/IPVS. Credit the resilience detail: kube-proxy routes from cached rules even if the control plane loses quorum.
Client-side skips the proxy hop for lowest latency; server-side trades a sub-millisecond hop for language-agnostic simplicity and outage-tolerant routing.