Kubernetes ConfigMap Configuration and Reload Strategy

Eresh Gorantla
The Startup
Published in
6 min readDec 20, 2019

This story focuses on ConfigMap resource and its usage in pods over Kubernetes container and reload strategy in application real-time.

Please go through my earlier story for Minikube installation and deploying the sample application in Kubernetes runtime in Minikube.

Why ConfigMap?

Many applications require configuration via some combination of config files, command line arguments, and environment variables. These configuration artifacts should be decoupled from image content in order to keep containerized applications portable. The ConfigMap API resource provides mechanisms to inject containers with configuration data while keeping containers agnostic of Kubernetes. ConfigMap can be used to store fine-grained information like individual properties or coarse-grained information like entire config files or JSON blobs.

This seperates the tight coupling between application and configuration properties under same package. The ConfigMap residing at container and available for the application at runtime when deployed in pod.

Overview of ConfigMap

The ConfigMap API resource holds key-value pairs of configuration data that can be consumed in pods or used to store configuration data for system components such as controllers. ConfigMap is similar to Secrets, but designed to more conveniently support working with strings that do not contain sensitive information.

Note: ConfigMaps are not intended to act as a replacement for a properties file. ConfigMaps are intended to act as a reference to multiple properties files. You can think of them as way to represent something similar to the /etc directory, and the files within, on a Linux computer.

Example of ConfigMap

ConfigMap Example
  • kind:- The kind is ConfigMap
  • metadata:- It holds the improtant information line ConfigMap name, namespace and others. This data is mapped in Pod or deployment config.
  • data:- This field contains the configuration data. As you can see, ConfigMaps can be used to hold fine-grained information like individual properties or coarse-grained information like the contents of configuration files.

Create ConfigMap:

ConfigMaps can be created from directories, files and literal values. Here we will apply config in our sample applcation.

ConfigMap Creation

Sample Spring Boot application to load config properties from ConfigMap

  • Maven dependencies :- Spring Boot latest version is used.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
  • bootstrap.yml :- In spring cloud applications, few of the config properties should be known to kubernetes runtime before deployment actually starts.
spring:
cloud:
kubernetes:
config:
enabled: true
sources:
- namespace: default
name: minikube-sample
management:
endpoint:
restart:
enabled: true

sources :- name is minikube-sample which is configmap mapping.

  • RestController:- properties are loaded in application for @ConfigurationProperties.
@RestController
@RequestMapping("/home")
public class HomeResource {

@Autowired
PropertiesConfig config;

@GetMapping("/data")
public ResponseEntity<ResponseData> getData() {
ResponseData responseData = new ResponseData();
responseData.setId(1);
responseData.setName(config.getName());
responseData.setPlace("Hyderabad");
responseData.setValue(config.getTest());
return new ResponseEntity<>(responseData, HttpStatus.OK);
}

@Getter
@Setter
public class ResponseData {
private String name;
private Integer id;
private String place;
private String value;
}
}

The name and value are set from config properties.

  • deployment.yaml :- Service kind as NodePort dedicated to a port number. ConfigMaps are mappedn through volume mounts. The Service and deployments binds to application from metadata : name.
  • ConfigMaps are maped to this pod from volumes and volumeMounts. ie., by name. Here in this example the value is “config”.
kind: Service
apiVersion: v1
metadata:
name: minikube-sample
spec:
selector:
app: minikube-sample
ports:
- protocol: TCP
port: 8080
nodePort: 30083
type: NodePort

---

apiVersion: apps/v1
kind: Deployment
metadata:
name: minikube-sample
namespace: default
spec:
selector:
matchLabels:
app: minikube-sample

replicas: 1
template:
metadata:
labels:
app: minikube-sample
spec:
containers:
- name: minikube-sample
image: minikube-sample:latest
imagePullPolicy: Never
ports:
- containerPort: 8080
env:
- name: env.namespace
value: default
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: minikube-sample

Deploy the application in to Kubernetes. Please see the steps from console

Now go to browser and test Rest API endpoint

RestAPI Response

The name and value above is picked from ConfigMap.

ConfigMap Reload Feature

Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration. The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related ConfigMap or Secret changes.

This feature is disabled by default and can be enabled using the configuration property spring.cloud.kubernetes.reload.enabled=true (eg. in the application.properties/yml file).

The following levels of reload are supported (property spring.cloud.kubernetes.reload.strategy): - refresh (default): only configuration beans annotated with @ConfigurationProperties or @RefreshScope are reloaded. This reload level leverages the refresh feature of Spring Cloud Context. - restart_context: the whole Spring ApplicationContext is gracefully restarted. Beans are recreated with the new configuration. - shutdown: the Spring ApplicationContext is shut down to activate a restart of the container. When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext and that a replication controller or replica set is configured to restart the pod.

For more details please visit here.

Now Let’s rework on same sample spring-boot application to make reloadable at run time without restarting the application.

To make it work we have to add restart enable and other configurations in bootstrap.yml

Lets rebuild the application with earlier steps like clean build and create docker image (For some reasons docker of windows version is not working properly in my laptop. So I am using minikube docker.)

Lets test Rest API Endpoint

Lets change configMap property values while the application is in running state.

Lets pull the logs

Observe the lines from highlighted to the end of it. When we changes the configMap manually, Kubernetes detected the change and reloaded the spring context gracefully.

Let’s hit again the Rest API endpoint. You will see the updated values.

Important things to keep in mind:

The view role on the service account is required in order to listen for config map changes.

kubectl create clusterrolebinding <view-name> --clusterrole=view --serviceaccount=<namespace>:default --namespace=<namespace>

The following levels of reload are supported (property spring.cloud.kubernetes.reload.strategy): - refresh (default): only configuration beans annotated with @ConfigurationProperties or @RefreshScope are reloaded. This reload level leverages the refresh feature of Spring Cloud Context. - restart_context: the whole Spring ApplicationContext is gracefully restarted. Beans are recreated with the new configuration. - shutdown: the Spring ApplicationContext is shut down to activate a restart of the container. When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext and that a replication controller or replica set is configured to restart the pod.

--

--

Eresh Gorantla
The Startup

Experience in Open source stack, microservices, event-driven, analytics. Loves Cricket, cooking, movies and travelling.