skip to content

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%

answer

  1. Two starters: -fabric8 vs -client
  2. Fabric8 = io.fabric8 client; -client = official client-java
  3. One starter only, auto-config registers DiscoveryClient
  4. spring.cloud.kubernetes.discovery.enabled
  5. Discovery Server = centralize RBAC over HTTP

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).

solid answer

~40 s

You pick one of two starter families. spring-cloud-starter-kubernetes-fabric8 uses the io.fabric8 Kubernetes client; spring-cloud-starter-kubernetes-client uses the official kubernetes-client/java. Adding the starter auto-configures a KubernetesDiscoveryClient (in newer releases an informer-based one) so DiscoveryClient and @LoadBalanced clients just work. @EnableDiscoveryClient is largely optional because auto-config activates it, but you can gate it with spring.cloud.kubernetes.discovery.enabled=true/false. Functionally the two clients are equivalent for discovery; the choice is about dependency footprint, existing usage, and which client your team standardizes on. The official-client family also pairs with a separate Discovery Server (HTTP) deployment so app pods don't each need cluster-wide RBAC. Both read Service/Endpoints from the API and require the pod's ServiceAccount to have list/watch/get on those resources.

code

java · 26 lines
java
// pom.xml — pick ONE:
// <dependency>
//   <groupId>org.springframework.cloud</groupId>
//   <artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
// </dependency>
// -- or --
// <dependency>
//   <groupId>org.springframework.cloud</groupId>
//   <artifactId>spring-cloud-starter-kubernetes-client</artifactId>
// </dependency>

@SpringBootApplication
@EnableDiscoveryClient // explicit intent; auto-config often enables it anyway
public class GatewayApp {
    public static void main(String[] args) { SpringApplication.run(GatewayApp.class, args); }
}

// application.yml
// spring:
//   cloud:
//     kubernetes:
//       discovery:
//         enabled: true
//         all-namespaces: false
//         service-labels:
//           tier: backend

go deeper

for a junior

Know that you add one starter and the DiscoveryClient appears; details of client choice can be fuzzy.

for a middle

Should name both starter families, know they share the SPI, and toggle via spring.cloud.kubernetes.discovery.enabled.

for a senior

Should discuss namespace scoping, label filters, and the Discovery Server RBAC-centralization tradeoff.

for a principal

Should reason about API-server watch load, permission blast radius, and standardizing one client stack org-wide.

**The two client stacks.** Spring Cloud Kubernetes must talk to the kube-apiserver over its REST API. There are two mature Java clients for that, and Spring Cloud offers a starter for each: 1. **Fabric8** — `org.springframework.cloud:spring-cloud-starter-kubernetes-fabric8` (and `...-fabric8-all` bundling config + discovery + LoadBalancer). Uses the popular `io.fabric8:kubernetes-client`. Historically the original and most battle-tested option in this project. 2. **Official Kubernetes Java client** — `org.springframework.cloud:spring-cloud-starter-kubernetes-client` (and `...-client-all`). Uses `io.kubernetes:client-java`, the CNCF-official generated client. Both ultimately implement the same Spring Cloud Commons `DiscoveryClient` SPI, expose the same `getServices()`/`getInstances()` behavior, and integrate identically with **Spring Cloud LoadBalancer**. You should include **exactly one** to avoid conflicting auto-configuration. **Enabling.** Adding a starter triggers auto-configuration that registers the discovery client bean. `@EnableDiscoveryClient` on your `@SpringBootApplication` is the explicit, portable way to signal intent, but with Spring Cloud Kubernetes on the classpath discovery is typically active by default. You control it via properties: - `spring.cloud.kubernetes.discovery.enabled=true|false` - `spring.cloud.kubernetes.discovery.all-namespaces=true` — discover across all namespaces (default is the pod's own namespace). - `spring.cloud.kubernetes.discovery.service-labels.*` — filter which Services are visible. - `spring.cloud.kubernetes.discovery.include-not-ready-addresses=true` — also surface not-ready pods (rare; usually undesirable). - `spring.cloud.kubernetes.discovery.primary-port-name` — which named port to use when a Service exposes several. **Discovery Server (HTTP mode).** A concern with putting a discovery client in every app is that each pod's ServiceAccount then needs RBAC to list/watch Services and Endpoints cluster-wide. Spring Cloud Kubernetes offers a standalone **Spring Cloud Kubernetes Discovery Server** — one deployment that holds the RBAC and exposes discovery over HTTP; app pods use a lightweight `DiscoveryClient` that calls that server instead of the kube-apiserver directly. Property: `spring.cloud.kubernetes.discovery.discovery-server-url`. This centralizes permissions and reduces API-server watch load. **Which to choose?** - If your team already uses the Fabric8 client elsewhere, or you want the `-all` convenience bundle, pick Fabric8. - If you standardize on the CNCF official client or want the Discovery Server topology, the `-client` family is the natural fit. - For pure discovery behavior, they are interchangeable; the decision is ecosystem/dependency alignment, not capability. **Gotcha:** don't mix both starters; and remember that neither works without the RBAC grant on the pod's ServiceAccount.

  • What happens if you accidentally include both the fabric8 and client starters?
    You get two competing DiscoveryClient auto-configurations and bean/classpath conflicts; discovery may fail to start or behave unpredictably. Include exactly one client stack per app.
  • Why might a platform team prefer the Discovery Server over embedding a client in every app?
    It concentrates the cluster-wide RBAC (list/watch services and endpoints) into one deployment instead of granting it to every app's ServiceAccount, and reduces the number of watch connections to the kube-apiserver, which matters at scale.

saying these in an interview costs you the question

  • Thinking Fabric8 and official client produce different discovery semantics
  • Including both starters at once
  • Believing @EnableDiscoveryClient is strictly mandatory
  • Forgetting RBAC is still required regardless of client choice

context