Having explored the origins and rationale for the project of managing Infrastructure as Code, we now turn to the core principles we should put into practice to make it happen.
Adam Jacob, co-founder of Opscode, and creator of Chef argues that, at a high level, there are two steps:
Break the infrastructure down into independent, reusable, network-accessible services.
Integrate these services in such a way as to produce the functionality your infrastructure requires.
Adam further identifies ten principles that describe what the characteristics of the reusable primitive components look like. His essay is essential reading, but I will summarize his principles here:
Our services should be small and simple—think at the level of the simplest freestanding, useful component.
Our design should discourage overlap of services, and should encourage other people and services to use our service in a way which fosters continuous improvement of our design and implementation.
Our services should be like building blocks—we should be able to build complete, complex systems by integrating them.
Our services should be easy to modify, enhance, and improve in response to new demands.
We should build our services using tools that provide unlimited power to ensure we have the (theoretical) ability to solve even the most complicated of problems.
Our services should produce the same results, in the same way, with the same inputs, every time.
We should specify our services in terms of what we want it to do, not how we want to do it.
We should not worry about the details of the implementation, and think at the level of the component and its function.
Our services should only be configured when required—action should only be taken once.
Our services should take responsibility for their own state being in line with policy; over time, the overall system will tend to correctness.
In practice, these principles should apply to every stage of the infrastructure development process—from provisioning (cloud-based providers with a published API are a good example), backups, and DNS; as well as the process of writing the code that abstracts and implements the services we require.
This book concentrates on the task of writing infrastructure code that meets these principles in a predictable and reliable fashion. The key enabler in this context is a powerful, declarative configuration management system that enables an engineer (I like the term infrastructure developer) to write executable code that both describes the shape, behavior and characteristics of an infrastructure that they are designing, and, when actually executed, will result in that infrastructure coming to life.