1. Endpoints 里有 IP,说明就绪探针通过
学完这篇,你能拿到一套可落地的判断标准:什么团队先用 Spring Cloud、什么时候把治理下沉到 Kubernetes、以及两者混用时具体怎么配。文章不讲概念史,只讲选型依据和配置入口。
第一步:先认清两者管的不是同一层
Spring Cloud 解决的是「Java 应用之间怎么找到彼此、怎么调、调挂了怎么办」——注册发现、负载均衡、网关、熔断、分布式事务。它是应用层框架,代码跑在 JVM 里。
Kubernetes 解决的是「容器怎么调度、怎么扩缩容、怎么滚动发布、怎么自愈」。它是基础设施层,跑在容器外,不关心你用什么语言写业务。
所以这不是二选一,而是「哪些职责交给谁」。
注意:最常见的翻车是两边都做服务发现——Nacos 注册一遍,K8s Service 又注册一遍,流量分裂,实例互相调到对方集群。开工前就要定死:注册发现只留一个权威来源。
第二步:用四个问题判断路线
- 服务数量在 10 个以内、团队没有专职运维?→ 纯 Spring Cloud,别碰 K8s。
- 已经有一套跑得稳的 K8s 集群和 CI/CD?→ 基础设施全交给 K8s。
- 需要灰度发布、多环境隔离、按 CPU 自动扩容?→ K8s 做底座。
- 需要熔断降级、分布式事务、复杂网关鉴权?→ Spring Cloud 保留这些能力。
服务数超过 30 个、多团队并行开发时,答案基本都是混合路线:K8s 管生命周期,Spring Cloud 管业务治理。
第三步:纯 Spring Cloud 路线怎么起
依赖只引一个起步包:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
`application.yml` 里指定注册中心:
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 192.168.1.10:8848
Nacos 单机启动 `sh startup.sh -m standalone`;生产必须三节点集群 + MySQL 持久化,否则注册表丢了整个系统失联。
服务间调用用 OpenFeign,直接写服务名:
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/api/user/{id}")
UserDTO get(@PathVariable Long id);
}
熔断降级交给 Sentinel,控制台 `java -jar sentinel-dashboard.jar`,默认端口 8080。
注意:Nacos 的 `server-addr` 别写域名解析不稳定的地址,容器里 DNS 抖动会导致实例被误判下线,出现周期性 503。
第四步:纯 Kubernetes 路线怎么起
镜像别手写 Dockerfile,用 Jib 直接构建:
mvn com.google.cloud.tools:jib-maven-plugin:3.4.0:build \
-Dimage=registry.local/order-service:v1
Deployment 里三个关键点——资源限制、就绪探针、存活探针:
containers:
- name: app
image: registry.local/order-service:v1
resources:
limits: { memory: "1Gi", cpu: "1000m" }
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
initialDelaySeconds: 20
livenessProbe:
httpGet: { path: /actuator/health/liveness, port: 8080 }
initialDelaySeconds: 60
对应打开 Spring Boot 的探针端点:
management:
endpoint:
health:
probes:
enabled: true
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
服务间调用直接用 Service DNS,不再需要注册中心客户端:`http://user-service.default.svc.cluster.local:8080`。
注意:JVM 参数别写死 `-Xmx512m`,容器被 `limits` 限制时要用 `-XX:MaxRAMPercentage=75.0`。堆内存按物理机算会导致 Pod 被 OOMKilled,日志里只看到 exit code 137,排查半天。
第五步:推荐的混合配置
K8s 负责发布、扩缩容、自愈、服务注册;Spring Cloud 只保留声明式调用、网关、熔断、事务。引入 K8s 的服务发现客户端:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-client-discovery</artifactId>
</dependency>
配置里关掉 Nacos 发现,改用 K8s:
spring:
cloud:
nacos:
discovery:
enabled: false
kubernetes:
discovery:
all-namespaces: false
`@FeignClient(name = "user-service")` 不用改,底层会解析成 K8s Service 的 Endpoints,只有 readiness 通过的 Pod 才会拿到流量。
第六步:上线前跑三条验证命令
kubectl get endpoints user-service
# 2. 滚动发布状态
kubectl rollout status deployment/order-service
# 3. 观察自动扩缩容是否生效
kubectl get hpa -w
三条都正常,再挂网关做一次全链路压测。
小结
- 两者不是竞品,是不同层:Spring Cloud 管应用内部治理,K8s 管容器生命周期。
- 服务少于 10 个、没有 K8s 运维,先上 Spring Cloud,别过度设计。
- 注册发现只能有一个权威来源,双注册是最高频事故。
- 容器里用 `MaxRAMPercentage` 而不是 `-Xmx`,探针用 `/actuator/health/liveness` 和 `readiness`。
- 混合路线的落点是:K8s 出服务发现,Spring Cloud 出 Feign、Gateway、Sentinel。
转载请注明出处,版权归原作者所有。
星耀SVIP
管理员
黑卡会员





