Spring Cloud Kubernetes - Spring Boot未读取配置映射

4

我是一个能够打印从Kubernetes的ConfigMap中传递的属性的Spring Boot Web应用程序。

这是我的主类:

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class DemoApplication {

    private MyConfig config;
    private DiscoveryClient discoveryClient;

    @Autowired
    public DemoApplication(MyConfig config, DiscoveryClient discoveryClient) {
        this.config = config;
        this.discoveryClient = discoveryClient;
    }

    @RequestMapping("/")
    public String info() {
        return config.getMessage();
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @RequestMapping("/services")
    public String services() {
        StringBuilder b = new StringBuilder();
        discoveryClient.getServices().forEach((s) -> b.append(s).append(" , "));
        return b.toString();
    }

}

MyConfig类如下:

@Configuration
@ConfigurationProperties(prefix = "bean")
public class MyConfig {

    private String message = "a message that can be changed live";

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

基本上,调用根资源时我总是会得到以下消息:

可以实时更改的消息

而调用/services时,我实际上会得到一个Kubernetes服务列表。
我使用kubectl create -f configmap-demo.yml命令创建ConfigMap,其内容如下:
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo
data:
    bean.message: This is an info from k8

使用kubectl create -f deploy-demo.yml进行部署,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
  labels:
    app: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      # this service account was created according to
      # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#service-account-permissions
      # point 5 - Grant super-user access to all service accounts cluster-wide (strongly discouraged)
      serviceAccountName: i18n-spring-k8
      containers:
      - name: demo
        image: aribeiro/sck-demo
        imagePullPolicy: Never
        env:
        - name: JAVA_OPTS
          value:
        ports:
        - containerPort: 8080
      volumes:
      - name: demo
        configMap:
          name: demo

问题在于访问根资源/时,我总是得到默认的硬编码值,而不是Kubernetes' ConfigMap中定义的值。
示例项目还提供了yaml文件和Docker文件,可从https://drive.google.com/open?id=107IcwnYIbVpmwVgdgi8Dhx4nHEFAVxV8获取。
同时,我也检查了启动调试日志,未发现任何错误或线索说明为什么它不起作用。
2个回答

7

Spring Cloud Kubernetes文档不完整。它缺少包含此依赖项的说明,以启用从ConfigMap加载应用程序属性:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>

谢谢您的回复,但最终我不会使用Spring Cloud Kubernetes - 这可以在没有它的情况下工作。此外,如果ConfigMap发生更改,我想利用配置重新加载的功能。 - Miguel Ribeiro
1
我现在明白你想要使用Spring Cloud Kubernetes来读取ConfigMap。我已经更新了我的回答。 - Chin Huang
这就是问题所在。文档确实没有提到这一点。现在我有重新加载配置文件的问题,但我会为此开一个不同的问题。我认为这是一个不同的主题。 - Miguel Ribeiro
部署中需要卷吗? - Pavan Kumar
在较新版本的Spring Boot中,starter的artifactId略有改变。现在它是spring-cloud-starter-kubernetes-fabric8-config或spring-cloud-starter-kubernetes-client-config,具体取决于您使用的Kubernates Java客户端。 - piphonom
秘密怎么样?我在读取秘密中的属性时遇到了问题。 - xbmono

1
你离成功不远:
1)稍微改变一下ConfigMap的定义方式,使其包含一个属性文件。例如:
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo
data:
  demo.properties: |
    bean.message: This is an info from k8

2) 将ConfigMap作为卷挂载:

...
spec:
  containers:
  - name: demo
    ...
    volumeMounts:
    - name: config
      mountPath: /demo/config
  volumes:
  - name: config
    configMap:
      name: demo

作为结果,在ConfigMap中定义的demo.properties文件将“出现”在运行容器内部的/demo/config目录中。
3)向MyConfig类添加@PropertySource注释。
@Configuration
@PropertySource("file:/demo/config/demo.properties")
@ConfigurationProperties(prefix = "bean")
public class MyConfig {
  ...
}

2
谢谢@apisim!但是我不需要Spring Cloud Kubernetes来实现这个方法。另外,据我所知,仅传递配置文件路径并不能在更改后重新加载配置。 - Miguel Ribeiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接