跳到主要内容

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 Configuration Watcher 控制器部署到你的 Kubernetes 集群中。

该应用程序以容器形式发布,并在 Docker Hub 上可用。然而,如果您需要自定义配置监视器的行为,或者更倾向于自行构建镜像,您可以轻松地从 GitHub 上的源代码 构建自己的镜像并使用它。

另一个配置选项是在用于部署配置监视器的 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
none

这些选项启用了配置监视器的调试日志记录,在初始设置时特别有用,能够帮助诊断可能的错误配置。

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

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

来自 configmaps/secrets 的更改只有在特定更改来自具有标签 spring.cloud.kubernetes.config=truespring.cloud.kubernetes.secret=true 的源时,才会触发配置监视器发出事件。

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

默认情况下,配置监视器会监控配置的命名空间中的所有 ConfigMap 和 Secret。如果你想过滤只监视特定的来源,可以通过以下设置来实现:

SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE
none

这将告诉 watcher 只监控带有标签 spring.cloud.kubernetes.config.informer.enabled=true 的源。

另一个重要的配置,特别是对于作为卷挂载的 ConfigMap 和 Secret(通过 spring.cloud.kubernetes.config.paths/spring.cloud.kubernetes.secrets.paths 或使用 spring.config.import)是:

- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
value: "10000"
none

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

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

你需要在集群中将这个 最终 部分与以毫秒为单位的值进行匹配。

Spring Cloud Kubernetes 配置监视器可以通过两种方式向应用程序发送刷新通知。

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

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

部署 YAML

以下是一个示例部署 YAML,您可以使用它将 Kubernetes 配置观察器部署到 Kubernetes 中。

---
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:3.2.0
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8888
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8888
path: /actuator/health/liveness
ports:
- containerPort: 8888
yaml

Service Account 和相关的 Role Binding 对于 Spring Cloud Kubernetes 配置的正常工作非常重要。控制器需要访问 Kubernetes 集群中的 ConfigMaps、Pods、Services、Endpoints 和 Secrets 的数据。

监控 ConfigMaps 和 Secrets

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

  • 将配置映射绑定到多个应用程序,以便单个配置映射中的更改触发多个服务的刷新

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

出于这些原因,您可以指定一个额外的注解:

spring.cloud.kubernetes.configmap.appsspring.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"
yaml

HTTP 实现

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

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

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

如果应用程序使用了非默认的 Actuator 路径和/或为管理端点使用了不同的端口,应用程序的 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
yaml

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

消息传递实现

通过将 Spring Cloud Kubernetes Configuration Watcher 应用程序部署到 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
yaml

配置 Kafka

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

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