简体   繁体   中英

Spring Boot: override application.yml properties from Kubernetes ConfigMap

I need to oveeride some of properties defined in a application.yml of Spring Boot application running in k8s. How can I do this? The only way I found is to mount whole application.yml but I only need to override one property.

Spring Boot Apps should override properties in the configuration files (aka, in their application.yml most of the times) with environment variables.

Assuming the App is deployed on Kubernetes with a Pod (but it doesn't matter, Deployments, StatefulSets, Jobs are all the same regarding environment) you can inject environment variables inside the container by either directly assigning them to the Deployment itself, or with a ConfigMap (or a Secret, should the property be more secure and masked)

apiVersion: v1
kind: Pod
metadata:
  name: example
spec:
  containers:
  - name: example-container
    image: example-image:latest
    env:
    - name: THIS_IS_AN_ENV_VARIABLE
      value: "Hello from the environment"
    - name: spring.persistence.url
      value: "The persistence url, for example"

Even better, you can inject all the content of a ConfigMap as environment variables:

apiVersion: v1
kind: ConfigMap
metadata:
  name: example-config
data:
  spring.persistence.url: "your persistence url"
  spring.mail.user: "your mail user"

And then your Pod:

apiVersion: v1
kind: Pod
metadata:
  name: example
spec:
  containers:
  - name: example-container
    image: example-image:latest
    envFrom:
    - configMapRef:
        name: example-config

Inside the container, the variables will be in the environment.. and Spring should use them to override variables with same name which are defined (or maybe not even defined) in your application.yml

For more info:

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/ https://docs.spring.io/spring-boot/docs/1.3.3.RELEASE/reference/html/boot-features-external-config.html

We had to do something similar. And i explain you how we did. Possibly this helps.

If you can modify your Dockerfile then create an entrypoint.sh script. It could contain the following:

entrypoint.sh

#!/bin/bash
set -e

# Source custom scripts, if any
if [ -d /etc/spring.d ]; then
    for f in /etc/spring.d/*; do
        if [ -x "$f" ]; then
            echo "Running $f ..." >&2
            "$f"
        else
            echo "Could not run $f, because it's missing execute permission (+x)." >&2
        fi
    done
    unset f
fi

exec "$@"

The entrypoint.sh is executing custom scripts inside the /etc/spring.d directory on startup. You can put any exectuble script inside, whatever you want.

Inside the /etc/spring.d you can create a copy script which copies an application.yml into same directory where the spring boot jar file is located. Example follows.

Your Dockerfile could look like

FROM adoptopenjdk:15-jre
RUN mkdir /app
COPY application.jar /app/
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["java", "-jar", "/app/application.jar"]

If this is prepared, you can use a configMap to define the copy script and mount it to the directory /etc/spring.d

apiVersion: v1
kind: ConfigMap
metadata:
name: spring-d
data:
  copy-yaml.sh: |
    #!/bin/bash
    cp /config/application.yml /app/application.yml

The copy script will take care, that you application.yaml (which will be mounted as a configMap as well) will be copied to the right place.

And a further configMap for your application.yml

apiVersion: v1
kind: ConfigMap
metadata:
name: app-yaml
data:
  application.yml: |
    spring:
      application:
        name: This is just an example, add as many values as you want.

Inside your pod yaml you could do something like this:

...
    volumeMounts:
    - name: spring-d
      mountPath: /etc/spring.d
    - name: app-yaml
      mountPath: /config
  - name: spring-d
    configMap:
      name: spring-d
      defaultMode: 0777
  - name: app-yaml
    configMap:
      name: app-yaml
...

THIS CODE IS CURRENTLY UNTESTED, IT'S JUST SHOWING YOU AN EXAMPLE HOW YOU COULD SOLVE YOUR PROBLEM IN A VERY FLEXIBLE WAY.

I used snippets from my scripts and copied it here together, so maybe there could be small mistakes inside. Please let me know.

Could be doable in another way, that's why i'm answering again. Do it in an easy way.

Create your application.yml in a configmap and mount it as a sub directory called config into the same directory where the spring boot jar ins located.

The documentation of spring boot (external application properties) says:

Spring Boot will automatically find and load application.properties and application.yaml files from the following locations when your application starts:

The classpath root

The classpath /config package

The current directory

The /config subdirectory in the current directory

Immediate child directories of the /config subdirectory

Which means we don't have to take care of setting anything. It should find the config inside the subdirectory config.

apiVersion: v1
kind: ConfigMap
metadata:
name: spring-application-config
data:
  application.yml: |
    spring:
      application:
        name: This is just an example, add as many values as you want.

pod.yaml:

...
    volumeMounts:
    - name: spring-application-config
      mountPath: /app/config
  - name: spring-application-config
    configMap:
      name: spring-application-config
...

Assuming that your spring boot jar file is located in the path /app

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