Dhananjay.blog

Recipes for Java, Golang on Kubernetes and more.

Menu
  • Home
  • About
Menu

SpringBoot Reload on Configmap changes in Kubernetes

Posted on August 25, 2022

SpringBoot applications when deployed in Kubernetes need the capability to reload in the event that some of the properties change. This becomes extremely important when you need to push out configuration to your spring boot application workloads deployed in Kubernetes without having to do a full-scale deployment.

SpringBoot Application deployed on Kubernetes using Helm Package manager.
SpringBoot Application deployed on Kubernetes using Helm Package Manager.

In this article, we will go through the setup of reloading configuration within Spring boot applications in Kubernetes using the Configmap object.

Pre-Requisites

Ensure that you have gone through the setup mentioned in here

1 . Add Required Dependencies to SpringBoot Application

We need Spring Cloud Kubernetes library that adds support for the SpringBoot application running on a pod to subscribe to any changes within k8s objects such as ConfigMap.

Add the following to your Gradle file within the dependencies section. Here is what the full Gradle file should look like once done.

implementation "io.kubernetes:client-java:${k8sJavaClientVersion}"
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-kubernetes-all', version: "${sbk8sVersion}"

2. Changes within SpringBoot Application

Add @RefreshScope annotation for the AppConfig.java bean, this allows the spring bean to be refreshed using the refreshAll() method which clears up the target cache.

@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String timeout;
    private String message;
    ....
}

Add the following properties in application.properties file:

spring.cloud.kubernetes.reload.enabled=true
spring.cloud.kubernetes.reload.strategy=refresh
spring.cloud.kubernetes.reload.mode=event
spring.application.name=spring-sample-app

The above properties define the reload strategy, mode, and the name of the application. The name here is especially important and needs to match the ConfigMap name you are using in k8s.

3. Helm chart Changes

The following objects are required for the ConfigMap to work with spring properties

  • Configmap Yaml: Defines ConfigMap specification
  • Role: Creates a role to create permissions to access Kubernetes objects from within SpringBoot application
  • RoleBinding: Binds the service account used by the application to the role.

Add the following files to your helm chart under helm/spring-sample-app/templates

ConfigMap

A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume. See detailed documentation on ConfigMap here

Create a file with the following content and name configmap.yaml or just get the full contents from confgmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: spring-sample-app
data:
  application.properties: |-
    app.message=Overriden Message from Configmap
    app.timeout=500

The above ConfigMap object creates a data property application.property that will override anything that is within src/main/resources/application.properties file.

Role

A Role sets permissions within a namespace which can then be leveraged by a service account via rolebinding. More on K8s roles here

Create a file with the following content and name roles.yaml or just get the full contents from roles.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: {{ include "spring-sample-app.name" . }}
  labels:
    {{- include "spring-sample-app.labels" . | nindent 4 }}
rules:
  - apiGroups: [""] # "" indicates the core API group
    resources: ["pods","configmaps","endpoints","services"]
    verbs: ["get", "watch", "list"]

This role provides access to SpringBoot application to call k8s APIs and request information on its objects such as pods, ConfigMaps, endpoints, and services.

Role Binding

A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A RoleBinding grants permissions within a specific namespace whereas a ClusterRoleBinding grants that access cluster-wide. Refer to rolebindings k8s documentation for more details.

Create a file with the following content and name rolebinding.yaml or just get the full contents from rolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ include "spring-sample-app.name" . }}
  labels:
    {{- include "spring-sample-app.labels" . | nindent 4 }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: {{ include "spring-sample-app.name" . }}
subjects:
  - kind: ServiceAccount
    name: {{ include "spring-sample-app.name" . }}

This binds the service account to the role created above which will be used by the SpringBoot application to call k8s APIs.

4. Upgrade Version Numbers within SpringBoot Application

Update the version in build.gradle file and helm charts chart.yaml to 1.0, version number can be anything as long as they are the same between both helm and build Gradle file.

build.gradle file:

version = '1.0'

Chart.yaml file

appVersion: "1.0"

5. Rebuild SpringBoot App and Deploy Helm Chart

Build the spring application with the changes and create an image, run the following in project root directory

./gradlew -i jibDocker

Then navigate to helm root directory and run helm upgrade command or helm install if you haven’t already installed this application before

helm upgrade --install spring-sample-app spring-sample-app/

6. Verify Configmap Changes

Open up a terminal window in Mac or something equivalent and run the following to start tailing the logs

kubectl logs -l app.kubernetes.io/name=spring-sample-app -f

Open up another terminal window and Verify the current property state

curl http://localhost/propertyValues
Timeout=500, Message=Overriden Message from Configmap

Now change the ConfigMap object and edit one of these values. Here I changed the message and timeout values

kubectl edit configmap spring-sample-app
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  application.properties: |-
    app.message=Property Changed to test Reload from Configmap
    app.timeout=600

Save it and view the logs, you should see the following within the logs. This indicates spring application received changes from ConfigMap and was able to successfully reload the application using new values.

Detected change in config maps
Reloading using strategy: REFRESH
curl http://localhost/propertyValues
Timeout=600, Message=Property Changed to test Reload from Configmap

Cleanup and Next Steps

Make sure you delete the helm chart and remove all images you created as a part of the tutorial. You probably don’t want stray pods running in your cluster and unwanted images filling up your disk

// To delete the application including the chart
helm delete spring-sample-app
// To remove all images created by our builds
docker rmi -f $(docker images spring-sample-app -aq)

Conclusion

To conclude we demonstrated how your application built using SpringBoot can subscribe to Configmap change events from K8s and then reload the context to reflect those changes. In this post, we assumed certain things regarding the configuration including refresh strategy. There are more than one ways to do this which we will go over in the next post.

Also for your reference, the entire source code with Helm chart is available on github.

Categories

  • GO
  • Home
  • Java
  • K8s and More
  • Programming
  • Software

Tags

Container Image Docker gingonic go helm jib kafka kubernetes microservices springboot spring cloud config tdd test driven development unit testing

Recent Posts

  • Unit Testing Checklist
  • ConfigMap Custom Watcher with SpringBoot
  • Go Service Configuration with k8s ConfigMaps
  • Go MicroService in Gin using Helm On k8s
  • Container Image Reducing Size with Jib

Archives

  • March 2025
  • January 2023
  • December 2022
  • September 2022
  • August 2022

Categories

  • GO
  • Home
  • Java
  • K8s and More
  • Programming
  • Software

About

  • Privacy
  • Terms of Service
  • About
  • Contact
@2024 Dhananajay on Tech