Infrastructure as Code: What is it all about?

Kehinde Ladipo
6 min readDec 10, 2019
Photo by Reza Namdari on Unsplash

The advent of the cloud introduced a major shift from traditional server administration to cloud computing. Over time, the lines between engineering (Development) and deployments (Operations) also began to blur, with the rapid adoption of DevOps, Continuous Integration and Continuous Deployments (CI/CD), Agile methodologies, etc.

Let’s consider setting up an infrastructure for a simple, hypothetical web application, that requires a virtual machine, a storage account, and a database. To create those resources using a cloud service provider such as Microsoft Azure, AWS, Google Cloud, etc, the traditional way is to go to the provider’s portal, select the resource you want to create, follow the configuration steps (wizard), follow a few “Next, Next” steps and finally Complete. Then you have your resource. If you have to do it again, say you want to provision a similar environment, you have to repeat the same steps.

Manual configuration of infrastructure is tedious because it takes time. Most of the time, in a team, it is the person who last changed the infrastructure’s configuration that has the knowledge of the current configuration. Sometimes, they forget 🤷‍♀️ what exactly they did, and that is totally normal. Even if this was documented somewhere, random tweaks happen on the infrastructure, making it hard to keep track of the configuration in a consistent manner. This is referred to as configuration drift.

Photo by Aral Tasher on Unsplash

Enter Infrastructure as Code

Infrastructure as code (IaC) is basically the paradigm of provisioning and managing cloud infrastructure and resources through human-readable and machine-readable code, as opposed to manual configuration or deployment of resources.

Any attempt to deploy or manage cloud infrastructure through code, scripts, declarative definitions, and so on can be regarded as IaC, although declarative definitions are more desirable. More information about that shortly.

Back to the web app example above, using IaC would mean stating the configurations of the 3 resources (VM, storage account and database) in a script, and running the script to set up the infrastructure. To provision a similar environment, say we want to set up a staging environment, we can simply run the script again, targeting the new environment. Thus we have identical, consistent and repeatable deployments.

As we have seen, manual configurations can be prone to misconfiguration, thereby leading to inconsistent infrastructure and behavior across different environments. IaC guarantees consistency because the infrastructure is deployed from the same scripts or definitions. All the time. This increases the speed of deployment because it saves time, cost and effort otherwise spent on manual configuration.

Misconfiguration can lead to security vulnerabilities, IaC increases the reliability of deployments because it provides a single source of truth for the state of the infrastructure, except for default configurations not explicitly stated. Well, on the flip side, this also implies that wrongly stated configs would be deployed across all environments.

Is IaC different from IaaS?

Yes. IaaS(Infrastructure as a Service) is a computing model whereby computing infrastructure such as virtual networks, storage, servers and data center space, etc, are made available over the internet, while IaC is a means of managing those IaaS resources.

Declarative or Imperative IaC?

The imperative approach specifies “what” resources and “how” the IaC framework should deploy them. It defines a sequence of commands to be executed so the infrastructure can reach the desired state.

On the other hand, the declarative approach “declares” the expected outcome. Instead of explicitly outlining the commands needed to reach the desired state, the declarative approach shows what the end result should look like. It’s up to the IaC framework to determine how to deploy those resources.

In declarative IaC, the developer specifies a list of resources required and their desired state configurations, whereas in imperative IaC, the developer writes a set of commands that will be executed in order to create the desired resources.

The following code snippets shed more light on this

Imperative IaC: Infrastructure is deployed by running a series of commands
Declarative IaC: Using Pulumi

Values encoded in {{ }} should be replaced with actual values

Declarative IaC: Using ARM templates

How Does IaC Work?

Different IaC tools have some specific details of how each one works, but the general idea is that the IaC system keeps a copy of the current state of your infrastructure from the last deployment. When a new deployment is launched, the IaC compares (imagine diff) the scripts with the current state of infrastructure and it “knows” what resources to add, update or delete accordingly.

IaC Best Practices

1. Idempotence
The chosen IaC framework should be idempotent. This means that it must always produce the same result in the target environment. Every time.

2. Version control
As the name implies, IaC is made of code, and as such must be treated as one. Versioning your IaC code makes it easy to track changes to the infrastructure configurations. Basically all the versioning that applies to normal code applies to IaC.

3. Testing
Like every good codebase, the IaC code can and should be tested. Though different IaC frameworks have different approaches to testing, the IaC code must be testable.

4. Graceful rollbacks
It’s desirable that the selected IaC framework support transactional operations, such that it can revert changes made when a deployment fails, or at the least, always leave the environment in a stable state by not partially creating resources. Versioning the IaC code also makes it easy to perform rollbacks, if required.

How do I Start?

Photo by Gia Oris on Unsplash

There are various IaC tools available. Examples Azure Resource Manager, Pulumi, Terraform, AWS CloudFormation, Ansible, Docker, Google Deployment Manager, Puppet, Chef, etc. Some frameworks rely on a domain-specific language (Terraform uses HCL, a specialized language called Hashicorp Configuration Language), some use familiar formats such as YAML and JSON, while others use real programming languages (Pulumi).

Some IaC tools are platform-specific, ARM templates only work with Azure, AWS CloudFormation only lets you manage resources on AWS. On the other hand, there are tools that support multiple platforms (Pulumi, Terraform, Chef, etc).

All of these should be put into consideration when deciding on the IaC framework(s) to use.

I’ll briefly describe 3 of these IaC tools that I have worked with — Ansible, ARM templates, and Pulumi.

Ansible is considered to be a configuration management tool. What it does is to install and manage software on existing server instances. For example, with Ansible you can install packages (with specific versions), start local services, and run custom scripts on the machine, in order to get it ready for your application.

Azure Resource Manager allows you to define the infrastructure and dependencies for your application in templates. With ARM templates, you can group resources, manage user permissions to resources, and so on, using predefined templates, known as schema. ARM templates are written in JSON.

With Pulumi, you can define infrastructure and configurations with real programming languages such as Python, JavaScript(NodeJS), TypeScript, Golang and recently announced support (preview) for C# and F#. Pulumi is particularly awesome for this reason because you can introduce regular programming patterns and constructs into your IaC code. You also get the benefit of IDE syntax highlighting and auto-complete.

If you already use IaC, please let me know which IaC tools work for you in the comments! If you haven’t, you should totally start experimenting with these tools and let me know what you think.

--

--