skip to content

Kubernetes-Native Discovery

In a cluster, discovery can come straight from the Kubernetes Endpoints API instead of a separate registry. Interviewers ask whether you need Eureka at all on Kubernetes, and the expected answer is usually no.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is Kubernetes-native service discovery in Spring Cloud, and how does it differ from using Eureka?

level: juniorimportance: must knowfreq 60%

answer

  1. Cluster IS the registry
  2. Reads Service + Endpoints from kube-apiserver
  3. No self-register, no heartbeat
  4. Same DiscoveryClient SPI as Eureka
  5. Readiness probe gates instances

basics

~20 s

Spring Cloud Kubernetes provides a DiscoveryClient that looks up other services by reading Kubernetes' own Service and Endpoints records from the API server. Unlike Eureka, there is no separate registry to run and apps do not self-register.

solid answer

~40 s

Spring Cloud Kubernetes ships a DiscoveryClient implementation that treats the Kubernetes cluster itself as the service registry. Instead of running a Eureka server and having each app register/heartbeat, it queries the kube-apiserver for Service objects and their backing Endpoints, mapping each ready pod behind a Service into a ServiceInstance. So you keep the familiar Spring abstractions — DiscoveryClient.getServices(), getInstances(serviceId), and integration with Spring Cloud LoadBalancer — but the source of truth is Kubernetes, which already knows every pod's IP and readiness state. Benefits: no extra registry to operate, no registration heartbeats, and readiness probes automatically gate which instances are discoverable. You add spring-cloud-starter-kubernetes-fabric8 (or -client) and enable discovery; the same @LoadBalanced RestTemplate/WebClient or Feign code works unchanged.

code

java · 26 lines
java
// Dependency (Maven): spring-cloud-starter-kubernetes-fabric8

@SpringBootApplication
public class OrdersApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrdersApplication.class, args);
    }

    // Client-side load balanced across pods behind the 'inventory' Service
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
class InventoryGateway {
    private final RestTemplate rt;
    InventoryGateway(RestTemplate rt) { this.rt = rt; }

    String stock(String sku) {
        // 'inventory' resolves via K8s Endpoints -> a ready pod IP
        return rt.getForObject("http://inventory/stock/" + sku, String.class);
    }
}

go deeper

for a junior

Know the one-liner: Kubernetes is the registry, apps don't self-register, you read Services/Endpoints instead of running Eureka.

for a middle

Should connect it to the DiscoveryClient SPI and @LoadBalanced clients working unchanged.

for a senior

Should articulate readiness-driven membership and the DNS-vs-DiscoveryClient tradeoff.

for a principal

Should frame it as a migration/portability story and know when plain Service DNS is sufficient versus needing pod-level instance lists.

**The problem.** In a microservice system, service A needs to find where service B is running. The classic Spring Cloud Netflix answer was **Eureka**: a standalone registry server where each instance *registers* itself on startup, sends periodic *heartbeats*, and other clients *fetch* the registry to get a list of instances. That means you operate an extra server and every app carries a Eureka client. **The Kubernetes insight.** When you run on Kubernetes, the cluster *already is* a service registry. A **Service** is a stable named abstraction over a set of pods; the **Endpoints** (or **EndpointSlice**) object attached to a Service lists the actual pod IP:port pairs that are currently *ready* (passing readiness probes). Kubernetes maintains this automatically as pods start, die, or scale. So you don't need Eureka — you just ask the **kube-apiserver**. **What Spring Cloud Kubernetes does.** It provides a `DiscoveryClient` implementation (historically `KubernetesDiscoveryClient`, and in recent versions `KubernetesInformerDiscoveryClient`) that implements the standard Spring Cloud Commons `org.springframework.cloud.client.discovery.DiscoveryClient` SPI. Its methods: - `getServices()` → lists Kubernetes **Service** names (optionally filtered by labels/namespace). - `getInstances(String serviceId)` → returns `List<ServiceInstance>`, one per ready pod behind that Service, resolved from the **Endpoints** subsets. Each `ServiceInstance` exposes host (pod IP), port, and metadata (labels, annotations, ports). Because it implements the same SPI as the Eureka client, everything downstream is unchanged: **Spring Cloud LoadBalancer** consumes the instance list, and a `@LoadBalanced` `RestTemplate`/`WebClient` or **OpenFeign** client calls `http://service-b/...` and gets client-side load-balanced to a real pod. **Key differences vs Eureka:** 1. **No registration.** Apps do not self-register or heartbeat. Kubernetes tracks membership via the Endpoints controller and readiness probes. 2. **No separate server.** The registry is the kube-apiserver you already run. 3. **Readiness-driven.** Only pods that pass their readiness probe appear in Endpoints (unless you opt in to not-ready addresses). 4. **RBAC required.** The pod's ServiceAccount needs permission to read services/endpoints from the API. **When to use it.** Choose it when running on Kubernetes and you want client-side load balancing, per-instance metadata, or gradual migration of existing Spring Cloud discovery code — without operating Eureka. If you only need simple request routing, plain **Kubernetes DNS** (`http://service-b.namespace.svc.cluster.local`) via the Service's ClusterIP may be enough and needs no library at all; Spring Cloud Kubernetes discovery adds value when you want pod-level instance lists and Spring's DiscoveryClient/LoadBalancer abstractions. **Out of scope here:** ConfigMap/Secret-based configuration is a separate concern; this leaf is only about discovery.

  • If Kubernetes already gives me DNS for Services, why use the Spring DiscoveryClient at all?
    Plain Service DNS resolves to the ClusterIP and lets kube-proxy round-robin at L4, giving you one virtual endpoint. The DiscoveryClient enumerates the actual pod instances, so you can do client-side load balancing with Spring Cloud LoadBalancer, read per-instance metadata (labels/annotations), and keep existing DiscoveryClient/Feign code portable across Eureka and Kubernetes.
  • Does an app need to call an API to register itself at startup?
    No. Registration is implicit: when the pod becomes ready, Kubernetes' Endpoints controller adds it to the Service's Endpoints. Spring just reads that list. There is nothing like Eureka's register/heartbeat call.

saying these in an interview costs you the question

  • Claiming apps must self-register with a heartbeat like Eureka
  • Saying you still need to run a Eureka server alongside Kubernetes
  • Confusing it with ConfigMap/Secret configuration (different feature)

context

open as a page

How do you enable Spring Cloud Kubernetes discovery, and what is the difference between the Fabric8 and official-client starters?

level: middleimportance: should knowfreq 45%

basics

~10 s

Add one starter — spring-cloud-starter-kubernetes-fabric8 or spring-cloud-starter-kubernetes-client — which auto-configures a DiscoveryClient. Both talk to the same Kubernetes API; they just use different underlying Java clients (Fabric8's io.fabric8 client vs the official kubernetes-client/java).

open as a page

How does Spring Cloud Kubernetes turn a Service into a list of ServiceInstances, and how do readiness, ports, and metadata factor in?

level: seniorimportance: should knowfreq 40%

basics

~20 s

For a serviceId it finds the matching Kubernetes Service and reads its Endpoints. Each ready pod address in the Endpoints subsets becomes one ServiceInstance, with pod IP, chosen port, and metadata built from the Service's labels, annotations, and ports.

open as a page

What RBAC and security setup does Spring Cloud Kubernetes discovery require, and how do you minimize the permission blast radius?

level: seniorimportance: should knowfreq 35%

basics

~20 s

The pod's ServiceAccount needs read access (get/list/watch) to Kubernetes services and endpoints in the relevant namespaces. Grant it with a Role/RoleBinding (namespace-scoped) — or a ClusterRole for all-namespaces. To avoid giving every app this access, route through a Discovery Server that holds the permissions.

open as a page

How does the informer/watch-based discovery client keep its instance data fresh, and what are the scaling and staleness tradeoffs versus native Kubernetes Service DNS?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Newer versions use Kubernetes informers: a watch stream feeds a local in-memory cache of Services/Endpoints, so getInstances() is a fast cache read that updates as the cluster changes. It trades some staleness and apiserver watch load for client-side load balancing that plain Service DNS can't do.

open as a page