Cloud Bits: Decouple Configuration from Code

person holding airplane control panel

Now both Name Service & Greeting Service maintain some configuration which they use for processing the request. In our case the configuration for Name Service is the value of name used for greeting & configuration for Greeting Service is the value of greeting in different locales. An example of this can be

greetings:
    en: Hello
    es: Hola
    fr: Bonjour
    cn: Nǐ hǎo
    jp: Kon'nichiwa

Let us consider a scenario where we start supporting a new locale for our Greeting Service or we discover a bug which is leading to incorrect greeting value for certain locale(Eg we missed an o in en greeting & now customers are seeing Hell ${customer} in the response). If the configuration lives within the application code then we have no other choice than to redeploy the service with our code fix even though in our case the fix can be as simple as setting the correct value of a greeting. This also means the incorrect behavior will be extended for the period in which we are doing the redeployment.

Now if we really consider the config for Greeting Service, it has nothing to do with our service logic. We don’t really care what does the configuration contain & our service flow won’t change based upon what value the config contains. What we really want is an easy mechanism to update the configuration which is independent of our service deployment. So when we notice an incorrect value for our configuration, we just update its value externally without having to redeploy our service to reflect the correct value. With the configuration being externalized our updated architecture looks as below

Exploring techniques for configuration externalization

There are various ways to store & update your external config. Some of them are:

  • Version control based configuration
  • Filesystem based configuration
  • Kubernetes ConfigMaps

All mainstream frameworks provide support for these mechanisms. We are going to look at how we can achieve this using Spring framework. Before diving in let us address another challenge which is pretty evident with our architecture. Right now every service is maintaining its own externalized configuration. This will become pretty challenging once we have to maintain large number of services. Having a centralized way to store & retrieve these configurations can easily abstract away the task of configuration management from our services.

In Spring ecosystem, Spring Cloud config server plays the role of this centralized system. We are going to see it in action while working with both file system as well as version control based configuration. Our updated architecture looks as below:

File system based configuration

Lets start with the simplest mechanism which is the filesystem based configuration. We store the configuration for our services in a filesystem & services can access it during run-time. Now whenever we need to change our configuration, we just need to update the configuration in file system & the config server will pick up the changes. We can now either manually refresh the config for our services by calling an administration endpoint (/actuator/refresh in case of Spring) or have our services listen for changes in configuration.

Lets go through a demo where our config lives on local file system on path ~config/config.yml. We can see that we have mistakenly checked in an incorrect value for greeting config & now when user calls our service they get Hell instead of Hello which is not so much of a greeting.

Now that we have externalized our configuration to a file system, we can just update the config value in the file system & our config server will pick it up. Once it has updated the config, all the services listening for config changes will be able to read the updated value. In our case it is the greeting service & we can see in the demo that it receives a refresh event & we can now see the correct greeting for our endpoint.

You can find all the code for the file system demo on this branch.

Version control based configuration

ConfigMaps

Now when we enter into the Kubernetes world, we no longer need a Spring based config server as ConfigMaps can perform the role of central config storage. All you need to do is to define your config in the ConfigMap & mount the volume on your service pods for them to access the underlying config.

Now when you want to change the config, you can just patch the config or re-apply the yml file for config & your service pods will have access to the updated config. You can achieve this either by invoking the refresh endpoint or make use of Spring Cloud Kubernetes Configuration Watcher to automatically refresh the config.

You can find all the code for ConfigMap based config on this branch.

Externalizing your application config provides multiple benefits. You can change the application behavior at runtime without doing a fresh deployment. You can also have separate configuration for different environments which can be picked up at run-time using something like a Spring profile. You also get better control over resolving issues which happen due to misconfiguration as now you have decoupled your application from your configuration.

Hope that this was helpful to you. Next I will be covering service registry pattern by doing similar demo using Spring framework. Till then happy learning!

Leave a Reply

Your email address will not be published. Required fields are marked *