Spring Cloud Kubernetes 不重新加载秘密更改

Posted

技术标签:

【中文标题】Spring Cloud Kubernetes 不重新加载秘密更改【英文标题】:Spring Cloud Kubernetes not reloading secret change 【发布时间】:2020-10-24 11:01:00 【问题描述】:

我正在探索 Spring Cloud Kubernetes 的功能,方法是使用它的特性来动态重新加载机密。但是,我仍然没有得到这个工作。

我有一个简单的 Spring Boot 应用程序,它只打印出挂载在 pod 中的秘密内容。这是 bootstrap.properties

中的配置
spring.cloud.kubernetes.reload.enabled=true
spring.cloud.kubernetes.reload.monitoring-secrets=true

spring.cloud.kubernetes.secrets.enabled=true
spring.cloud.kubernetes.secrets.paths=/etc/secret-volume

management.endpoint.info.enabled=true
management.endpoint.health.enabled=true
management.endpoint.restart.enabled=true

application.properties中,我定义了获取secret值的属性:

mysecret.password=$MY-PWD

在 Spring Boot 应用程序中,我定义了一个将存储秘密值的 bean:

@Configuration
@ConfigurationProperties(prefix = "mysecret")
public class MySecret 

    private String password;

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    

当我在 minikube 上运行应用程序时,我在日志中看到 Spring 检测到声明的机密并激活配置文件:

16:54:30.887 [主要] 信息 o.s.c.b.c.PropertySourceBootstrapConfiguration - 定位属性 来源:[BootstrapPropertySource@1132379993 name='bootstrapProperties-my-pwd',属性=MY-PWD=qwerty] 16:54:30.899 [main] 信息 c.c.r.ReloadSecretsApplication - The 以下配置文件处于活动状态:kubernetes

一段时间后,我收到以下日志,表明它被添加了一个对秘密的观察者:

16:54:35.460 [OkHttp https://10.96.0.1/...] 调试 i.f.k.c.d.i.WatchConnectionManager - WebSocket 成功打开 16:54:35.460 [主要] 信息 o.s.c.k.c.r.EventBasedConfigurationChangeDetector - 添加了新的 Kubernetes watch:secrets-watch 16:54:35.460 [main] INFO o.s.c.k.c.r.EventBasedConfigurationChangeDetector - Kubernetes 已激活基于事件的配置更改检测器

然后,当我更改密码时,我得到这行说不会触发重新加载:

11:20:15.963 [OkHttp https://10.96.0.1/...] 警告 o.s.c.k.c.r.EventBasedConfigurationChangeDetector - 当前数量 的 Confimap PropertySources 与从 Kubernetes - 不会发生重新加载

关于这个主题的文档非常稀缺。 我这里有什么遗漏的配置吗?

指向 Spring Boot 应用程序的链接:https://github.com/Azlop/spring-cloud-kubernetes-reload-secrets

【问题讨论】:

可能与此有关? github.com/spring-cloud/spring-cloud-kubernetes/issues/524 【参考方案1】:

我知道这是一个没有答案的老问题。我遇到了同样的问题,经过一番研究后解决了。在这里我分享我对这个问题的经验,如果它可以帮助将来的人。

Spring Cloud Kubernetes 已将外部配置映射作为多个 ConfigMapPropertySource 实例存储在 CompositePropertySource 或 BootstrapPropertySource 中。当应用程序管理 configmap 已更改时,它会从 CompositePropertySource 获取 ConfigMapPropertySource 实例,并将 ConfigMapPropertySource 实例的长度与传入实例进行比较。如果长度不同,应用程序会返回错误消息:“当前 Confimap PropertySources 的数量与从 Kubernetes 加载的不匹配 - 不会重新加载”。

但是这里有一个潜在的问题:其他函数,在我的例子中是一个加密器,可能会改变 CompositePropertySource 的类型。之后应用无法获取到 ConfigMapPropertySource 实例,肯定是比较失败了。

所以我的解决方案是创建一个自定义的 EventBasedConfigurationChangeDetector ,它已经改变了比较的逻辑。原来的版本是:

private void onEvent(ConfigMap configMap) 
    boolean changed = changed(locateMapPropertySources(this.configMapPropertySourceLocator, this.environment), findPropertySources(ConfigMapPropertySource.class));
    if (changed) 
            XXXX
    

您应该重写 findPropertySources 函数以适应您的情况。在我的实例中,我打开加密的 PropertySource 以获取原始的 ConfigMapPropertySource 实例。

最后,注入您自定义的 EventBasedConfigurationChangeDetector 来替换原版的将解决问题。

【讨论】:

以上是关于Spring Cloud Kubernetes 不重新加载秘密更改的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Kubernetes,网关路由映射

spring-cloud-kubernetes与SpringCloud Gateway

正在使用 Kubernetes Spring Cloud 多个配置映射

部署微服务的时候,Spring Cloud 和 Kubernetes 哪个更好?

Spring Cloud Kubernetes(二)

spring-cloud-kubernetes官方demo运行实战