Spring boot pick up dynamic application.properties from kubernetes configmap - java

We have springboot application running as a pod , it picks from application.properties from configmap. When we update configmap this change is not picked up springboot aplication , we need to restart the application to pick new property change.
Can we do this without restarting the sringboot application pod to pick new properties.

No, ideally you can not do it, you need to restart the POD if you are using the config map.
However, you can set the auto reloader which will do work for you, whenever configmap will get updated it will auto restart the PODs of deployment so you won't need to manually restart the PODs.
You can read more about it here Reloader : https://github.com/stakater/Reloader
Or else
you can export the variable with this command however it not permanent solution
kubectl exec -it <pod_name> export VARIABLENAME=<value>

The problem you are facing is that spring boot config doesn't know when to do a refresh of the config.
You have two options
If you want to refresh whenever the config changes use spring cloud k8s watcher link to project
2. Restart the pod whenever config changes. There are many controllers available to do

Related

Java Spring Scheduler not working in PCF server

I have a spring boot project in which spring scheduler is working fine as i have added logger in scheduler method in my local system using Cron expression.
Problem:
When same spring boot app is deployed over PCF(Pivotal Cloud Foundary) it does not enable the scheduler and no logs are printed neither any error is shown in pcf logs related to scheduler.
While if i hit any controller through postman, logs are printing for that but not of scheduler.
I also provided cron expression value like for every minute in pcf environment variables in app and restarted the app. But that didn't help.
Can anyone suggest me something in this issue?
Thank you in advance for your valuable time!!
When you deploy your application in PCF Cloud space, it takes your code, scan it against available buildpacks unless explicitly provided by user and then creates a container image also known as Droplet using code, build-pack and base container.
If you use cloud config to manage the configurations for spring boot scheduler, it uses auto configurations to load the properties at runtime. In some cases due to the difference in the OS configuration and loading of these configurations at runtime, there will be mismatch between what timezone your app expects and the one that the server understands.
Most of the time it can be resolved by explicitly defining the timezone configuration in PCF manifest file or command line when pushing the application.
E.g. set environment TZ variable.
cf set-env {app-name} TZ 'America/Chicago'
OR by adding following in manifest.yml file:
env:
TZ: America/Chicago

How to load changed environment variable in spring boot application running in PCF without restarting application?

We have a spring boot application running in PCF and it reads the PCF environment variables(CF_INSTANCE_INDEX, CF_INSTANCE_ADDR,..) from an application. Based on those variables, we are trying to implement the logic for a scheduler. While running this scheduler, these variables' values could have changed. Is there a way to refresh/reload bean that have env values during runtime?
we used #RefreshScope annotation on config properties bean.
#Configuration
#RefreshScope
public class PcfEnvProperties{
#Value("${CF_INSTANCE_INDEX}")
private int intanceIndex;
#Value("${CF_INSTANCE_ADDR}")
private String intanceAddr;
...
}
and refresh using
context.getBean(RefreshScope.class).refresh("PcfEnvProperties");
PcfEnvProperties pcfEnv = context.getBean(PcfEnvProperties.class);
But It is not loading the recently changed env variable into running application. Any ideas on how to accomplish this?
You can use Spring Cloud Config Server in combination with Spring Actuator to expose an endpoint in your service that will refresh the application's properties on the fly. You could set up your scheduler to hit this endpoint on a timer or as needed.
Here is one tutorial I found that seems pretty straightforward: https://jeroenbellen.com/manage-and-reload-spring-application-properties-on-the-fly/
You may have to play with the setup depending on how your platform is configured, but I believe it should do what you're wanting. We have deployed many java web services on our PCF platform using this actuator/config server approach, and we can just make a call to the refresh endpoint and it successfully pulls in (and overwrites when necessary) the new properties and values from the config server. Also you can pull out a list of the property names and values that changed from the response.
I'm not familiar with the specific property values you mentioned, but as long as they are normally a part of Spring's ApplicationContext (where properties usually are found) then you should be able to pull in changed values using this approach with Spring's cloud config server and actuator libraries.
Hope this helps

Prevent Spring Boot Invoking EC2MetadataUtils.getItems on startup

I am having an issue where EC2MetaDataUtils.getItems is being invoked on application start up ( Spring boot app), we do not use EC2 and so the calls made to AWS to get Metadata always fail, the application attempts to get this data 3 times and so this is adding around 15 seconds to the start time of the application.
I have been searching high and low for solutions I found a promising solution would suggested the following #EnableAutoConfiguration(exclude = { ContextResourceLoaderAutoConfiguration.class, ContextResourceLoaderConfiguration.class, ContextInstanceDataAutoConfiguration.class })
However when I try to start up the application it complains that ContextResourceLoaderConfiguration.class cannot be excluded as it is not auto configuration; if I just exclude the other 2 the application still invokes the MetaDataUtils.
Has anyone experienced this in the past and managed to resolve it?
Thank you for your time.
Resolved with the following:
#EnableAutoConfiguration(exclude = {ContextInstanceDataAutoConfiguration.class, ContextStackAutoConfiguration.class, ContextResourceLoaderAutoConfiguration.class})
when running spring-boot-application with AWS dependencies ,
It invokes stack auto-configuration , you need to disable it ,
add following to application.yml
cloud.aws.stack.auto: false
SpringBoot application should not do any call to EC2. This mean your are using some AWS specific library/component/what ever and this library on startup do this call.
Please check your dependencies and context configuration. There are nothing about SpringBoot. There is something with your custom dependencies/components.
If you're not using EC2, you can try removing the spring-cloud-aws* libraries from your dependencies.
You can use Spring profiles to differentiate between cloud and default profiles. For cloud profile, you can use spring-cloud-aws artifact to get metadata about EC2 instance which you need EC2 read permission access from an attached IAM role whereas for default profile, you don't need to worry about cloud environment and disable the cloud configuration properties which should not cause an issue for the application startup.

JHipster registry, change properties value in spring cloud config server

I'm trying to migrate from monolithic web application to microservices.
For doing this I'm using JHipster v 4.11.1 (very helpful!).
My problem is:
In JHipster registry (central-config folder) I wrote some property files and every microservice, on startup, read the owned properties.
I need to change this properties on runtime both from registry and from every microservices.
There are any ways to do this? I have to use kafka or somethings like that?
JHipster Registry is a Spring Cloud Config server and should allow this behavior but I'm new with this stuff and maybe I lost some information. For now I don't use Git or SVN repository, but only a native configuration.

application configuration for java apps in kubernetes

I'm new to java and k8, and I have some doubts about how to handle application configurations for my java apps. I've got one spring boot app and the other three use wildfly.
So, they all got hardcoded application configurations, and when starting them the just use something like:
java -Dswarm.project.stage=development -jar foobar/target/foobar-swarm.jar
except for the spring boot which has an application.properties file that consists of application configuration data.
So basically the three java apps have backed in two files (which I know is a no no):
- project-stages.yml
- standalone.xml
And when the developer wants to deploy to production he uses:
java -Dswarm.project.stage=production -jar foobar/target/foobar-swarm.jar
And, now we come to kubernetes which has three ways of dealing with application configuration data:
1.) Env variables
2.) Config maps
3.) Secrets
I was thinking of using configmaps instead of env variables because they have more benefits.
So, the developer gave me the possibility of overwriting those hardcoded variables with an external file : Dsystem.properties.file=/var/foobar/environment.properties
But I'm still overwriting an hardcoded files with an external file, and I'm not happy with that solution!
So, I'm basically looking on advise can those hardcoded files be supplied externally and populated with configmaps in k8 - what would be the best practice of handling the config files in the world of k8?
Tnx,
Tom
There are several questions in the post, but I can address only the one related to spring-boot.
The simplest and the most convenient way of specifying configurations to spring boot app is via its built in profiling feature. As you already mentioned you have application.properties. You can create similar files according to your usage cases: application-production.properties, application-staging.properties, application-k8s.properties, etc.
Kubernetes deployment doesn't change this in any way.
You can control which configuration to pick by setting SPRING_PROFILES_ACTIVE env variable from the kubernetes.
You might have something like this:
docker run -e SPRING_PROFILES_ACTIVE=k8s -d -p 0.0.0.0:8080:8080 \
--name=yourapp your_image_name bash -c "java -jar yourapp.jar"
It will pick configuration from application-k8s.properties.
Configuration files support environment variables as well.
You can have placeholders like ${YOUR_DB} in your properties files and Spring will automatically pick up env variable with name YOUR_DB. It is convenient to use this feature let's say when your app pod must have its own db pod.
If I got your question right you are asking how to configure a Spring Boot application via a k8s ConfigMap. Yes, you can do that.
Create a Docker image with WORKDIR work_dir in which you start the Spring Boot application eg via java -jar /work_dir/app.jar
Create a ConfigMap
Run a container of the above mentioned image within k8s
Mount the ConfigMap for the Spring Boot application.properties into the Container as /work_dir/config/application.properties
On changes in the ConfigMap the file within the container gets updated. You have to restart the Spring Boot Application to set your changes active.

Categories

Resources