Spring Cloud Kubernetes Configuration Watcher
Kubernetes 提供了在您应用程序的容器中 mount a ConfigMap or Secret as a volume 的能力。当 ConfigMap 或 Secret 的内容更改时, mounted volume will be updated with those changes。
Kubernetes provides the ability to mount a ConfigMap or Secret as a volume in the container of your application. When the contents of the ConfigMap or Secret changes, the mounted volume will be updated with those changes.
然而,在您重启应用程序之前,Spring Boot 不会自动更新这些更改。Spring Cloud 提供通过点击 actuator 端点 /refresh
或通过使用 Spring Cloud Bus 发布`RefreshRemoteApplicationEvent` 来刷新应用程序上下文而不重启应用程序的能力。
However, Spring Boot will not automatically update those changes unless you restart the application. Spring Cloud
provides the ability refresh the application context without restarting the application by either hitting the
actuator endpoint /refresh
or via publishing a RefreshRemoteApplicationEvent
using Spring Cloud Bus.
若要在 Kubernetes 上运行的 Spring Cloud 应用程序中实现此配置刷新,您可以向 Kubernetes 集群中部署 Spring Cloud Kubernetes Configuration Watcher 控制器。
To achieve this configuration refresh of a Spring Cloud app running on Kubernetes, you can deploy the Spring Cloud Kubernetes Configuration Watcher controller into your Kubernetes cluster.
该应用程序发布为一个容器,并且在 Docker Hub 中可用。但是,如果您需要自定义配置监视程序行为或希望自己构建该映像,那么您可以轻松地从 source code on GitHub 构建自己的映像并使用该映像。
The application is published as a container and is available on Docker Hub. However, if you need to customize the config watcher behavior or prefer to build the image yourself you can easily build your own image from the source code on GitHub and use that.
配置它的另一个选择是在用于部署配置 watcher 的 deployment.yaml 中提供一些环境变量。以下是其中一些重要的变量:
Another option to configure it is to provide some environment variables in the deployment.yaml used to deploy configuration watcher. Here are some important ones:
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
这些变量将启用配置 watcher 上的调试日志记录,并且在初始设置中特别有用,以便诊断潜在的错误配置。
These enable debug logging on the configuration watcher and are particular useful on the initial set-up, to be able to diagnose potential miss-configurations.
env:
- name: SPRING_CLOUD_KUBERNETES_RELOAD_NAMESPACES_0
value: "namespace-a"
这一选项让监视程序知道到哪里查找秘密和 ConfigMap。您在此处有两个选项:选择性命名空间(上面的设置)和由 Namespace Resolution 选择的命名空间(这是默认选项)。请记住,所有这些选项都需要适当的 RBAC 规则。
This one lets watcher know where to search for secrets and configmaps. You have two options here: selective namespaces (the setting above) and a namespace chosen by Namespace Resolution (this is the default option). Keep in mind that all these options require proper RBAC rules.
configmap/secret 中的更改将仅在特定更改来自标签为:spring.cloud.kubernetes.config=true
或 spring.cloud.kubernetes.secret=true
的源的情况下触发配置 watcher 发出事件。
Changes from configmaps/secrets will only trigger an event being fired from configuration watcher if that particular change came from a source that has a label: spring.cloud.kubernetes.config=true
or spring.cloud.kubernetes.secret=true
.
简而言之,如果您更改了一个 configmap(或 secret),它 不 具有上述标签,配置 watcher 将跳过为其触发事件(如果您启用了调试日志记录,这将在日志中显示)。
To put it simpler, if you change a configmap (or secret), that does not have the label above, configuration watcher will skip firing an event for it (if you enabled debug logging, this will be visible in logs).
默认情况下,配置 watcher 将监视配置命名空间中所有 configmap/secret。如果您希望仅过滤以监视特定源,您可以通过设置以下来实现:
By default, configuration watcher will monitor all configmaps/secrets in the configured namespace(s). If you want to filter to watch only particular sources, you can do that by setting:
SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE
这将告诉 watcher 仅监视具有标签:spring.cloud.kubernetes.config.informer.enabled=true
的源。
This will tell watcher to only monitor sources that have a label: spring.cloud.kubernetes.config.informer.enabled=true
.
另一项重要的配置,特别是对于作为存储卷挂载(通过 spring.cloud.kubernetes.config.paths
/spring.cloud.kubernetes.secrets.paths
或使用 spring.config.import
)的 configmap 和 secret,是:
One more important configuration, especially for configmaps and secrets that are mounted as volumes (via spring.cloud.kubernetes.config.paths
/spring.cloud.kubernetes.secrets.paths
or using spring.config.import
) is:
- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
value: "10000"
这表示在从配置 watcher 发出事件之前我们应该等待多少毫秒。这非常重要,因为 kubernetes 文档说:
This tells how many milliseconds should we wait before firing the event from configuration watcher. This is important because kubernetes documentation says:
当前在存储卷中使用的 ConfigMap 更新后,最终也会更新投影的键。
When a ConfigMap currently consumed in a volume is updated, projected keys are eventually updated as well.
您需要将这个 eventually 部分“匹配”到集群中的该毫秒值。
You need to "match" this eventually part to that value in milliseconds on your cluster.
Spring Cloud Kubernetes Configuration Watcher 可以通过两种方式向应用程序发送刷新通知。
Spring Cloud Kubernetes Configuration Watcher can send refresh notifications to applications in two ways.
-
通过 HTTP,在这种情况下,正在通知的应用程序必须具有在集群内部公开且可访问的
/refresh
actuator 端点 -
Over HTTP, in which case the application being notified, must have the
/refresh
actuator endpoint exposed and accessible from within the cluster -
使用 Spring Cloud Bus,在这种情况下,需要为应用程序部署到主机中一个消息代理。
-
Using Spring Cloud Bus, in which case you will need a message broker deployed to your custer for the application to use.
Deployment YAML
以下是样本部署 YAML,您可以使用它将 Kubernetes Configuration Watcher 部署到 Kubernetes。
Below is a sample deployment YAML you can use to deploy the Kubernetes Configuration Watcher to 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:{spring-cloud-version}
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 集群中 ConfigMap、Pod、服务、端点和 Secret 的数据。
The Service Account and associated Role Binding is important for Spring Cloud Kubernetes Configuration to work properly. The controller needs access to read data about ConfigMaps, Pods, Services, Endpoints and Secrets in the Kubernetes cluster.
Monitoring ConfigMaps and Secrets
如果对带有有效标签的 ConfigMap 或 Secret 进行更改(如上文所述),那么 Spring Cloud Kubernetes Configuration Watcher 将获取 ConfigMap 或 Secret 的名称,并向具有该名称的应用程序发送通知。这可能不足以满足您的用例,例如,您可能希望:
If a change is made to a ConfigMap or Secret with valid labels (as detailed above), then Spring Cloud Kubernetes Configuration Watcher will take the name of the ConfigMap or Secret and send a notification to the application with that name. This might not be enough for your use-case though, you could for example want to:
-
将 ConfigMap 绑定到多个应用程序,以便单个 ConfigMap 中的更改触发多个服务的刷新
-
bind a config-map to multiple applications, so that a change inside a single configmap triggers a refresh for many services
-
让基于配置文件的源触发应用程序的事件
-
have profile based sources trigger events for your application
由于这个原因,您还可以指定附加注释:
For that reasons there is an addition annotation you could specify:
spring.cloud.kubernetes.configmap.apps
或 spring.cloud.kubernetes.secret.apps
。它获取以逗号分隔的应用字符串,该字符串指定在该 secret/configmap 中发生更改时将收到通知的应用程序的名称。
spring.cloud.kubernetes.configmap.apps
or spring.cloud.kubernetes.secret.apps
. It takes a String of apps separated by comma,
that specifies the names of applications that will receive a notification when changes happen in this secret/configmap.
例如:
For example:
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 Implementation
HTTP 实现是默认使用的实现。当使用此实现时,如果 Spring Cloud Kubernetes Configuration Watcher 发生更改到 ConfigMap 或 Secret,那么 HTTP 实现将使用 Spring Cloud Kubernetes Discovery Client 获取与 ConfigMap 或 Secret 名称匹配的所有应用程序实例,并向应用程序的执行器“/refresh
”端点发送 HTTP POST 请求。默认情况下,它将使用在发现客户端中注册的端口,向 /actuator/refresh
发送 post 请求。
The HTTP implementation is what is used by default. When this implementation is used, Spring Cloud Kubernetes Configuration Watcher and a
change to a ConfigMap or Secret occurs then the HTTP implementation will use the Spring Cloud Kubernetes Discovery Client to fetch all
instances of the application which match the name of the ConfigMap or Secret and send an HTTP POST request to the application’s actuator
/refresh
endpoint. By default, it will send the post request to /actuator/refresh
using the port registered in the discovery client.
Non-Default Management Port and Actuator Path
如果应用程序使用的是非默认执行器路径和/或为管理端点使用的是不同的端口,那么该应用程序的 Kubernetes 服务可以添加一个名为 boot.spring.io/actuator
的注释,并将其值设置为该应用程序使用的路径和端口。例如
If the application is using a non-default actuator path and/or using a different port for the management endpoints, the Kubernetes service for the application
can add an annotation called boot.spring.io/actuator
and set its value to the path and port used by the application. For example
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
。
Another way you can choose to configure the actuator path and/or management port is by setting
spring.cloud.kubernetes.configuration.watcher.actuatorPath
and spring.cloud.kubernetes.configuration.watcher.actuatorPort
.
Messaging Implementation
当在 Kubernetes 中部署 Spring Cloud Kubernetes Configuration Watcher 应用程序时,可以通过将概要文件设置为 bus-amqp
(RabbitMQ)或 bus-kafka
(Kafka)来启用消息传递实施。
The messaging implementation can be enabled by setting profile to either bus-amqp
(RabbitMQ) or bus-kafka
(Kafka) when the Spring Cloud Kubernetes Configuration Watcher
application is deployed to Kubernetes.
Configuring RabbitMQ
启用 bus-amqp
概要文件时,您将需要配置 Spring RabbitMQ,将其指向要使用的 RabbitMQ 实例以及进行身份验证所需的任何凭据。可以通过设置标准的 Spring RabbitMQ 属性来执行此操作,例如
When the bus-amqp
profile is enabled you will need to configure Spring RabbitMQ to point it to the location of the RabbitMQ
instance you would like to use as well as any credentials necessary to authenticate. This can be done
by setting the standard Spring RabbitMQ properties, for example
spring:
rabbitmq:
username: user
password: password
host: rabbitmq
Configuring Kafka
启用 bus-kafka
概要文件时,您将需要配置 Spring Kafka,将其指向要使用的 Kafka Broker 实例。可以通过设置标准的 Spring Kafka 属性来执行此操作,例如
When the bus-kafka
profile is enabled you will need to configure Spring Kafka to point it to the location of the Kafka Broker
instance you would like to use. This can be done by setting the standard Spring Kafka properties, for example
spring:
kafka:
producer:
bootstrap-servers: localhost:9092