Centralized Configuration Spring Application on Kubernetes
A couple months ago, Spring Cloud Kubernetes project has been graduated from the incubation process. The project provides Kubernetes integration with Spring Cloud. For those who are not familiar with Kubernetes, you can look at this article, and this, for introduction, and you can start interactive tutorial here.
Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems. [source]
One of the functionalities is integration with the Kubernetes ConfigMap.
In general, spring application configuration is created using files (e.g. properties, yaml). There is no problem with this way, until we have many service instances. Only one value changes, then the configuration should be distributed to all service nodes and… restart the services. Another problem can occur if you deploy the service uses container (e.g. Docker) and you save the configuration file in it, then you have to re-build the container image (I don’t think anyone will do this 😅).
If you don’t deploy the service to Kubernetes, then you can use Spring Cloud Config or using Consul for Distributed Configuration. But… when your service is deployed to a container and with container orchestration (in this case Kubernetes) for its management, it would be nice to try Kubernetes ConfigMap for centralized configuration.
This time, I want to share my experience trying this project, at least as far as I have learned until today.
First of all, you have to install minikube and kubectl so you can run Kubernetes on your local development machine. Next…
Start Minikube
You can start Minikube by just entering minikube start
command. Because you run Kubernetes on the local machine, you have to make Kubernetes reusing your Docker daemon by entering eval $(minikube docker-env)
command, as this means you don’t have to build a docker registry on your host machine and push the image into it — you can just build inside the same docker daemon as Minikube which speeds up local experiments.
Create ConfigMap
Next, create your configuration using ConfigMap. You can create Kubernetes object spesification definition (including ConfigMap) all in command line (like in interactive tutorial) or create yaml file, and execute kubectl create -f filename
command. I prefer to use files because it can be included into version control.
Above is an example of a yaml file to create a ConfigMap. Fill data
property with the contents of the application.properties
that we usually use, and then execute kubectl create -f ConfigMap.yaml
command.
You can check the list and content of ConfigMap with the command as shown above.
Create Role
Next, create role for the namespace (in this case, default namespace), if not, then the config taken will be null, or if you use other integration such as service discovery, it will receive a forbidden response.
Project Setup
Make sure to add some dependencies to your spring-boot project. I used 2.0.5.RELEASE for the parrent.
- spring-boot-starter-web
- spring-boot-starter-actuator
- spring-cloud-starter-kubernetes-config
- lombok
if you use maven, see code below…
application.properties
Even though all application configurations already exist in the ConfigMap, at least we need configuration for integration with Kubernetes.
spring.cloud.kubernetes.reload.*
configs are for configuring the ConfigMap auto reload method, and management.endpoint.*
are to configure the actuator.
Object Mapping for Configuration in ConfigMap
Actually, you can use the old method with @Value("${myconfig.properties1}")
but this cannot be auto-reload. To be able to make it auto-reload, create POJO for mapping content in ConfigMap.
and add @Configuration
annotation and @ConfigurationProperties(prefix="myconfig")
annotation, the prefix here is adjusted to the content in the ConfigMap.
Test the Configuration
To use the configuration, just inject Object from the Class that has been made before, using @Autowired
.
Next, you can try it directly without deploying it to Kubernetes, because Spring Cloud Kubernetes has the Transparency feature.
All of the features described above will work equally well regardless of whether your application is running inside Kubernetes or not.
But, before you run your application, you must have an environment variable named KUBERNETES_NAMESPACE containing the namespace name that you use.
export KUBERNETES_NAMESPACE=default
Test Result
The picture above shows the results of the HTTP API that was created previously to display the config.
Deploy to Kubernetes
First, build your docker image, you can see my story about Dockerize Your Java Application for more detailed step.
After your image is ready, then it’s ready to deploy. Next…
Create Controller, i choose Replicaset
Create a Service.
Next, test using Service port.
Full source code is available on my Github page.
Are you looking for any information about remote work?
or have a cool resource about remote work?
remotework.FYI is all you need to know about remote work, find and share cool resources right now.