If you are beginning your journey in learning a cloud provider like Amazon Web Services or Google Cloud Platform you have likely come across the term Infrastructure As Code (IaC). It is a swiss army knife for both developers and system administrators. In this post, we are going to dive into what IaC is, the benefits it provides, and the different forms it can take.
Explain Infrastructure as Code like I'm Five
To put it simply, it is the practice of representing our infrastructure in some form of code. The definition of "code" is kept very loose in IaC as it could be YAML or JSON config files, homegrown languages like HCL, or traditional languages like NodeJs or Ruby.
While IaC is often talked about within the context of the cloud it's not limited to just our cloud resources.
As we know there are all types of infrastructure. There are public cloud and private cloud resources. Cloud and on-premise resources. Or a combination of all of these sometimes referred to as hybrid cloud.
Therefore at the highest level, we can summarize IaC as the process or practice of representing the infrastructure our systems run on in a common language. This language makes the infrastructure visible to the entire team and is reproducible with relative ease.
OK, we get it, infrastructure as code is...just code.
But why in the world should we care to use it and what are we going to get out of it?
In my opinion, you don't see the benefits until you have experienced provisioning infrastructure by hand. Have you ever followed a tutorial where you clicked this button, that button, this other button, and a few more buttons until you had something set up with your cloud provider?
The answer is most likely yes.
Maybe you did that for your test environment. Then when it came time to go to production, you had to click those same buttons again and hope you get the order right.
What if someone else on your team had to reproduce the same button clicks in order to create their own environment? See how this is getting painful. Some folks might say, document the process and that solves the problem. This is true but it's still not ideal.
Documentation shares knowledge initially but can become stale. Developers have a nasty habit of not reading the documentation if it isn't right in front of them. Lastly, documentation can't be tested in the same way code can.
This is the biggest benefit infrastructure as code provides, automated, reproducible, testable, and self-documenting infrastructure.
By representing resources as code, we can parameterize the code to support multiple environments, share the code with our teammates, and even test the code to ensure accuracy.
Just like changes in our application code are tested, peer-reviewed and consumable by everyone on the team. The process of provisioning, maintaining, and updating our infrastructure can slip right into the same flow using IaC.
While I believe the benefits of representing your infrastructure as code far outweigh the downsides, it is still worth knowing the traps we can fall into.
The initial downside of infrastructure as code is the learning curve. Like I mentioned earlier, the term code is flexible in this process and therefore it often requires learning a new flavor of code based on the tool you are using. Learning how to represent your VPC networking stack inside of AWS CloudFormation is a non-trivial skill to learn.
Piggybacking on the learning curve, time is another potential downside of IaC. It is often a lot quicker to go into your AWS Console and click a few buttons than it is to write infrastructure code inside of Terraform. Many teams make this tradeoff early on for the sake of going faster and shipping a product or service.
The final trap is infrastructure divergence. Once we commit to the path of infrastructure as code we must stick to our guns. Changing an infrastructure stack by hand in the console that has been provisioned by an IaC tool can cause divergence. Meaning the state of our infrastructure has changed because it was edited manually and our IaC tool doesn't know that.
While these are significant downsides they shouldn't stop us from exploring IaC further. However, they should be things we consider as we are choosing tools that help us on this journey.
Tools, Tools, Tools and more Tools
When it comes to IaC tools it is helpful to think of them in two different, but often overlapping categories.
- Configuration orchestration tools are designed to automate the deployment of our infrastructure.
- Configuration management tools are designed to help configure the software and systems on infrastructure that has been provisioned.
It is important to note that these categories often overlap. As we will see some IaC tools allow you to orchestrate/provision infrastructure as well as configure it. Additionally, as infrastructure gets more complex it is not uncommon to see both types of tools used.
With me so far? Excellent. Here are some of the current tools that are popular in the infrastructure as code space.
Terraform is a infrastructure provisioning tool that supports multiple cloud providers. It allows us as developers to represent our infrastructure, regardless of whether it is AWS, Google Cloud or Azure, in a well-defined language known as HCL.
Terraform is highly extensible via plugins and has a very strong community around it that produces great open source modules for provisioning chunks of infrastructure.
AWS CloudFormation is not cloud agnostic and is dedicated to provisioning infrastructure within AWS accounts. It allows us to represent our AWS infrastructure in JSON or YAML configuration files that we can then execute to create, update, and destroy resources.
CloudFormation is very well integrated into the AWS ecosystem and has developed a lot of features for previewing, rolling back, and managing resource changes.
Chef falls under the configuration management tooling. It allows us to create recipes and cookbooks that define the exact steps needed to reach the necessary configuration of our application.
Chef, like Terraform, supports multiple cloud providers. It uses the commonly known language, Ruby. It is typically used for configuring Elastic Compute (EC2) instances and even on-premise servers.
Puppet is another Ruby-based configuration management tool similar to Chef. The difference between the two is that Puppet is known as a declarative tool. This means that we as developers define what our infrastructure is supposed to be and Puppet figures out how to make that true.
Ansible is an infrastructure automation tool from Red Hat. Developers describe how their components and system relate to one another. It is meant to manage and codify systems end to end rather than independently. These definitions are written in YAML and are known as Playbooks.
Juju is an IaC tool from Ubuntu which allows developers to represent their infrastructure as charms which are sets of scripts that deploy and operate systems. These charms can be packed together as bundles to deploy the entire infrastructure for an application.
This is definitely not a comprehensive list. There are constantly new tools being developed in both the configuration orchestration and management space. But for right now these are the mainstream tools that are being used across the industry.
Where to go from here
We now know the definition of infrastructure as code, the benefits it provides as well as the pitfalls, and we now know a few tools to explore that allow us to provision our resources via code.
The next step in understanding IaC is to pick a tool from the list above and begin exploring it.
- Start with a simple use case like provisioning an S3 bucket or EC2 instance.
- Once the resource is provisioned. Explore another resource to provision.
- Experiment with parameterizing the code to support multiple environments.
- Learn the differences between creating, updating, and destroying resources for the tool.
Once we have explored a tool that enables us to represent our infrastructure as code we can then explore the differences between that tool and others in the list above.
Infrastructure as code is the process and practice of representing underlying resources that support our systems in code. This allows us to use the same processes we use already when writing application code.
This includes sharing the infrastructure with our team so that the team can maintain the resources collaboratively. It also includes testing how our infrastructure is created, updated, and deleted. Just as with application code the definition of our infrastructure can be peer-reviewed.
Infrastructure as code is a swiss army knife in the toolbelt of DevOps. It is one that can be leveraged by teams big and small regardless of whether that cloud is provisioning resources in AWS, GCP, Azure, or their own data center.