Consume k8s configmap in spring

3/10/2020

I've got a spring boot service that presently uses .properties file for consuming variables using the spring @Value annotation. Recently we have been migrating the spring boot service to K8 cluster. This means that, we need to create a configmap.yml file containing all the same properties as the .properties file. And whenever changes to properties are made, it must be done in both places, the configmap and .properties file used for local dev. So we have to manage 2 files (configmap and .properties) for each spring profile. Is there a better way to do this? We use gitlab ci/cd tools for deployment.

Is there a way to use the configmap instead of the properties for local development in our machines, so that we can discard the .properties file altogether and only maintain configmap?

What's the ideal way to manage properties for the spring boot application?

Sample service-config-map.yaml

kind: ConfigMap 
apiVersion: v1 
metadata:
  name: myservice-config
data:
  server.port: "10300"
  spring.application.name: myserviceGateway
  myservice.application.name: helloworld
  myservice.server.apiContext: /api
  myservice.server.versionContext: /v
  myservice.current.version=2.0

properties file application.properties

server.port=10300
spring.application.name=myserviceGateway
myservice.application.name=helloworld
myservice.server.apiContext=/api
myservice.server.versionContext=/v
myservice.current.version=2.0
-- MhnCodes
configmap
java
kubernetes
spring
spring-boot

3 Answers

3/11/2020

Yes, it's doable.

First of all you would need a bean to placehold from yaml like:

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
    PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
    yaml.setResources(new ClassPathResource(CONF_FILE));
    propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
    return propertySourcesPlaceholderConfigurer;
}

And then you can annotate any your standard service as:

    @Service
@EnableConfigurationProperties
@ConfigurationProperties(prefix="service-config-map")
public class ConfigMapConfigService {
...
-- AlexGera
Source: StackOverflow

3/12/2020

Depending on your type of access to the cluster, you can use the K8s API to retrieve resources via HTTP. For example, you can have some sort of a script that pulls the configmap from your cluster and parses it to yaml (it's in json by default, not sure if yaml output is supported, haven't really tested, though).

See more here: https://docs.openshift.com/container-platform/3.7/rest_api/api/v1.ConfigMap.html#Get-api-v1-namespaces-namespace-configmaps-name

-- Urosh T.
Source: StackOverflow

3/11/2020

The Spring Cloud Kubernetes project makes Kubernetes ConfigMaps available during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on observed ConfigMaps.

An example here

The bootstrap yaml which has the name of the config map looks like

spring:
  application:
    name: reload-example
  cloud:
    kubernetes:
      reload:
        enabled: true
        mode: polling
        period: 5000
      config:
        sources:
          - name: other
          - name: ${spring.application.name}
-- Arghya Sadhu
Source: StackOverflow