Spring Cloud Kubernetes 配置观察器
Kubernetes 提供了在应用程序容器中挂载 ConfigMap 或 Secret 作为卷的功能。当 ConfigMap 或 Secret 的内容发生更改时,挂载的卷将使用这些更改进行更新。
但是,除非您重新启动应用程序,否则 Spring Boot 不会自动更新这些更改。Spring Cloud 提供了在不重新启动应用程序的情况下刷新应用程序上下文的功能,方法是点击执行器端点 /refresh
或通过使用 Spring Cloud Bus 发布 RefreshRemoteApplicationEvent
。
为了实现运行在 Kubernetes 上的 Spring Cloud 应用程序的此配置刷新,您可以将 Spring Cloud Kubernetes 配置观察器控制器部署到您的 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
这些变量在配置观察器上启用调试日志,并且在初始设置时特别有用,以便能够诊断潜在的错误配置。
env:
- name: SPRING_CLOUD_KUBERNETES_RELOAD_NAMESPACES_0
value: "namespace-a"
此变量让观察器知道在哪里搜索 secrets 和 configmaps。您有两个选项:选择性命名空间(上面的设置)和通过命名空间解析选择的命名空间(这是默认选项)。请记住,所有这些选项都需要正确的 RBAC 规则。
来自 configmaps/secrets 的更改只有在该特定更改来自具有标签:spring.cloud.kubernetes.config=true
或 spring.cloud.kubernetes.secret=true
的源时,才会触发配置观察器发出的事件。
简单来说,如果您更改了一个没有上述标签的 configmap(或 secret),配置观察器将跳过为此发出事件(如果您启用了调试日志,这将在日志中可见)。
默认情况下,配置观察器将监视已配置命名空间中的所有 configmaps/secrets。如果您想过滤以仅监视特定源,可以通过设置
SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE
这将告诉观察器仅监视具有标签:spring.cloud.kubernetes.config.informer.enabled=true
的源。
另一个重要的配置,特别是对于作为卷挂载的 configmaps 和 secrets(通过 spring.cloud.kubernetes.config.paths
/spring.cloud.kubernetes.secrets.paths
或使用 spring.config.import
)来说是
- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
value: "10000"
这指示在从配置观察器发出事件之前应等待多少毫秒。这很重要,因为 Kubernetes 文档指出
当当前在卷中使用的 ConfigMap 更新时,投影键最终也会更新。
您需要将此最终部分与集群中以毫秒为单位的值相匹配。
Spring Cloud Kubernetes 配置观察器可以通过两种方式向应用程序发送刷新通知。
-
通过 HTTP,在这种情况下,被通知的应用程序必须公开
/refresh
执行器端点,并且集群内部可以访问它 -
使用 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.1.3
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8888
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8888
path: /actuator/health/liveness
ports:
- containerPort: 8888
服务帐户和关联的角色绑定对于 Spring Cloud Kubernetes 配置正常工作非常重要。控制器需要访问 Kubernetes 集群中 ConfigMaps、Pod、服务、端点和 Secrets 的读取数据权限。
监视 ConfigMaps 和 Secrets
如果对具有有效标签(如上所述)的 ConfigMap 或 Secret 进行了更改,则 Spring Cloud Kubernetes 配置观察器将获取 ConfigMap 或 Secret 的名称,并向具有该名称的应用程序发送通知。但这对于您的用例可能还不够,例如,您可能希望
-
将一个 config-map 绑定到多个应用程序,以便单个 configmap 中的更改会触发许多服务的刷新
-
让基于配置文件的源为您的应用程序触发事件
出于这些原因,您可以指定一个附加注释
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 Discovery Client 获取与 ConfigMap 或 Secret 的名称匹配的所有应用程序实例,并向应用程序的执行器 /refresh
端点发送 HTTP POST 请求。默认情况下,它将使用发现客户端中注册的端口向 /actuator/refresh
发送 POST 请求。
非默认管理端口和执行器路径
如果应用程序使用非默认执行器路径和/或为管理端点使用不同的端口,则应用程序的 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)来启用消息传递实现。