A demo Spring Boot application that demonstrates on using Kubernetes ConfigMaps to configure Spring Boot application.
-
You might need an access to Kubernetes Cluster to play with this application. The easiest way to get local Kuberentes cluster up and running is using minikube
-
Install Spring Boot CLI
-
Untar/Unzip Spring Boot CLI 1.5.7.RELEASE and add it your path
Note
|
The rest of the document assumes you have minikube up and running |
For the demo purpose we will be creating a simple Spring Boot project,
spring init --artifactId=spring-boot-configmaps-demo \
--name="Kubernetes:: Spring Boot:: Demos :: ConfigMaps Demo" \
--groupId="com.redhat.developers" \
--package-name="com.redhat.developers" \
--dependencies=web,actuator,lombok \
--extract spring-boot-configmaps-demo (1)
cd spring-boot-configmaps-demo
./mvnw io.fabric8:fabric8-maven-plugin:3.5.30:setup (2)
-
Creates a Spring Boot project with web and actuator dependencies
-
Adds the fabric8-maven-plugin to the project that will help with deploying the application on Kubernetes
The complete demo sources is available here
The directory spring-boot-configmaps-demo will be referred to as $PROJECT_HOME throughout this document.
package com.redhat.developers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class GreeterController {
@GetMapping("/greet/{user}")
public String greet(@PathVariable("user") String user) {
String prefix = System.getenv().getOrDefault("GREETING_PREFIX", "Hi"); (1)
log.info("Prefix :{} and User:{}", prefix, user);
if (prefix == null) {
prefix = "Hello!";
}
return String.format("%s %s! Welcome to Configuring Spring Boot on Kubernetes!", prefix, user);
}
}
-
The application looks for the prefix from an environment variable called GREETER_PREFIX
Lets create a Kubernetes ConfigMaps to hold the property called greeter.prefix
,
which will then be injected to Kubernetes deployment via an environment variable called GREETER_PREFIX
kubectl create configmap spring-boot-configmaps-demo --from-literal=greeter.prefix="Hello" (1)
kubectl get configmap spring-boot-configmaps-demo -oyaml (2)
-
Creates a configmap called
spring-boot-configmaps-demo
which will have property calledgreeter.prefix
with a value "Hello" -
Displays the ConfigMap called
spring-boot-configmaps-demo
as yaml
Example output of kubectl get configmap spring-boot-configmaps-demo -oyaml
apiVersion: v1
data:
greeter.prefix: Hello
kind: ConfigMap
metadata:
creationTimestamp: 2017-09-19T04:03:37Z
name: spring-boot-configmaps-demo
namespace: default
resourceVersion: "50671"
selfLink: /api/v1/namespaces/default/configmaps/spring-boot-configmaps-demo
uid: 8397deb7-9cef-11e7-9b8d-080027da6995
As the application is configured to use fabric8-maven-plugin, we can create Kubernetes deployment
and service as fragments in $PROJECT_HOME/src/main/fabric8
. The fabric8-maven-plugin takes
care of building the complete Kubernetes manifests by merging the contents of the fragment(s) from $PROJECT_HOME/src/main/fabric8
during deploy.
Create a file called deployment.yaml in $PROJECT_HOME/src/main/fabric8
with the following contents,
spec:
template:
spec:
containers:
- env:
- name: GREETING_PREFIX (1)
valueFrom:
configMapKeyRef: (2)
name: spring-boot-configmaps-demo (3)
key: greeter.prefix (4)
-
Define Environment variable called GREETING_PREFIX
-
Defines that the value will be a ConfigMap reference
-
Name of the ConfigMap from where to look for the key/value pair, this should be same name you have used in Create ConfigMap
-
The property key inside the ConfigMap, whose value needs to be assigned to environment variable GREETING_PREFIX
To deploy the application execute the command ./mvnw clean fabric8:deploy
. The application deployment status can be
checked using the command kubectl get pods -w
To access and test the application execute the following command,
curl $(minikube service spring-boot-configmaps-demo --url)/greet/jerry; echo "";
The above command should display a message like Hello jerry! Welcome to Configuring Spring Boot on Kubernetes!
Note
|
minikube service spring-boot-configmaps-demo --url is used to get the service url and port via which we can access
the application
|
In ConfigMap Properties as Environment Variables we saw how Kubernetes ConfigMaps can
be injected to the Kubernetes deployment as environment variables. In this section we will see how we can mount
Spring Boot application.yaml
using ConfigMaps.
Add a property called greeter.message
to the $PROJECT_HOME/src/main/resources/application.properties. The modified file
is as shown below,
greeter.message=%s %s! Spring Boot application.properties has been mounted as volume on Kubernetes!
cd $PROJECT_HOME
kubectl create configmap spring-app-config --from-file=src/main/resources/application.properties (1)
-
This is similar to creating ConfigMap but instead of literal we will now put the entire file
application.properties
in a configmap called spring-app-config
To see the contents of the ConfigMap, execute the command kubectl get configmap spring-app-config -oyaml
, a sample output
is shown below,
apiVersion: v1
data:
application.properties: greeter.message=%s %s! Spring Boot application.properties has been mounted as volume on Kubernetes!
on Kubernetes!
kind: ConfigMap
metadata:
creationTimestamp: 2017-09-19T04:45:27Z
name: spring-app-config
namespace: default
resourceVersion: "53471"
selfLink: /api/v1/namespaces/default/configmaps/spring-app-config
uid: 5bac774a-9cf5-11e7-9b8d-080027da6995
Modify the GreeterController
to use the greeter.message
, the modified file looks as shown below
package com.redhat.developers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class GreeterController {
@Value("${greeter.message}")
private String greeterMessageFormat; (1)
@GetMapping("/greet/{user}")
public String greet(@PathVariable("user") String user) {
String prefix = System.getenv().getOrDefault("GREETING_PREFIX", "Hi");
log.info("Prefix :{} and User:{}", prefix, user);
if (prefix == null) {
prefix = "Hello!";
}
return String.format(greeterMessageFormat, prefix, user);
}
}
-
Injects the property
greeter.message
which has been defined inapplication.properties
Kubernetes ConfigMaps can be mounted as volumes inside the deployments.
Update the $PROJECT_HOME/src/main/fabric8/deployment.yaml with the following contents,
spec:
template:
spec:
containers:
- env:
- name: GREETING_PREFIX
valueFrom:
configMapKeyRef:
name: spring-boot-configmaps-demo
key: greeter.prefix
volumeMounts:
- name: application-config (1)
mountPath: "/deployments/config" (2)
readOnly: true
volumes:
- name: application-config
configMap:
name: spring-app-config (3)
items:
- key: application.properties (4)
path: application.properties (5)
-
Define a Volume mount and give it a logical name
-
Define mountPath, location inside container where the file will be mounted
-
The ConfigMap to be used, this name should be same as defined in ConfigMap from file
-
The property key from ConfigMap to be used as a content of file
-
The sub path within location defined, in this case it will be
/deployments/config/application.properties
Deploy and Access the Application to see the application.properties
loaded and used from ConfigMaps via
container volumes.
When you access the application you will notice the response to be Hello jerry! Spring Boot application.properties has been mounted as volume on Kubernetes!
Tip
|
To check if the volume has been mounted execute the command, kubectl exec spring-boot-configmaps-demo-3812387281-f566v -- cat /deployments/config/application.properties (1)
|