Spring Cloud Config vs Kubernetes ConfigMap — Detailed Comparison
Table of contents
Introduction
We can face many challenges when working on any project. These challenges start from clean code and going on to the high availability of the system. During all phases of the product development we always try to implement the best practices (at least we should :) ) and there are dozens of articles about these concepts on the internet. So I’ll also try to contribute to this topic in the aspect of configuration management and externalization.
In this article, I’m going to deep dive and compare the popular solutions from two different areas: Spring Cloud Config from Spring framework and ConfigMap from Kubernetes.
Before proceeding, It’s also worth mentioning that there is usually no ideal solution that fits all scenarios for these types of architectural challenges and we should carefully consider a lot of general points such as the current state of the system, the business requirements, the team size and etc. I mean, while one solution works well for a certain project could be useless for others. So I’ll try to mention the pros and cons of both technologies through the examples and hope it'll give you a brief overview in your further opinions.
At last, based on my previous experience, we should not rely on a certain technology just because It’s currently fashionable or used by many others. Implementing redundant solutions to the simple problem will just bring more complexity to the system and lead to the over-engineering problem.
Spring Cloud Config
Spring Cloud Config currently provides client-side and server-side support for configuration externalization and management for distributed systems. I’m not going to show the setup process for Spring Cloud Config from scratch as there are already plenty of resources on the web. Some of the links that were useful for me:
- https://cloud.spring.io/spring-cloud-config/reference/html/
- https://www.baeldung.com/spring-cloud-configuration
- https://www.baeldung.com/spring-cloud-bus
In general, we’ll go through the below steps in order to make Spring Cloud Config up and running:
- Create a Git repository to store our configuration files for different environments and profiles. (actually, we could use the file system instead but It’s recommended to use Git for production purposes)
- Create and start a new application that will work as Spring Cloud Config Server. We should add Spring Cloud Config dependencies, set up the Git repository URL and give accesses and do other necessary bootstrapping works so our application becomes config server. It’ll read the configuration files from the Git repository and expose them as REST endpoints to its clients when we start the config server.
- Configure the client applications that will read properties from the Config Server. These configurations include adding Spring Cloud Config Client dependencies and setting up the config server URL in the client applications. So after starting the config client applications they will read their configurations from the config server (at least they will try).
Although everything looks ok at this time, we need to do extra works in order to complete the procedure. I mean, we should dynamically inform the client applications if there are any changes on the properties files. Otherwise, we should restart the application context to refresh the updated property values each time and I think you already know why It’s a bad approach.
So as the next steps:
- Setup and start a message broker server (ex.: RabbitMQ, Kafka) so the Config Server could send messages to its clients about the update events on configuration files.
- Configure the client applications and add Spring Cloud Bus and Actuator dependencies that clients could receive the update messages from Config Server.
After all of these steps, our Config Server is ready and we can externalize our configurations. The final overview of the system looks like this:
Kubernetes ConfigMap
The ConfigMap object that comes with Kubernetes (aka K8s) is also an optimal solution to separate our configuration from the application. Also taking into account that the Spring framework has already plenty of libraries to ease the integration of the Spring applications to the Kubernetes, ConfigMap looks like a good candidate to use with the Spring environment.
Again, instead of going into the integration details between Spring and K8s ConfigMap at the code level, I’ll provide some useful links below so we could proceed to the general steps:
- https://developers.redhat.com/blog/2017/10/03/configuring-spring-boot-kubernetes-configmap#setup
- https://capgemini.github.io/engineering/externalising-spring-boot-config-with-kubernetes/
- https://www.baeldung.com/spring-cloud-kubernetes#config_maps_springcloudk8
I consider there is already a working K8s cluster and not include It in the below steps. So we will:
- Create the ConfigMap object inside the Kubernetes cluster and assign the property values to the ConfigMap. Properties can be assigned from either file, directory or directly from key-value literals.
- Configure the client applications — add Spring Boot Kubernetes Client and Actuator dependencies. Then we should set the ConfigMap names in the application properties.
Also, we don’t need any additional components in order to hot-reload the application properties that come from ConfigMap because It’s already considered in the Kubernetes Client implementation in the Spring framework and the beans annotated with RefreshScope or ConfigurationProperties will dynamically refresh the values without the need to restart the whole context.
Now our application will read its values from ConfigMap when deployed to the K8s and the final overview will look like this:
Spring Cloud Config — PROS
- Since there are already ready solutions provided by Spring Framework, It’s relatively easy to integrate the Spring Cloud Config to the other components if we already use Spring technologies in our ecosystem.
- It provides centralized management for the configurations. So, we can manage all of our properties from the Git repository. (It’s not possible with ConfigMap and we should control each ConfigMap across different clusters separately. But please correct me if I’m wrong)
- It provides encrypt/decrypt possibilities to store the sensitive data in the configuration files. (It’s not recommended to store the sensitive data in ConfigMap, instead, we should use Secrets)
- It’s a mostly developer-oriented solution — developers can directly update the configuration values from Git and there is no need for DevOps (or other members that are responsible for the system) to connect to the remote server and update the configurations.
- Since we store the properties in a Git repo, it's a common place for storage, as well as, to save the changes history.
Spring Cloud Config — CONS
- It will lead to some challenges if we’re going to use technologies other than Java (generally other than Spring) for integration with Spring Cloud Config Server. Although, Config Server provides REST endpoints to access the properties, let’s admit that no one will implement a client integration from scratch in its NodeJs application for the Config Server.
- The main downside is, as we see from the above overview, we need three different applications/servers that should be up and running all the time (Git server, Config Server application, Message Broker server) in order to use the Spring Cloud Config. Considering that, every time we add a new component to the system will create a new stress point, potential bugs and require additional monitoring, It could be not an option to use Spring Cloud Config in certain scenarios.
- Adding new components requires additional development and resources.
Kubernetes ConfigMap — PROS
- Regardless of your languages or technologies in the system, ConfigMap could fit them easily because It’s language independent and can be integrated for every technology that uses external configurations.
- It’s mostly a DevOps-oriented solution — considering that the post-development processes are handled by DevOps (or other members that are responsible for the system) in most companies, It may be more suitable for them to update/change configurations as well.
- There is no need for additional components in order to notify the clients about the configuration updates as we can handle it with a little workaround in the client applications.
- It’s relatively easy to set up the configuration externalization and we’ll do less work comparing with Spring Cloud Config as the ConfigMap is “native” for Kubernetes.
Kubernetes ConfigMap — CONS
- As we noted above It’s mostly suitable for DevOps people and if we need the developers to update the configurations It could be negotiable to give access to the K8s environment for the development team members.
- We should choose a new solution to the configuration management If we decide to move from Kubernetes at some point because as we already know, the ConfigMap is part of the Kubernetes.
- Kubernetes does not provide centralized management for all of its ConfigMaps across different clusters/environments/servers.
Summary & Conclusion
Even though we’ve been using Spring Cloud Config on production for a long time, after investigating about ConfigMap and its features we decided to smoothly switch to the ConfigMap. As the system grew, supporting and monitoring the different components of the Config Server became a headache in our situation, and new deployments were delayed if one of these components were unavailable for a time.
I hope the above comparisons will give you a brief overview of both solutions and will help with your further decisions.
Happy engineering! :)