bigywater.tech
Spring · 133

Spring Cloud Kubernetes:服务发现与 ConfigMap 刷新

Spring Cloud Kubernetes 的服务发现和配置在本地为什么什么都读不到?ConfigMap 要不要写 import?ConfigMap 改了之后多久生效?为什么开了 reload 还是不刷新?这篇在本机 kind 集群里用真实的 Deployment、Service 和 ConfigMap 逐项验证。

静默不生效
应用不在 Kubernetes 上时,服务发现返回空、ConfigMap 不被读取,不会有任何报错
0.2 秒
reload.enabled=true 并带 actuator 时,ConfigMap 改动被应用看到的耗时
没有 actuator
开了 reload 却没有 actuator 依赖,20 秒内没有任何变化

服务发现

实测 · 本机执行输出
  应用跑在集群外面(宿主机),只有 kubeconfig:getServices() = [],getInstances("web") = [],配置:greeting=local-greeting,local.only=yes,shared.key=null;app.msg:@RefreshScope=local-msg,普通单例=local-msg,@ConfigurationProperties=local-msg
  加上 spring.main.cloud-platform=kubernetes(强制当作跑在 Kubernetes 上):
  DiscoveryClient.getServices() = [web]
  getInstances("web") = [10.244.0.10:80|metadata键=[app, k8s_namespace, kubectl.kubernetes.io/last-applied-configuration, port.<unset>, type],k8s_namespace=x133,type=ClusterIP, 10.244.0.6:80|metadata键=[app, k8s_namespace, kubectl.kubernetes.io/last-applied-configuration, port.<unset>, type],k8s_namespace=x133,type=ClusterIP]
  kubectl 看到的 Service web 的 Endpoints = 10.244.0.10 10.244.0.6

需要识别为 Kubernetes 平台;实例来自 Endpoints,metadata 带 Service 的标签与注解。

副本变化

实测 · 本机执行输出
  扩到 3 个副本:1.0 秒后 getInstances 返回 3 个
  缩到 1 个副本:0.2 秒后 getInstances 返回 1 个

1 秒内可见。

ConfigMap

实测 · 本机执行输出
  ConfigMap orders(application.properties: greeting=k8s-greeting、shared.key=from-cm、app.msg=k8s-v1):configmap/orders unchanged
  没有写 spring.config.import:启动成功,greeting=local-greeting,local.only=yes,shared.key=null;app.msg:@RefreshScope=local-msg,普通单例=local-msg,@ConfigurationProperties=local-msg
  spring.config.import=optional:kubernetes::greeting=k8s-greeting,local.only=yes,shared.key=from-cm;app.msg:@RefreshScope=k8s-v1,普通单例=k8s-v1,@ConfigurationProperties=k8s-v1

要写 spring.config.import=kubernetes:;不写则被悄悄忽略。

热加载

实测 · 本机执行输出
  默认(没开 reload),改成 k8s-v2 后等 10 秒:greeting=k8s-greeting,local.only=yes,shared.key=from-cm;app.msg:@RefreshScope=k8s-v1,普通单例=k8s-v1,@ConfigurationProperties=k8s-v1
  开启 reload.enabled=true,没有 actuator 依赖:改成 k8s-v3 之后 20 秒内没有看到变化:greeting=k8s-greeting,local.only=yes,shared.key=from-cm;app.msg:@RefreshScope=k8s-v1,普通单例=k8s-v1,@ConfigurationProperties=k8s-v1
  开启 reload.enabled=true,加上 spring-boot-starter-actuator:改成 k8s-v3 之后 0.2 秒看到变化:greeting=k8s-greeting,local.only=yes,shared.key=from-cm;app.msg:@RefreshScope=k8s-v3,普通单例=k8s-v1,@ConfigurationProperties=k8s-v3

reload.enabled=true 加 actuator 依赖,约 0.2 秒生效。

分步演示

Spring Cloud Kubernetes
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。Kubernetes 是本机 Docker Desktop 里用 kind 起的单节点集群(kindest/node v1.37.0),命名空间 x133;Spring 应用跑在宿主机上用 kubeconfig(管理员权限)访问集群,所以没有验证 ServiceAccount 与 RBAC;Pod 里的 nginx 实例 IP 在宿主机上不可直接访问,只读取发现结果
    • 没有验证:应用真正跑在 Pod 里时的 ServiceAccount 与 RBAC 权限(Role 需要哪些 get / list / watch);EndpointSlice 的使用(discovery.k8s.io/v1);Secrets 作为配置源;spring.cloud.kubernetes.config.sources 多个 ConfigMap 的优先级;polling 模式的 reload(我试过 polling 在没有 actuator 时同样不生效);reload 的 restart_context / shutdown 策略;多命名空间发现;Kubernetes 发现自身的缓存时长;服务发现与 Kubernetes 原生 Service DNS 的取舍
    京ICP备2026067502号-1京公网安备11010502063487号