Kubernetes ConfigMap & Secret for Storing Spring Boot Properties

Fauzan
4 min readJul 28, 2019

When you build a Spring Boot Project, it will create a “JAR” artifact with the properties included in it. It seems good as it becomes portable. But there’s a concern when it’s live on the production. The configuration cannot be seen from the server. When something bad happened and operations need to make sure that the application properties is the right one, you cannot just see on the /main/resources. And you need to rebuild the project again to make sure that it’s not because of the wrong properties.

So instead of placing the configuration inside the artifact, I prefer to externalise the project properties where I can exactly see what the exact properties is being used on the server. Because I use Kubernetes and Docker, I have 2 options, on the docker layer (still outside the artifact), or on the Kubernetes layer, which maybe you have heard about ConfigMap, if you’re familiar with Kubernetes. The difference of that 2 options is if you place the properties on the docker layer and you want to change the properties, you need to rebuild the docker image again, and push to the Kubernetes Cluster to update the existing Kubernetes Deployment. But when you place the properties on the ConfigMap, in case you want to change it, you can directly change the right ConfigMap and refresh the Kubernetes Deployment then it will use the new edited properties.

What else? You can use the same docker image to all of the cluster (environment), you can adjust the right ConfigMap (properties) on the each cluster, if you place it on docker layer, then you need different docker image each cluster.

To implement this you need to add Spring Cloud Kubernetes to your project. Add this to your pom.xml

And still, you need to add at least this properties in order to this integration working properly.

Remember that, the spring.cloud.kubernetes.config.name should be same as the ConfigMap that we will create, and spring.cloud.kubernetes.config.namespace should define which Kubernetes Namespace you will deploy your App on.

Now from the Kubernetes side, you need to give cluster-admin authorization to default service account first so the app can access the resource on the Kubernetes Cluster. Apply this ClusterRoleBinding manifest

kubectl apply -f default-cluster-role-binding.yaml

Next we can create the project properties on the Kubernetes ConfigMap manifest like this. You can adjust the properties as your project needs

If you want to put more than one properties, add it like this

Moreover, in some cases like environment variable, db host and db password that should be different on each Cluster, instead you edit the the properties to adjust variable every time, you can use ConfigMap variable for the ConfigMap itself. So your ConfigMap Properties can be used on any Cluster dynamically. And you can protect sensitive information like Password on the Kubernetes Secret. Check example below

Before we can use properties like that, we need to create that variable in Kubernetes ConfigMap and other sensitive variable in Kubernetes Secret first. And then mount that variable on Kubernetes Deployment of the Spring Boot project.

Costumise the variable for each cluster and apply it

kubectl apply -f globalenv.yaml

For Kubernetes Secret, you need to encode the variable with base64 first. You can create with simple command like this

echo -n 'devdbpasswd' | base64
ZGV2ZGJwYXNzd2Q=

And create Kubernetes Secret like this one

kubectl apply -f globalsec.yaml

After all environtment variables have been stored on Kubernetes. I last thing to do is inject it to the Kubernetes Deployment of your project

kubectl apply -f kubernetes-deployment-with-variable.yaml

This is what your spring boot would look like if the projects successfuly inject properties on the configmap to the container

.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)

2019-Jul-29 16:58:31 PM [main] INFO org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration - Located property source: CompositePropertySource {name='composite-configmap', propertySources=[ConfigMapPropertySource {name='configmap.app-name-example.default'}]}
2019-Jul-29 16:58:31 PM [main] INFO org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration - Located property source: SecretsPropertySource {name='secrets.app-name-example.default'}

That’s all !

Maybe it seems to complicated for the first. But I think all of that configuration can be added to your CI/CD tools. In my cases I use Jenkins, I automate almost the configurations above so I don’t spend much time doing the same thing repeatedly.

Please don’t hestitate to comment and share your view point below.

Thanks!

--

--