本文目录导读:

Spring Cloud Kubernetes 是一个开源项目,旨在让基于 Spring Cloud 的微服务能够无缝地在 Kubernetes(K8s)环境中运行,尤其是利用 Kubernetes 原生的服务发现与配置管理能力,替代传统的 Eureka 或 Consul。
下面详细介绍 Spring Cloud Kubernetes 的服务发现机制。
核心思想:用 K8s Service 取代 Eureka
在传统的 Spring Cloud 架构中,服务通过 Eureka 注册中心相互发现,在 Kubernetes 中,Kubernetes 本身就是一个强大的服务发现系统,通过 Service 资源和 kube-dns / CoreDNS 实现。
Spring Cloud Kubernetes 的服务发现模块 (spring-cloud-starter-kubernetes-discovery) 的作用就是:
- 对接 Kubernetes API Server,实时获取当前 Namespace 下的所有 Service 和 Pod 信息。
- 实现 Spring Cloud 标准的
DiscoveryClient接口(即org.springframework.cloud.client.discovery.DiscoveryClient)。 - 使得
@LoadBalanced的RestTemplate或WebClient可以直接使用http://service-name这样的 Kubernetes 内部域名进行服务调用。
工作机制与流程
sequenceDiagram
participant ServiceA as ServiceA Pod
participant K8sAPI as K8s API Server
participant K8sDNS as K8s DNS (CoreDNS)
participant ServiceB as ServiceB Pod
Note over ServiceA: 启动时,Spring Cloud K8s<br/>通过 API Server 获取所有 Service
ServiceA->>K8sAPI: GET /api/v1/namespaces/default/services/
K8sAPI-->>ServiceA: 返回 Service 列表 (endpoints)
Note over ServiceA: 更新本地 Service 缓存<br/>(service-b: 10.1.0.5:8080)
ServiceA->>ServiceA: 调用 http://service-b/api/data
Note over ServiceA: 拦截请求,解析 service-b<br/>不直接走 DNS,而是走本地缓存(LB)
ServiceA->>ServiceB: HTTP Request (10.1.0.5:8080)
ServiceB-->>ServiceA: HTTP Response
主要组件与配置
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-discovery</artifactId>
</dependency>
核心配置类
在 application.properties 或 application.yml 中:
spring:
application:
name: service-a
cloud:
kubernetes:
discovery:
# 是否启用 K8s 服务发现,默认 true
enabled: true
# 要发现的服务所在的 Namespace,默认当前 Pod 所在 Namespace
# 如果所有服务都在同一个 Namespace,通常不需要设置
# namespaces: [default, production]
all-namespaces: false
# 服务发现的轮询间隔(毫秒),默认 30000 (30秒)
cache-refresh-interval: 10000
# Pod 启动在 K8s 外部(例如本地开发),需要指定 API Server 地址
# master-url: https://kubernetes.default.svc
# config-map 和 secret 相关配置...
使用方式
服务调用代码与传统 Spring Cloud 完全一致:
@RestController
public class ConsumerController {
@Autowired
@LoadBalanced
private RestTemplate restTemplate;
@GetMapping("/call")
public String callServiceB() {
// 这里的 service-b K8s Service 的名称
String response = restTemplate.getForObject("http://service-b/api/data", String.class);
return "Response from service-b: " + response;
}
}
关键点:
- 结合了
@LoadBalanced注解后,RestTemplate会使用 Spring Cloud LoadBalancer(默认实现)进行客户端负载均衡。 - 它并不直接使用 Kubernetes 的
Service进行负载均衡(这是 kube-proxy 的工作),而是客户端侧负载均衡,直接从 Pod 的 IP:Port 直接调用,跳过了一次 kube-proxy 的转发,延迟更低。
与 K8s 原生 Service 的区别
| 特性 | Kubernetes 原生 Service (通过 kube-proxy) | Spring Cloud Kubernetes 服务发现 |
|---|---|---|
| 负载均衡位置 | 节点内核 (iptables/IPVS) | 客户端进程内 (Spring Cloud LoadBalancer) |
| 请求路径 | → Pod → Service IP → kube-proxy → Pod | → Pod → Pod (直接调用) |
| 网络开销 | 多一次 DNAT 转发 (非常小) | 无转发,直连 Pod |
| 控制粒度 | 粗粒度(只能 round-robin) | 细粒度(自定义负载均衡策略、权重、熔断等) |
| 服务列表来源 | iptables/IPVS 规则(静态) | API Server(动态拉取 + 本地缓存) |
| 适用场景 | 简单微服务,不关心客户端负载均衡 | 需要高级负载均衡、断路器、灰度发布的场景 |
常见问题与最佳实践
权限问题
Spring Cloud Kubernetes 需要读取 API Server 的资源,在 K8s 1.24+ 中,默认的 service account 权限很低,你需要创建 RBAC:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: spring-cloud-k8s-discover rules: - apiGroups: [""] resources: ["services", "endpoints", "pods"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: spring-cloud-k8s-discover-binding subjects: - kind: ServiceAccount name: default namespace: default roleRef: kind: ClusterRole name: spring-cloud-k8s-discover apiGroup: rbac.authorization.k8s.io
本地调试
在 K8s 集群外启动 Spring Boot 应用进行调试时,需要配置 K8s 连接信息:
spring:
cloud:
kubernetes:
client:
master-url: https://your-k8s-master:6443
# 或者使用 kubeconfig 文件
# kube-config-path: ~/.kube/config
discovery:
namespaces: [default]
与 ConfigMap/Secret 的配合
服务发现常与配置管理一起使用,Spring Cloud Kubernetes 还提供 spring-cloud-starter-kubernetes-config 支持从 ConfigMap 和 Secret 加载配置。
完整示例
假设有一个 order-service 和一个 user-service:
order-service 的 application.yml:
spring:
application:
name: order-service
cloud:
kubernetes:
discovery:
all-namespaces: false
cache-refresh-interval: 5000
OrderController.java:
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/services")
public List<String> getAllServices() {
// 获取所有注册的服务名
return discoveryClient.getServices();
}
@GetMapping("/users/{id}")
public String getUserById(@PathVariable Long id) {
// 调用 user-service
String response = restTemplate.getForObject(
"http://user-service/users/" + id, String.class);
return "User: " + response;
}
}
部署到 K8s 后,order-service 就会自动发现 user-service 的 Pod 列表,并进行负载均衡调用。
- Spring Cloud Kubernetes 服务发现 是 Spring Cloud 与 K8s 的桥梁,让传统微服务开发体验迁移到容器环境。
- 它不替代 K8s Service,而是基于 K8s Service 提供更高级的客户端负载均衡能力。
- 核心优势:Spring Cloud 生态的无缝集成,支持 Ribbon/LoadBalancer、Sentinel 熔断、OpenFeign 等。
- 注意事项:需要配置 RBAC 权限,并在本地开发时指定 K8s 连接信息。