Why Infrastructure as Code?
Traditionally, if we look back when you wanted a server, you would raise a ticket, and someone from the ops team would create a VM instance or order a physical server. This could be using scripts, point and click, or even manual install. And then, with every request, there would be more VMs, for DNS, mail, databases, and so on. And then, there were continuous updates to the Operating systems, web servers, JVMs, and everything else. Over time they had slightly different configurations from each other (configuration drift) resulting in snowflake servers. And when something broke, it was a challenge to track what changes were made. This was still acceptable as long as servers were few and long-lived. A big change happened with the arrival of cloud service companies like AWS. Many companies, instead of investing in hardware and data centers, started moving their applications to the cloud. And in the cloud, you could deploy a server in minutes, which earlier would take hours or even days. To maintain optimum performance and availability, you may have to deploy more instances to meet demand. And then later you may have to terminate them to save on costs. As you pay by the hour, you may need to scale up or down every day. Doing this manually, many times a day is clearly challenging. Capturing the steps required to deploy or terminate instances and other infrastructure components in code enables automation. Automation in cloud and infrastructure provisioning can help deliver value faster and reliably.
What is Infrastructure as Code?
Infrastructure as code (IaC) is infrastructure automation using software development principles and practices. The idea is that you treat your infrastructure like software and then write, test, and execute code to define, deploy, update, and destroy your infrastructure. You write code to manage your servers, databases, networks, logs, application deployment & configuration. When you want to make changes to your infrastructure, you make changes to code, test it, and then apply it to your systems.
Benefits
Infrastructure as code offers significant benefits over manual provisioning:
Self-service
As the infrastructure is defined as code, the entire process and deployment can be automated and can be started by anyone in the DevOps team. Users of infrastructure get the resources they need when they need it.
Idempotency
Being idempotent means you define the desired state, and no matter how many times you run the script, the result is the same. It checks the current state and the desired state and only applies the changes which are needed. This can be extremely difficult to achieve with bash scripts. Tools like Ansible and Terraform have built-in features to make your code idempotent.
Reduced costs
Reduces the time and effort required for provisioning, much less than manual provisioning.
Faster software delivery
Quick provisioning of infrastructure for development, testing, and production results in your ability to deliver software much faster. Since the deployment process is automated, it is also consistent and repeatable.
Self Documenting
The state of the infrastructure is defined in code which is easily readable by anyone.
Version controlled
Traditionally changes to the production systems are considered risky. But then, change is inevitable. You may need to add a new database when you add a new feature. You may need to add new servers or storage to the cluster. Infrastructure as code reduces the effort and risk of making changes to infrastructure. You can check-in your source files in version control, which means you can track all the changes done to the infrastructure and revert quickly to the previous version if something breaks.
Validation and testing
Infrastructure as code enables testing and applying small changes continuously. As everything is code, you can check for errors using static analysis and automated tests.
Improved security
The shift to infrastructure as code enables you to embed security right from the beginning, and then you can apply changes reliably and safely.
Infrastructure as Code tools
While many tools are available, choosing one to work with, may not be easy. Following are some of the considerations, you might find helpful :
Configuration management vs. provisioning tools
Broadly, tools available fall under two categories –
Configuration management tools. Provisioning tools
Configuration management tools
Configuration management tools are designed to manage users, install and manage software and tools on existing servers. Chef, Puppet, Ansible, and SaltStack are all primarily configuration tools.
You can use configuration management tools to install and update the software on servers.
Provisioning tools
Terraform, CloudFormation, OpenStack Heat, on the other hand, are provisioning tools, i.e., used to create servers, database servers, load balancers, queues, subnets, firewalls, and all other components of your infrastructure. These tools make API calls to providers to create the required infrastructure.
Mutable vs. immutable infrastructure
Mutable infrastructure is one that can be modified after it has been provisioned. Chef, Ansible, Puppet & SaltStack are designed to install or update the software on existing servers. This may happen many times over the lifetime of a server. After many updates, each server is likely to be a little different from others, leading to configuration drift. For example, some changes which work fine on test servers may not work on production servers. Tools like Terraform and CloudFormation are designed to create a new server from a machine image or a container image every time. If the servers need to be updated, you replace them with new servers. When the new servers are up, you can terminate the old ones. Each deployment uses an immutable image to create a server, therefore avoiding configuration drift. This can be a little slow, though.
Imperative vs. declarative tools
Imperative tools are similar to scripting. You list steps to be taken to arrive at the desired state. Declarative tools enable you to specify the end state, and the tool works out the steps to achieve that state. While Chef is primarily an imperative tool, Ansible uses a hybrid approach and supports both imperative and declarative techniques. Terraform, CloudFormation, Puppet, OpenStack Heat, and SaltStack all belong to the declarative tools category where you declare the desired end state.
Using multiple tools together
Though each of these tools can be used on their own, a common approach is to use them together. For example, you can use Terraform to build VPCs, subnets, Internet gateways, load balancers, and VMs and then use Ansible to configure and deploy services on these instances.
Conclusion
Infrastructure defined as code offers many advantages over manual provisioning – it can be version controlled, tested, leads to faster provisioning, and software delivery. Many organization has already started adopting the IaC approach to build and manage their infrastructure.