Spring Cloud Kubernetes - загрузка Spring не читает карту конфигурации

У меня есть веб-приложение с весенней загрузкой, которое просто печатает свойство, переданное в ConfigMap Kubernetes.

Это мой основной класс:

@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.

Я создаю ConfigMap с содержанием kubectl create -f configmap-demo.yml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo
data:
    bean.message: This is an info from k8

И развертывание с kubecetl 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

Проблема в том, что при доступе к корневому ресурсу / я всегда получаю жестко заданное значение по умолчанию, а не то, что определено в ConfigMap Kubernetes.

Пример проекта также с файлами yaml и файлом Docker, доступным по адресу https://drive.google.com/open?id=107IcwnYIbVpmwVgdgi8Dhx4nHEFAVxV8.

Также проверил журналы запуска DEBUG, и я не вижу ошибок или подсказок, почему он не должен работать.


person Miguel Ribeiro    schedule 28.12.2018    source источник


Ответы (2)


Spring Cloud Kubernetes неполный. В нем отсутствует инструкция по включению этой зависимости, чтобы разрешить загрузку свойств приложения из ConfigMap:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>
person Chin Huang    schedule 29.12.2018
comment
Спасибо за это, но, в конце концов, я бы не стал использовать Spring Cloud Kubernetes - это работает без него. Кроме того, я хочу воспользоваться перезагрузкой конфигурации при изменении ConfigMap. - person Miguel Ribeiro; 29.12.2018
comment
Я понимаю, что теперь вы хотите использовать Spring Cloud Kubernetes для чтения ConfigMap. Я обновил свой ответ. - person Chin Huang; 01.01.2019
comment
Это была проблема. Документация действительно не упоминает об этом. Теперь у меня проблема с перезагрузкой конфигурации, но я открою для этого другой вопрос. Я считаю, что это другая тема. - person Miguel Ribeiro; 02.01.2019
comment
Требуются ли тома в развертывании? - person pavan kumar; 07.04.2020

Вы близки:

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

В результате файл demo.properties, как определено в ConfigMap, «появится» в каталоге /demo/config внутри работающего контейнера.

3) Добавьте аннотацию @PropertySource к классу MyConfig:

@Configuration
@PropertySource("file:/demo/config/demo.properties")
@ConfigurationProperties(prefix = "bean")
public class MyConfig {
  ...
}
person apisim    schedule 30.12.2018
comment
Спасибо @apisim! Но для этого подхода мне не понадобится Spring Cloud Kubernetes. Кроме того, afaik, передачи пути к файлу конфигурации недостаточно для перезагрузки конфигураций после их изменения. - person Miguel Ribeiro; 30.12.2018