☁️Cloud App Config Externalization. No more Restarts & ReDeployments!

Using: Spring Cloud Config through Kafka.

📚 Introduction:

Many Spring-based Java applications do have configuration properties. They might have been written in YML files or property files. Good citizens choose the .yml to avoid word repetition and so for better readability. Apart from this,

  1. These properties live inside the application under resources maven structure in general.
  2. When we do have a change in these configuration files, the correspondent application requires a repackage and redeployment in non-local environments. In the case of the local environment, we will just restart as it auto deploys to the embedded server.

Imagine when you have multiple microservices, frustration arises with deployments, every time when a simple configuration is changed.

This article explains how to avoid these redeployments, restarts, and use-cases that it addresses:

🎭 Use Cases:

  1. Organize well: Grouping by application and environment. Control from a centralized GitHub storage.
  2. Runtime Behavior: When we need to modify the runtime behavior of the application upon changing the configurations.
  3. Auditing: Keep track of who is modifying the configurations and what configurations are modified from the platform or product perspective.
  4. Enables to deploy the same application with CD(no CI) only and group the nodes as a single cluster and then make these clusters to exhibit a configuration driven behavior. Example: When a single common service needs to deal with multiple lines of business, the same app can be deployed across multiple clusters and each cluster can be tweaked at runtime dedicated to a line of business functionality. This reduces the maintenance cost in terms of packaging and deploying to each line of business and enables the power of divide and conquer controlling of the service. Saves time and avoids human error-prone.
  5. Enables multiple instances of the same distributed application inside a cluster, react to a configuration change in the same fashion from a single location.
  6. Enables to alter the behavior of the service(s) during runtime whether it is a single node deployed or multi-node deployed.

📖 Solution:

The Architecture — Explaining how the Config Server and Clients work together

There are 3 pieces to observe from the above architecture diagram.

  1. Config Client: It's your application that had an additional build dependency as below. When the application starts it queries the config server for configurations and bootstrap further. Supply the name of the application and Config Server URL to identify the properties that the application can query for.

2. GitHub: A central storage location, where we create a repository only to maintain the configurations. Create folders for each of your services and store your yml/properties files underneath. Organize at your best. I bet you know.

3. Cloud Config Server: is responsible to observe the changes coming from the github on every commit. This service has the following build dependency

👮 Security:

Security served in terms of encryption and decryption. There are two different types of techniques:

  1. Symmetric: Uses a shared key. Supply a key in bootstrap.properties and start the config server. Example: encrypt.key=GOPI_TEST_ALPHA_NUMERIC_KEY. Now we can encrypt and decrypt the individual properties using the rest calls http://localhost:8888/encrypt -d mypassword. Now we need to make the property prefixed with {cipher} inside your properties file using the outcome of the above rest call.
  2. Asymmetric: Is stronger than Symmetric as we need to generate an encryption key. We need to use the JCE for this technique. Using the keytool from JDK we need to generate keystore file which contains the keys to encrypt and decrypt the configurations.

We can convert the PKCS12 using a simple command.

finally set the bootstrap.properties file pointing to the keystore file:

So the encrypting and decrypting the property is same across the techniques.

Check out the sample code from Github.

So by running the above applications, the following things should have been observed.

  1. Make sure the “Config Server ” is started before the clients.
  2. Start the “Service One” Application for a couple of times running on different ports to mimic multiple instances of the same application.
  3. Observe the @RefreshScope inside the Client for the model which can pick up the configuration changes.
  4. Make sure your local kafka is running and if you need SSL connectivity, uncomment the secured properties under resources.
  5. Make Sure to run the localhost:8080/actuator/bus-refresh on any one of the client instance. All Instance will get updated with the latest configuration changes then from “Config Server”. Wondering how it works? The instance received the request to update will push an event over the bus and all the consumers will listen to it including itself who published the event and all of them pulls the changes from “Config Server”
  6. If you are not seeing the expected changes means, “CloudServer” has missed the connectivity with the GitHub Repo. Enable the debug logs to trace.
  7. The reason for bus refresh is to update all the distributed instances of the same application running across the cluster(s). If it is a single node deployed or not a distributed application, running the actuator/refresh is sufficient enough and we can take out the bus dependency.

Find the publication here: https://medium.com/thinkspecial

Gopi Krishna Kancharla- Founder of http://allibilli.com

--

--