Developer Discoveries

Configmap Reload with Spring Boot in Kubernetes

In Kubernetes, configmap is used for keeping properties for an application. Once Spring applications required restart just due to change in properties file to take effect. Now in cloud with the help of fabric8 Kubernetes client, restart is not required anymore. We can reflect changes in configuration to Spring Boot live without downtime.

There are two reload modes: polling and event. Polling as the name implies polls Kubernetes API periodically. Event is more effective since it takes effect when configmap changed. We will cover event mode reload in this post.

How events arrive Spring Boot? Does Kubernetes aware of our Spring Boot app? No. Don’t confuse this event with Kubernetes event.

configmap-diagram

Above you can see Websocket is used between Spring Boot and Kubernetes API Server. Assuming we are using namespace “default” in this example, changes to response in this address reflected to KubernetesClient https://{api_server_clusterip}/api/v1/namespaces/default/configmaps/k8s-live-reload-configmap . If kube-proxy does not allow WebSocket then API Server is polled by HttpClient.

In Spring side, bootstrap.yaml reload mode and configmap name given. I deliberately disabled actuator endpoints, because most examples include actuator endpoints, however it is not required because fabric8-client refreshes bean internally. In pom.xml however actuator dependencies needed since fabric8-config depends on actuator configuration classes. See example

spring:
  application:
    name: k8s-live-reload-example
  cloud:
    kubernetes:
      reload:
        enabled: true
        mode: event
      config:
        sources:
          - name: k8s-live-reload-configmap
          
management:
  endpoints:
    enabled-by-default: false #actuator endpoints disabled in order to show it is not required to reload config

Beans annotated with @ConfigurationProperties are refreshed.

@Configuration
@ConfigurationProperties(prefix = "bean" )
@Data
public class Config {

    private String testvalue;
    
}


Run example
We need to build and push our application image to Docker and Kubernetes need to see this image. I suggest using Minikube 1.16.0. There are problems in prior versions due to DNS and VM(Hyper-V, VirtualBox). This version allows to run minikube as a docker container. It can be download from here: https://github.com/kubernetes/minikube/releases Assuming you are not behind proxy or VPN (you may have network problems), following installation start minikube with this command. You must have docker running.

minikube start --driver=docker

This will download images and start minikube. Then install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl

First we need rolebinding for querying API Server. Otherwise KubernetesClient cannot reach API Server. default is the namespace here.

kubectl create rolebinding default-sa-view --clusterrole=view --serviceaccount=default:default --namespace=default

Get example project

git clone https://github.com/gungor/springboot-k8s-configmap-reload-example.git
cd springboot-k8s-configmap-reload-example

Now add configmap named “k8s-live-reload-configmap” to kubernetes

kubectl apply -f src/k8s/config-map.yml

Switch to kubernetes docker daemon in active shell to make Kubernetes reach application image. Run the command below, then run the last command in the output.

minikube docker-env

Build application image

mvn clean install spring-boot:build-image

Deployment and service

kubectl create deployment liveconfig-demo --image=springboot-configmap-livereload-example:0.0.1-SNAPSHOT
kubectl create service clusterip liveconfig-demo --tcp=8080:8080


Test

Now see config before it has changed Deployment and service

kubectl get service liveconfig-demo #copy CLUSTER-IP returned from this command
minikube ssh
curl http://CLUSTER-IP:8080/liveconfigtest

It should return oldvalue. Now edit config map through command below or through minikube dashboard

kubectl edit configmap k8s-live-reload-configmap

After editing configmap, recheck application

minikube ssh
curl http://CLUSTER-IP:8080/liveconfigtest

It returns new value.

This project is maintained by gungor