ConfigMap is not working well with application.properties but works well with application.yml

7/7/2019

New to k8s.

Went through https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/2.1.0.RC1/multi/multi__kubernetes_propertysource_implementations.html

I am having multi profiles in config map and want my app to pickup the properties based on the spring.profiles.active.

Case 1:-

My ConfigMap looks like,

kind: ConfigMap
apiVersion: v1
metadata:
  name: example-configmap-overriding-new-02
data:
  application.properties: |-
    globalkey = global key value
    TeamName = Team Name value
    Purpose = Purpose value
    RootFile = Root file value
    Company = company value
    Place = Place value
    Country = Country value
    ---
    spring.profiles = qa
    globalkey = global key qa value
    TeamName = Team Name qa value
    Purpose = Purpose qa value
    RootFile = Root file qa value
    ---
    spring.profiles = prod
    globalkey = global key prod value
    Company = company prod value
    Place = Place prod value
    Country = Country prod value

My deployment file looks like,

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: demo-configmapsingleprofile
spec:  
  selector:
    matchLabels:
      app: demo-configmapsingleprofile
  replicas: 1
  template: 
    metadata:
      labels:
        app: demo-configmapsingleprofile
    spec:
      serviceAccountName: config-reader
      containers:
      - name: demo-configmapsingleprofile
        image: image name
        ports:
        - containerPort: 8080
        envFrom:
          - configMapRef:
              name: example-configmap-overriding-new-02
        securityContext:
            privileged: false        

My Config file in spring boot looks like,

@Configuration
public class ConfigConsumerConfig {

@Value(value = "${globalkey}")
private String globalkey;

@Value(value = "${TeamName}")
private String teamName;

@Value(value = "${Purpose}")
private String purpose;

@Value("${RootFile}")
private String rootFile;

@Value("${Company}")
private String company;

@Value("${Place}")
private String place;

@Value("${Country}")
private String country;

//With getters and setters
}

My application.properties looks like,

spring.profiles.active=prod
spring.application.name=example-configmap-overriding-new-02
spring.cloud.kubernetes.config.name=example-configmap-overriding-new-02
spring.cloud.kubernetes.config.namespace=default
spring.cloud.kubernetes.config.sources[0].name=example-configmap-overriding-new-02
spring.cloud.kubernetes.config.enabled=true

App is starting fine and it grabbed the values from the config map. But it is picking from wrong profile. Some values are picked up from qa profile.

I am getting the final result as:-

{"globalkey":"global key prod value","teamName":"Team Name qa value","purpose":"Purpose qa value","rootFile":"Root file qa value","company":"company prod value","place":"Place prod value","country":"Country prod value"}

Case 2:-

But, when I used the config map with yaml, as given below,

kind: ConfigMap
apiVersion: v1
metadata:
  name: example-configmap-overriding-new-02
data:
  application.yml: |-    
    globalkey : global key value
    TeamName : Team Name value
    Purpose : Purpose value
    RootFile : Root file value
    Company : company value
    Place : Place value
    Country : Country value
    ---
    spring:
      profiles: qa
    globalkey : global key qa value
    TeamName : Team Name qa value
    Purpose : Purpose qa value
    RootFile : Root file qa value
    ---
    spring:
      profiles: prod
    globalkey : global key prod value
    Company : company prod value
    Place : Place prod value
    Country : Country prod value

I am getting the result as expected. It picks from prod profile as expected.

{"globalkey":"global key prod value","teamName":"Team Name value","purpose":"Purpose value","rootFile":"Root file value","company":"company prod value","place":"Place prod value","country":"Country prod value"}

Case 2 is working as expected but not the Case 1.

Am I doing any mistake/misunderstanding with config map. Could some one advice here?

Thx.

-- NANDAKUMAR
application.properties
configmap
kubernetes
minikube
spring-boot

2 Answers

7/8/2019

As per documentation here

Another option is to create a different config map per profile and spring boot will automatically fetch it based on active profiles

You can also consider these approach:

    valueFrom:
      configMapKeyRef:
          name: example-configmap-overriding-new-02
          key: application-prod.properties
-- Hanx
Source: StackOverflow

7/8/2019

Given that there are no other answers yet...let me try to help you.

The --- divider in a YAML file separates multiple YAML documents. Not so in a properties file. Not sure how the properties file gets loaded at all with those --- but otherwise the way it is structured right now it leads to duplicate keys where a key overwrites the same key before it.

Create multiple key/value pairs - one for each profile - when using properties files. Something like this:

kind: ConfigMap
apiVersion: v1
metadata:
  name: example-configmap-overriding-new-02
data:
  application.properties: |-
    globalkey = global key value
    TeamName = Team Name value
    Purpose = Purpose value
    RootFile = Root file value
    Company = company value
    Place = Place value
    Country = Country value
  application-qa.properties: |-
    spring.profiles = qa
    globalkey = global key qa value
    TeamName = Team Name qa value
    Purpose = Purpose qa value
    RootFile = Root file qa value
  application-prod.properties: |-
    spring.profiles = prod
    globalkey = global key prod value
    Company = company prod value
    Place = Place prod value
    Country = Country prod value

They will "materialize" inside a running container as individual files at the mounted location.

-- apisim
Source: StackOverflow