The Immutability Pattern – Better programming practices and even better DevOps outcomes.
In the world of electronics, we often hear – ‘It cannot be repaired, these components need a direct replacement’ in the context of a motherboard or a supplementary PCB card for say a washing machine that has broken down. In all such cases, the complexity, and the effort to fix all the issues on the path to a complete repair is full of uncertainty in terms of timelines and cost and hence it is much more economical to directly replace such components.
Applying the same concept to programming, we make use of the immutability pattern to create objects that never change once they are instantiated, rather than changing the original object it makes more sense to create a new one to make any changes. The intent is to avoid unruly situations which can be caused by a state change and the recommendation is to create a new copy with the needed changes instead of changing the original object. This design pattern forms one of the foundational concepts of functional programming and there are numerous built-in mechanisms in different programming languages to achieve the same.
Replace the code objects with servers/containers and you can apply the same pattern and get similar benefits using – ‘Immutable Infrastructure’.
Note that traditionally, infrastructure components have always been mutable as infrastructure teams provision and maintain servers based on their configurations and updates from time to time. We have seen countless ‘troubleshooting sessions’ wherein a couple of SMEs- the server guys and the application teams engage in long-running working sessions to find that single piece of configuration that is causing a newly provisioned server to misbehave. Also, configuration is hard to document and most importantly to maintain and ensure that it is applied to the relevant servers in each environment.
So, how does the concept of immutability help us in the DevOps world?
Immutable infrastructure is built a single time based on a given specification and cannot be changed or modified later. If there is a change, the specification itself needs to be updated with the change and then the infrastructure needs to be built again with the updated specification.
Below are some problems that immutable infrastructure can potentially solve:
Configuration drift
an issue wherein the configuration varies for the same servers in different environment due to haphazard/undocumented changes to servers or servers have the latest changes applied to solve an issue faster but the configuration files in the repository are not updated to reflect the change responsible for issue resolution. In the case of Immutable infrastructure, the ‘in-place, ‘hot patches’ kind of resolution is discouraged as the infrastructure itself is never changed but replaced with newer, better versions enforcing a better change control mechanism.
Brittle Servers
Repetitive patching activity on critical servers sometimes leads these servers to a point of no return. Anxious admin folks are reluctant to change anything on such servers as a small change can lead to unpredictable failures and there are situations wherein only a handful bunch of people know how to fix these issues and they are most difficult to engage as they are always busy fixing such more ‘brittle’ servers elsewhere at odd hours. Immutable infrastructure guarantees freshly minted servers that are stable due to reviewed and tested configuration only.
Environment Shakedown Cycles
An infrastructure team normally provisions an environment, tests the same, and then hands it over to an application team that makes use of this environment for fresh deployments. However, at times most infrastructure changes do not get tested suitably and are discovered only once the deployments begin and the features start getting tested. We define buffers/estimates for such environment shakedown cycles wherein it is a painful exercise for both the teams to jointly test an environment and certify that application features work well. Immutable infrastructure allows such teams to have standardized contracts, change handshakes and change reviews/walkthroughs which are more agile and robust than joint troubleshooting sessions.