I was learning about micro services with spring boot and came across spring cloud config server which is used to exernalise application configuration.The advantage it state is that one can change the configuration without redeploying the application .Is it the only point of externalizing configurations ?
4 Answers
There are many reasons to externalize configuration. Changing configs without redeploying is a good reason for sure, but consider the impact of storing config settings in a text file in version control.
- Any config change will likely require a code review.
- Any person with read access to source control can view this information.
- Rendering configs unreadable to people involves an extra layer of encryption that must be taken into account.
- An emergency config change might be done on the files out on the servers. Production configs become out of sync with the version-controlled copies.
- And you need to remember this the next time you deploy the application so your version-controlled copy does not overwrite changes that support staff made... causing an emergency again.
In some organizations, separation of duties is an important objective. This is common in government, finance, defense, and healthcare industries. Any industry where security is a concern or laws dictate some of the development and maintenance process will likely require the developers and production support staff be different people.
By externalizing configuration you have greater control over who sees sensitive information like passwords, authentication tokens, URLs (yes URLs are sensitive information, because it can tell attackers who they can attack next if they cannot hack your system), and file system paths (I hope I don't have to explain why this is sensitive information).
Some additional benefits to consider:
- Most of these systems come with a GUI tool, which more people might be comfortable using.
- Increased automation. Many tools automate mundane tasks other than configuration. This forms the foundation of DevOps.
-
You could add that externalized configuration also makes it easier to have different settings (URLs, credentials, etc.) for different environments (develop, staging, production). Commented May 8, 2022 at 6:57
-
I might add that using externalised configuration server does not preclude keeping the source of truth about configuration in version control system (like Git for example). In fact, Spring Config Server lists Git as the very first configuration source and I would encourage taking full advantage of that whenever possible. Keeping your configuration version controlled has so many benefits, it would be foolish to throw it away … Commented May 21, 2022 at 6:44
-
@RolandTepp: perhaps I should clarify. I'm not advocating that version control should be abandoned for configs. I'm advocating that config changes should not require a code review. It certainly should require testing in pre-production environments, if possible. But config changes can circumvent some steps that application code changes shouldn't. Commented May 21, 2022 at 12:34
-
1@GregBurghardt, neither did I suggest that you did advocate against using source control for configuration. I just felt that it needed to be pointed out separately. As a side note, I want to clarify that when we I am talking about source controlled configuration, I do not mean that configuration should live alongside with the code it configures. It would be preferable to keep configuration close to the source that defines the infrastructure and deployment manifest of the application deployed to the environment. Commented May 22, 2022 at 16:27
-
@RolandTepp: "keep configuration close to the source that defines the infrastructure and deployment" — perfect way of describing that. Better words than I could come up with. Commented May 22, 2022 at 18:48
It all boils down to changing application behavior without rebuilding. But, the reasons you might do this have to do this are helpful to consider, and they can help you determine what values should be "configuration" for your particular application.
The software runs in many environments.
You might be running a service and have differences in your development, alpha, beta, and production environments, each with different logging levels, database backends, and an appropriate set of stage-appropriate services to interact with.
Or, you might deploy to several geographical regions or clusters, where each region/cluster needs its own resources, security keys, caching rules, or possibly even security or performance tweaks. You might have a deployment of your service running in a country that forces your service to use seaker encryption protocols, which may in turn mean you need a setting to flag those servers as "less secure", quarantine them, and prevent them from storing certain types of data.
Things that differ between environments and geographies are "configuration".
Someone else runs the software.
This is an extension of the first reason. But, you may not even know who's running the software, or have complete understanding of what they're using it for.
It could be a desktop application or service that someone else necessarily installs and runs. And, they will likely need to configure their own database server, GUI options, caching service or requirements, credentials, orchestration service, etc...
Things your users are allowed to tweak, as well as details you simply can't know about the runtime environment, are all "configuration".
One final point though: If you are in control of your application's deployment, and you have good visibility into all runtime environments, it's perfectly acceptable to bundle and deploy some aspects of your configuration alongside the app as code. You really just have to draw the line around things that must differ from machine to machine that cannot be derived programmatically.
The 12-Factor App is a good intro to building services, even if it predates the microservice craze. One of its core points is the difference between the software and a deployment/instance of this software.
External dependencies that might differ between deployments (e.g. credentials, hostnames, databases) should not be hardcoded. Similarly, committing config files like production.properties
or test.env
to the source code repository is typically an anti-pattern since it confuses the software's source code with its deployment. Instead, this configuration should be provided/injected by the deployment environment. Added benefits:
- In larger orgs, this also helps with separation of responsibilities: devs should not need access to production credentials.
- Configuration can be adjusted without having to go through the service's entire build process.
Thus, the application might take its configuration from environment variables. A central config server extends this idea, making it easy to manage multiple instances.
Having such a central config server does not necessarily make it possible to change the configuration on the fly without redeployment. It is typically necessary to restart an instance for new configuration to take effect. But with a central config server we can easily see the system's target state, and can be sure that once all instances have restarted they will use the new configuration.
Since there is a connection between managing instances/deployments and providing configuration, it is not necessarily appropriate to separate these by using an application-level configuration server. Configuration management is typically already part of orchestration systems such as Kubernetes or Docker. Internally, Kubernetes also uses a central configuration server (an etcd cluster). Thus, managing your own config server makes most sense when your system is large enough to have multiple instances, but not large enough to use a dedicated orchestration approach.
"The advantage it state is that one can change the configuration without redeploying the application"
This is a debatable advantage. I think the real advantages of externalising config are realised when you start to think about deploying configuration changes where there has been no code change eg.
- scaling with multiple instances of the same app.
- canary releases
- feature flags
In these kind of scenarios you potentially have no dev involvement at all but you want to ensure that all the instances of your deployed app get the same and correct configuration.
In the past you might have manged this by having the configuration stored as part of the deployment script, this means a new deployment would be done when the config changed enforcing all your change management controls are obeyed and a roll back possible.
But scaling up, toggling a feature flag etc these blur 'config', which I would term "anything that remains the same while the app is running", ie a connection string. and 'settings' which I would term "changeable options in the application", ie dark mode.
If you can externalise these with a third party admin interface, which has change control and authorisation levels lower than "redeploy everything" it gives you more flexibility.
The benefit of keeping everything as a config and requiring a redeploy is that you would assume that the app have been tested with that configuration and the deployment will enforce the change controls and a redeployment will not break the app or result in downtime.
The downside to splitting some of the config into "settings" is that you are maybe bypassing your change control, the app might not be tested with the new combination of settings and changing the setting while the app is running might break the app