《Continuous Delivery》 Notes 2: Configuration Management
What is Configuration Management?
Configuration Management refers to the process by which all artifacts relevant to your project, and the relationships between them, are stored, retrieved, uniquely identified and modified.
As a good configuration management strategy, we can implement the following things.
- We can exactly reproduce any of the environments, including the version of the operating system, its patch level, the network configuration, the software stack, the application deployed into it and their configuration.
- We can easily make an incremental change to any of these individual items and deploy the change to any, and all, of the environments.
- We can easily see each change that occurred to a particular environment and trace it back to see exactly what the change was, who made it, and when they made it.
- We should be satisfy all of the compliance regulations that we are subject to.
- It is easy for every member of the team to get the information they need, and to make the change they need to make.
We need to consider the following things for configuration management.
- Get everything into version control.
- Manage dependency.
- Manage an application's configuration.
- Configuration management of whole environments.
The aim of a version control system:
- it retains and provides access to every version of every file that has ever been stored in it.
- it allows teams that may be distributed across space and time to collaborate.
Keep absolutely everything in version control
Every single artifact related to the creation of your application should be under version control.
It is also important to store all the information required to re-create the testing and production environments that your application runs on.
It is even useful to keep the configuration files for the development team's development environments in version control so that everyone on the team can share the same setting.
Many projects may store binary images of their application servers, compilers, virtual machines and other parts of their toolchain in version control, this is fantastically useful.
Some projects may store the output of the application to version control, it is not recommended, as we may run deployment pipeline many times, for each time, it will create the binary files, if we store all the binary files, it does not make sense.
Check In Regularly to Trunk
As check in will trigger deployment pipeline, so we need to check in on a reasonable frequent regular basis.
We need to run commit test before we perform check in.
We do not recommend branch and trunk strategy, reason as:
- It is antithetical to continuous integration, since the creation of a branch defers the integration of new functionality and integration problems are only found when the branch is merged.
- If several developers create branches, the problems increases exponentially, and the merge process can become absurdly complex.
- Although there are some great tools for automated merging, these do not solve semantic conflicts.
- It becomes very hard to refactor the codebase.
Use Meaningful Commit Messages
The most important reason to write description commit messages it that when the build breaks, you will know who broke the build and why.
When we try to debug a complex problem under a tight deadline, the scenario as below.
- You find a bug that is down to a rather obscure line of code.
- You use your version control system to find out who put in that line of code and when.
- That person is off on holiday or has gone home for the night, and left a commit message that said "fixed obscure bug.".
- You change the obscure line of code to fix the bug.
- Something else breaks.
- You spend hours trying to get the application working again.
It is a dispirited experience.
For a meaningful commit description, it can includes several paragraph.
- first paragraph is a summary about this commit.
- following paragraph is about some details on what you did.
Manage Dependencies
Manage External Libraries
External libraries usually come in binary form, and we can download it from network.
Also we can maintain a copy of the libraries locally.
Whether you keep external libraries in version control or not involves some trade-offs, it makes much easier to correlate versions of your software with the versions of the libraries that were used to build them. However it makes version control repositories bigger and check-outs longer.
Manage Components
It is good practice to split all but the smallest applications into components.
Typically you would start off with a monolithic build creating binaries or an installer for your entire application in one step.
It is important to have binary dependencies between your pipelines rather than source dependencies.
Some CI servers do a pretty good job of managing dependencies, but it makes harder to reproduce the entire end-to-end environment.
Managing Software Configuration
We should treat application configuration in the same way as you treat the source code.
Configuration and Flexibility
The desire to achieve flexibility may lead to common antipattern of "ultimate configurability".
Configuration information is somehow less risky to change than source code, and most configuration information is free-form and untested. so we need to store it in version control.
When we develop a new application, it is almost always better to focus on delivering the high-value functionality with little configuration and then add configuration options later when necessary.
Types of Configuration
Configuration information can be injected into your application at several points in your build, deploy, test and release process.
- Your build scripts can pull configuration in and incorporate it into your binaries at build time.
- Your packaging software can inject configuration at packaging time, such as when creating assemblies, ears or gems.
- You deployment scripts or installers can fetch the necessary information or ask the user for it and pass it to your application at deployment time as part of the installation process.
- Your application itself can fetch configuration at startup time or run time.
Generally we consider it bad practice to inject configuration information at build or packaging time.
It is usually important to be able to configure your application at deployment time so that you can tell it where the services it depend upon, i.e. the database, message queue.
It is important that we should try and supply all configuration information for all the applications and environments in your organization through the same mechanism, so that we can treat every environment in the same way.
Managing Application Configuration
We need to consider the following questions.
- How do you represent your configuration information?
- How do your deployment scripts access it?
- How does it vary between environments, applications and versions of applications?
There are some obvious choices for where to store your application configuration.
- Database
- Version Control System
- Directory
- Registry
It is important to keep the actual configuration information specific to each of your application's testing and production environments in a repository separate from your source code. usually the separation is particularly relevant for security-related configuration.
Please note do not check any confidence information such as password into source control or hard-code them in the application.
Each configuration setting can be modeled as a tuple, it contains the following three things.
- The application
- The version of the application
- the environment it runs in
When we consider application configuration, we need to think about the following things.
- Adding a new environment.
- Creating a new version of the application.
- Promoting a new version of your application from one environment to another.
- Reloading a database server.
- Managing environments using virtualization.
How to test system configuration?
- Ensure that reference to external services in the configuration settings are valid.
- Run some smoke tests once your application is installed to make sure it is operating as expected. Ideally these tests should stop the application and fail the installation or deployment process if the results are not as expected.
Managing Configuration across Applications
We need to keep a catalogue of all the configuration options that each of your application has, where they are stored, what their life cycle is, and how they can be changed.
It is especially important to have access to the configuration on a real-time basis when your applications depend on each other and deployments must be orchestrated.
Configuration management of every application should be planned as part of project inception.
Principles of Managing Application Configuration
- Consider where in your application's lifecycle it makes sense to inject a particular piece of configuration.
- Keep the available configuration options for your application in the same repository as its source code, but keep the values somewhere else.
- Configuration should always be performed by automated processes using values taken from your configuration repository, so that you can always identify the configuration of every application in every environment.
- Your configuration system should be able to provide different values to your application.
- Use clear naming conventions for your configuration options.
- Ensure that your configuration information is modular and encapsulated so that change in one place do not have knock-on effects for other.
- User DRY principle.
- Be minimalist: Keep the configuration information as simple and as focused as possible.
- Avoid overengineering the configuration system.
- Ensure that you have tests for your configuration that are run at deployment or installation time.
Managing the Environments
Every application depends on hardware, software, infrastructure and external systems in order to work.
The worst approach to managing configuration information is to deal with it on an ad-hoc basis.
The problem of managing environment as below.
- The collection of configuration information is very large.
- One small change can break the whole application or severely degrade its performance.
- Once it is broken, finding the problem and fixing it takes an indeterminate amount of time and requires senior personnel.
- It is extremely difficult to precisely reproduce manually configured environment for testing purposes.
- It is difficult to maintain such environments without the configuration, and hence behavior, of different nodes drifting apart.
The key to managing environments is to make their creation a fully automated process.
An environment that is in a properly deployed state is known as a baseline in configuration management terminology.
You should treat the environment the same way as you treat your source code.
We can use Puppet or CfEngine to manage the environment.
Managing the Change Process
It is essential to be able to manage the process of making changes to your environment, it should not be possible for anybody to make a change to it without going through your organization's change management process.