Spring Cloud Config with Spring Boot Microservices
Objective
In this article we will see how to configure a secure Spring Cloud Config Server, backed with configuration files from a private GitHub repo. This server will be serving configuration to microservices built with Spring boot 2.x. This system will be extended further in next article where we will also include a spring cloud bus system to inform all the microservices about any config change in runtime and to update their state without downtime.
Setting up a git config repository
First, we will create a new repository in our GitHub account and checkout the branch in local system. Note that we are creating a private repository as shown below.
Generally, in any production ready project we have different configurations for different environments. Spring boot provides a wonderful way to manage this via “profiles” which we will be making use of in our microservices later. For this article, we will use a microservice which works on three profiles, dev, qa, prod.
After checkout we will create three ‘properties’ files, each representing separate environment mydbapplication-dev.properties, mydbapplication-qa.properties and mydbapplication-prod.properties. When using spring config along with ‘profiles’, you can setup your configuration file path and names in one of the patterns mentioned below. If you have common properties, read the notes section at the bottom of this article.
Each file may contain same property keys but you may set different values as shown below. After creating the files, commit and push it to remote branch.
mydbapplication-dev.properties
mydbapplication-qa.properties
mydbapplication-prod.properties
Now, we will create a ssh key for our github account using which our spring configuration server will connect to this repo to fetch configuration. Instead of using a SSH key, we can also use our password directly but that will mean that we have to save our plain text password somewhere which is not a good practice.To generate a ssh private and public key open terminal and paste the text below, substituting in your GitHub email address.
This creates a new ssh key, using the provided email as a label. When prompted to “Enter a file in which to save the key,” enter any filename,say, github. The file will be generated at the current folder of terminal. At the prompt, type a secure passphrase. Finally, you will have two files a private key (github) and a public key (github.pub). Now we will add the public key to our GitHub Account. Go to your account’s key page, press “New SSH Key” button and copy paste the content of your public key (github.pub) onto the form. Add any title you want, and press “Add SSH Key”.
Creating a Spring config server and connecting it with the git config repository
Fire up your IDE and let’s create a spring config server with maven. Out config server needs to be secure, so we will add a spring security component too. Add the following entries to your pom.xml
Your application should look like this
Your application.yaml of config server should have the following entries. I preferred a .yaml format for this application over .properties because it’s easier to maintain private key here
The property clone-on-start=true says that your config server will clone the git repo in local file system before starting the application, we will look into search-paths later. spring.security.user.xx properties are your config server security details, you will need to share this same details with all microservices connecting to this server.
There it is! your config server is ready. Start the application and try to access http://localhost:8000/mydbapplication/dev which should show you your applications dev profile configuration.
Creating microservices which connect to Spring config server
This one is pretty simple, first you will need to add the following dependencies in your pom.xml and configure our properties to use the config server
That’s it, now we can access the properties in your application using @Value. To test it out, let us create a rest controller to see the values and access it from http://localhost:8001/getDBValues
In the next part of this article, we will also include a spring cloud bus system to inform all the microservices about any config change in runtime and to update their state without shutdown.
Notes:
- If you have common properties across environment, you can use a file named {application}.properties. The property defined in this file will be overridden by any profile specific property file. An environment-specific properties will overriding the non-specific ones (like {application}.properties file).
- Another important thing to note is, if client’s active profile is not set (spring.profiles.active) the system will work with a profile named ‘default’ and will look for {application}-default.properties, so you can also set all your default or common properties in this file too. To summarize, any property in {application}.properties will be overridden by {application}-default.properties (if this file exist). If {application}-default.properties does not exist client will use values from {application}.properties. If spring.profiles.active is set, the profile specific file overrides any property values set by {application}.properties and {application}-default.properties but inherits non common properties.
- In our cloud config server, we looked at a property ‘spring.cloud.config.server.git.search-paths’. This is useful in cases where your properties files are not at the root of your repo OR you want the server to navigate at some folder to find the property files, you can also use placeholders like {application} or {profile} or some folder name like “AllApplicationProperties”. In fact, this property is an array, so you can add more folder/paths separated by a comma, you can even use regex syntax.
- In case you want your client applications to fail startup if they are unable to connect to the config server, set spring.cloud.config.fail-fast=true
- Look into spring.cloud.config.retry if you want your clients to retry connection in case of failure
Git repo: