简体   繁体   中英

Dockerized Spring Boot app not using mounted Kubernetes ConfigMap (application.properties)

I have a problem where in my dockerized Spring Boot application is not using the application.properties I stored in a configMap .

However, I can see and confirm that my configMap has been mounted properly in the right directory of my Spring Boot app when I enter the pod's shell.

Note that I have an application.properties by default wherein Kubernetes mounts / overwrites it later on.

It seems that the Spring Boot uses the first application.properties and when k8s overwrites it, apparently, it doesn't use it.

It seems that, apparently, what happens is:

  • run the .jar file inside the Dockerized Spring Boot app
  • use the first/default application.properties file on runtime
  • Kubernetes proceeds to mount the configMap
  • mount / overwrite success, but how will Spring Boot use this one since it's already running?

Here is the Dockerfile of my Spring Boot / Docker image for reference:

FROM maven:3.5.4-jdk-8-alpine

# Copy whole source code to the docker image
# Note of .dockerignore, this ensures that folders such as `target` is not copied
WORKDIR /usr/src/myproject
COPY . /usr/src/myproject/

RUN mvn clean package -DskipTests

WORKDIR /usr/src/my-project-app
RUN cp /usr/src/myproject/target/*.jar ./my-project-app.jar
EXPOSE 8080
CMD ["java", "-jar", "my-project-app.jar"]

Here's my Kubernetes deployment .yaml file for reference:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-project-api
  namespace: my-cluster
  labels:
    app: my-project-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-project-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: my-project-api
    spec:
      containers:
        - name: my-project-api
          image: "my-project:latest"
          imagePullPolicy: Always
          env:
            .
            .
            .
          volumeMounts:
          - name: my-project-config
            mountPath: /usr/src/my-project/my-project-service/src/main/resources/config/application.properties
          ports:
            - containerPort: 8080
              name: my-project-api
              protocol: TCP
      volumes:
        # Name of the volume
        - name: my-project-config
          # Get a ConfigMap with this name and attach to this volume
          configMap:
            name: my-project-config

And my configMap for reference:

kind: ConfigMap
apiVersion: v1
data:
  application.properties: |-
    # This comment means that this is coming from k8s ConfigMap. Nice!
    server.port=8999
    .
    .
    .
    .

metadata:
  name: my-project-config
  namespace: my-cluster

Any help is greatly appreciated... Thank you so much.. :)

The thing is that /src/main/resources/application.properties that your application uses is the one that is inside the jar file by default. If you open your jar, you should see it there. That being said, your expectations to mount a /src/main/resources directory where your jar is are not going to be fulfilled, unfortunately. These are the docs you should be looking at .

I won't go into much detail as it's explained pretty good in the docs but I will say that you are better off explicitly declaring your config location so that new people on the project know from where the config is coming from right off the bat.

You can do something like this:

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-project-api
  labels:
    app: my-project-api
spec:
  selector:
    matchLabels:
      app: my-project-api
  template:
    metadata:
      labels:
        app: my-project-api
    spec:
      containers:
        - name: my-project-api
          image: "my-project:latest"
          imagePullPolicy: Always
          env:
            - name: JAVA_OPTS
              value: "-Dspring.config.location=/opt/config"
            .
            .
            .
          volumeMounts:
            - name: my-project-config
              mountPath: /opt/config
          ports:
            - containerPort: 8080
      volumes:
        - name: my-project-config
          configMap:
            name: my-project-config

Hope that helps,

Cheers!

I did slightly differently. I made sure I have mounted application.properties at config/. ie; below is my example mounted application.properties (below commands show the values in pod - ie; after kubectl exec -it into the pod)

/ # pwd
/
/ # cat config/application.properties 
logback.access.enabled=false
management.endpoints.web.exposure.include=health, loggers, beans, configprops, env

Basically, the trick is based on the link in the above answer . Below is an excerpt from the link in which it does say application.properties will be picked from config/. So, I made sure my environment (dev, test, prod) specific config map was mounted at config/. Do note there is precedence for the below list (per the link: locations higher in the list override lower items)

A /config subdir of the current directory.
The current directory
A classpath /config package
The classpath root

Below is the config map definition (just pasted data section)

data:
  application.properties: |+
    logback.access.enabled={{.Values.logacbkAccessEnabled}}
    management.endpoints.web.exposure.include=health, loggers, beans, configprops, env

And you can also see from actuator/env endpoint SpringBootApp did pick those values.

{
"name": "Config resource 'file [config/application.properties]' via location 'optional:file:./config/'",
"properties": {
"logback.access.enabled": {
"value": "false",
"origin": "URL [file:config/application.properties] - 1:24"
},
"management.endpoints.web.exposure.include": {
"value": "health, loggers, beans, configprops, env",
"origin": "URL [file:config/application.properties] - 2:43"
}
}
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM