跳到主要内容
版本:5.0.1

Spring Cloud Kubernetes 配置监视器

DeepSeek V3 中英对照 Spring Cloud Kubernetes Configuration Watcher

Kubernetes 提供了将 ConfigMap 或 Secret 挂载为卷到应用程序容器中的能力。当 ConfigMap 或 Secret 的内容发生变化时,已挂载的卷将自动更新以反映这些更改。

然而,除非重启应用,否则Spring Boot不会自动更新这些变更。Spring Cloud提供了无需重启应用即可刷新应用上下文的能力,这可以通过访问执行器端点 /refresh 或通过Spring Cloud Bus发布 RefreshRemoteApplicationEvent 事件来实现。

要实现运行在Kubernetes上的Spring Cloud应用程序的配置刷新,您可以将Spring Cloud Kubernetes配置监视器控制器部署到您的Kubernetes集群中。

你可以从 GitHub 上的源代码 构建一个 Docker 镜像,并用它来部署到 Kubernetes。

另一种配置方式是在用于部署配置监视器的 deployment.yaml 中提供一些环境变量。以下是一些重要的环境变量:

env:
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CONFIGURATION_WATCHER
value: DEBUG
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD
value: DEBUG

这些选项用于启用配置监视器的调试日志记录,在初始设置阶段尤其有用,能够帮助诊断潜在的配置错误。

env:
- name: SPRING_CLOUD_KUBERNETES_RELOAD_NAMESPACES_0
value: "namespace-a"

这个选项让 watcher 知道在哪里搜索 secrets 和 configmaps。这里你有两个选择:选择性命名空间(上面的设置)和通过命名空间解析选择的命名空间(这是默认选项)。请记住,所有这些选项都需要适当的 RBAC 规则。

只有当特定变更来自带有标签 spring.cloud.kubernetes.config=true 或 spring.cloud.kubernetes.secret=true 的源时,配置映射/机密的更改才会触发配置监视器发出事件。

简单来说,如果你更改了一个没有上述标签的配置映射(或密钥),配置监视器将跳过为其触发事件(如果你启用了调试日志记录,这将在日志中可见)。

默认情况下,配置监视器会监控配置命名空间中的所有 ConfigMap 和 Secret。如果您希望筛选仅监视特定来源,可以通过设置以下内容实现:

SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE

这将告诉监视器只监控那些带有标签 spring.cloud.kubernetes.config.informer.enabled=true 的配置源。

另一个重要的配置,特别是对于通过 spring.config.import 挂载为卷的 ConfigMap 和 Secret 来说,是:

- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
value: "10000"

这表示在配置监视器触发事件之前,我们应该等待多少毫秒。这一点很重要,因为 Kubernetes 文档中提到:

当一个当前在卷中使用的 ConfigMap 被更新时,其投射的键最终也会被更新。

你需要将这个 eventually 部分与集群中对应的毫秒值进行“匹配”。

Spring Cloud Kubernetes Configuration Watcher 可以通过两种方式向应用程序发送刷新通知。

  1. 通过 HTTP 方式,在这种情况下,被通知的应用程序必须暴露 /refresh 执行器端点,并确保该端点可在集群内访问。

  2. 使用 Spring Cloud Bus,在这种情况下,您需要在集群中部署消息代理,以供应用程序使用。

部署 YAML​

以下是您可用于将 Kubernetes 配置监视器部署到 Kubernetes 的示例部署 YAML。

---
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Service
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
name: spring-cloud-kubernetes-configuration-watcher
spec:
ports:
- name: http
port: 8888
targetPort: 8888
selector:
app: spring-cloud-kubernetes-configuration-watcher
type: ClusterIP
- apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
name: spring-cloud-kubernetes-configuration-watcher
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
name: spring-cloud-kubernetes-configuration-watcher:view
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: namespace-reader
subjects:
- kind: ServiceAccount
name: spring-cloud-kubernetes-configuration-watcher
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: namespace-reader
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
verbs: ["get", "list", "watch"]
- apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-configuration-watcher-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-configuration-watcher
template:
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
spec:
serviceAccount: spring-cloud-kubernetes-configuration-watcher
containers:
- name: spring-cloud-kubernetes-configuration-watcher
image: springcloud/spring-cloud-kubernetes-configuration-watcher:5.0.1
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8888
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8888
path: /actuator/health/liveness
ports:
- containerPort: 8888

Service Account 和相关的 Role Binding 对于 Spring Cloud Kubernetes Configuration 的正常工作至关重要。控制器需要访问权限来读取 Kubernetes 集群中关于 ConfigMaps、Pods、Services、Endpoints 和 Secrets 的数据。

监控 ConfigMap 和 Secret​

如果对具有有效标签(如上所述)的 ConfigMap 或 Secret 进行了更改,那么 Spring Cloud Kubernetes Configuration Watcher 将获取该 ConfigMap 或 Secret 的名称,并向具有该名称的应用程序发送通知。然而,这可能不足以满足您的使用场景,例如,您可能希望:

  • 将配置映射绑定到多个应用程序,这样单个配置映射内的更改会触发多个服务的刷新

  • 让基于配置文件的源为您的应用程序触发事件

因此,您可以指定一个额外的注解:

spring.cloud.kubernetes.configmap.apps 或 spring.cloud.kubernetes.secret.apps。它接受一个以逗号分隔的应用程序名称字符串,用于指定当此 Secret 或 ConfigMap 发生变更时将收到通知的应用程序名称。

例如:

kind: ConfigMap
apiVersion: v1
metadata:
name: example-configmap
labels:
spring.cloud.kubernetes.config: "true"
annotations:
spring.cloud.kubernetes.configmap.apps: "app-a, app-b"

HTTP 实现​

HTTP 实现是默认使用的实现方式。当使用此实现时,Spring Cloud Kubernetes 配置监视器检测到 ConfigMap 或 Secret 发生变更后,HTTP 实现将使用 Spring Cloud Kubernetes 发现客户端来获取与 ConfigMap 或 Secret 名称匹配的应用程序的所有实例,并向该应用程序的执行器 /refresh 端点发送 HTTP POST 请求。默认情况下,它将使用在发现客户端中注册的端口向 /actuator/refresh 发送 POST 请求。

你也可以配置配置监视器来调用实例的 shutdown 执行器端点。为此,你可以设置 spring.cloud.kubernetes.configuration.watcher.refresh-strategy=shutdown。

非默认管理端口和执行器路径​

如果应用程序使用了非默认的执行器路径和/或为管理端点使用了不同的端口,应用程序的Kubernetes服务可以添加一个名为 boot.spring.io/actuator 的注解,并将其值设置为应用程序使用的路径和端口。例如

apiVersion: v1
kind: Service
metadata:
labels:
app: config-map-demo
name: config-map-demo
annotations:
boot.spring.io/actuator: http://:9090/myactuator/home
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: config-map-demo

另一种配置执行器路径和/或管理端口的方式是设置 spring.cloud.kubernetes.configuration.watcher.actuatorPath 和 spring.cloud.kubernetes.configuration.watcher.actuatorPort。

消息传递实现​

通过将 Spring Cloud Kubernetes 配置监视器应用程序部署到 Kubernetes 时,将配置文件设置为 bus-amqp(RabbitMQ)或 bus-kafka(Kafka),可以启用消息传递实现。默认情况下,当使用消息传递实现时,配置监视器将通过 Spring Cloud Bus 向所有应用程序实例发送 RefreshRemoteApplicationEvent。这将导致应用程序实例在不重启的情况下刷新应用程序的配置属性。

你也可以配置该设置以关闭应用程序实例,从而刷新应用程序的配置属性。当应用程序关闭时,Kubernetes 将重新启动应用程序实例,新的配置属性将被加载。要使用此策略,请设置 spring.cloud.kubernetes.configuration.watcher.refresh-strategy=shutdown。

配置 RabbitMQ​

当启用 bus-amqp 配置文件时,你需要配置 Spring RabbitMQ,使其指向你想要使用的 RabbitMQ 实例的位置,以及进行身份验证所需的任何凭据。这可以通过设置标准的 Spring RabbitMQ 属性来完成,例如

spring:
rabbitmq:
username: user
password: password
host: rabbitmq

配置 Kafka​

当启用 bus-kafka 配置文件时,你需要配置 Spring Kafka 以指向你想要使用的 Kafka Broker 实例的位置。这可以通过设置标准的 Spring Kafka 属性来完成,例如

spring:
kafka:
producer:
bootstrap-servers: localhost:9092