What Is Infrastructure as Code? Examples, Best Practices & Tools

What Is Infrastructure as Code? Examples, Best Practices & Tools

Infrastructure as Code (IaC) isn’t a new notion, but it still causes confusion today. While most large enterprises are in the process of adopting IaC, as they move their workloads to the cloud, only a few have managed to implement it effectively.

IaC has evolved significantly from its early beginnings, when the infrastructure surface was only the operating system, and “Puppet vs Chef” was a common debate. Today, operating systems often constitute a legacy abstraction, superseded by containers, Function as a Service (FaaS)-based applications, and sophisticated managed services.

In this article, you’ll learn about the state of the art in IaC and DevOps today, and the factors you must take into account for a successful implementation.

What Is Infrastructure as Code (IaC)

Infrastructure as Code (IaC) is the ability to define all aspects of a virtualized infrastructure using code instead of a configuration management tool for operating systems. Virtualized infrastructure handles foundational primitives like compute, storage, and network resources. But it also increasingly offers advanced services like API gateways and managed databases.

How IaC Solves Problems

IaC started initially as a means to reduce the time system administrators spend on servers. But in a world where servers have moved to the cloud, the role of IaC goes beyond increased productivity via automation. IaC is used more and more to ensure the integrity of an infrastructure, its security, and the traceability of its changes.

Moreover, IaC solves the very real problem of environment drift within the release pipeline. Teams that don’t use IaC have to devote labor hours regularly to maintaining multiple deployment environments.

Why IaC Matters for DevOps

Infrastructure as code is a time-saving tool for DevOps pros because it lets them skip the IT admin bottleneck and automate their infrastructure. This creates a fast, consistent infrastructure for every project. This makes life easier for DevOps by streamlining the software development life cycle (SLDC).

In DevOps, there’s no separation of church and state between writing code and deploying it. Ops tasks are meant to be expressed as code, rather than carried out manually. An example would be the automatic deployment of code that’s been checked into a source code management system such as Git.

DevOps teams can use IaC to create and test applications in production-like infrastructures early on in the SLDC. They can provision as many reliable environments as needed, effectively preventing common deployment issues. With manual configuration out of the picture, efficiency becomes the norm, and configuration drift a thing of the past.

Infrastructure as Code Use Case

One basic IaC use case involves the financial system. Imagine that you work for an international bank that operates across multiple world jurisdictions, with varying data sovereignty rules. 

IaC can help you create a single infrastructure definition common for the entire bank holding. Yet this definition is instantiated in different regions say, Canada and Germany. It ensures compliance without a duplication of technical efforts.

Benefits of Infrastructure as Code

IaC provides a uniform, repeatable specification for an infrastructure. Why repeatable? Because with IaC, you can be sure of obtaining the same infrastructure every time. Evolving and maintaining an infrastructure that’s defined as code is more effective than maintaining it manually.

With IaC, you can track changes, compare versions, ensure security, and enforce policies.

Here are the main benefits of IaC:

  • Speed: Companies that use IaC spend less time on manual processes, getting more done in less time. Iteration is faster without the bottleneck of waiting for an IT admin to complete manual tasks.
  • Consistency: With IaC, every step of the process is managed and completed automatically, eliminating human error, sick days, weekends, or PTO. Changes are implemented globally and swiftly, freeing up development teams to add value.
  • A more efficient software development lifecycle: IaC makes it easier for developers to do real work. With a more consistent path to provisioning infrastructure, they can save time and focus on non-repetitive, higher-order tasks.
  • Less overhead: Without the need to manage networking, storage, and other systems, admins can focus on streamlining the process and supporting the development team.

Infrastructure as Code is beneficial not only for developers but also for Product Managers and business people. You can learn more about it in our blog post on Business Benefits of Infrastructure as Code.

Disadvantages of IaC

While IaC has the potential to solve all the demands listed above, it comes at the expense of complexity. That doesn’t necessarily mean the nature (or amount) of code in the infrastructure itself. Instead, it means writing, maintaining, submitting, validating, applying and controlling the effects of IaC definitions.

The main disadvantages of infrastructure as code are:

  • Dependency on coding: With IaC, IT admins are no longer front-andcenter during infrastructure management. This puts developers in the limelight. A shortage of coding language skills in your company can put a crimp in IaC implementation.
  • Monitoring issues: Though IaC makes monitoring easier, the monitoring itself can require the use of additional tools. Old monitoring tools won’t always carry forward into an IaC environment.
  • Legacy security may need updating: Existing security processes and tools might not translate to an IaC environment. Before transitioning to IaC, it’s vital to assess and update legacy security tools and systems.

A flexible IaC management platform like Spacelift addresses all those challenges automatically, allowing workflow customization, automation, security, and monitoring, all from one convenient platform.

Infrastructure as Code Example

The below code snippet, written using Terraform’s HCL language, lets you set up a DynamoDB table in AWS:

resource "aws_dynamodb_table" "dynamodb-table-users" {
  name           = "users"
  billing_mode   = "PROVISIONED"
  read_capacity  = 2 
  write_capacity = 2
  hash_key       = "user_id"

  attribute {
    name = "user_id"
    type = "s"

That (very simple) IaC example doesn’t just provision the DynamoDB “resource.” It also creates a table, using user_id as the hash key. Though it’s basic, it illustrates how overarching IaC is in scope today, and the extent a modern virtualized (in most cases cloud) infrastructure can be codified.

On a grander scale, other IaC examples include:

  • Automating the configuration and deployment of applications and resources in the cloud
  • Creating cloud-agnostic templates for cloud resources
  • Deploying security policies for virtual networks
  • Automatically updating applications

How to Manage Infrastructure as Code

Broadly speaking, the minimum IaC framework you’ll need to manage infrastructure as code consists of a source code management system (SCM) tool, at least one infrastructure definition tool, a number of security and quality tools, and a CI/CD pipeline to string the first three together.

IaC Tools

Trying to implement an infrastructure as code system from scratch is problematic, not to mention costly and time consuming. Most organizations today leverage useful infrastructure as code tools to ensure a smooth, efficient process. The most common tools for each of the four aforementioned categories are as follows:

  • SCM: GitHub, GitLab, and Atlassian Bitbucket (All “Git” implementations)
  • Infrastructure Definition: Terraform and Pulumi are the most popular general-purpose multi-cloud tools in this space. Ansible is also often used in tandem, for operating system-centric edge cases. 
  • Security and Quality Tools: There’s a vast ecosystem of IaC security and quality tools on offer. Qualys and Checkmarx, are examples of tools that can detect the inclusion of vulnerable operating system packages.
  • CI/CD Tools: Traditional general-purpose CI/CD tools are often subdivided into pure continuous integration tools like Jenkins, deployment-oriented tools like Spinnaker, and “one stop shop” CI/CD tools like GitLab.

While you can use general-purpose CI/CD tools for IaC, they have limitations. (Managing the commonly-used tools of IaC itself eats up massive resources of both budget regular developer time.) Specialized IaC management tools like Spacelift overcome those limitations automatically.

To manage IaC smoothly, follow the best practices below.

IaC Best Practices

A sound IaC strategy involves using the following best practices:

  • Use a source code management system: Establish a code workflow strategy including review, verification, and approval procedures.
  • Write code rather than documentation: Define your infrastructure definitions and tasks (backups, disaster recovery, etc.) using code rather than by writing documentation, lists of steps, or runbooks.
  • Optimize your DevOps process for IaC: Include checks to prevent insecure, or non-compliant infrastructure definitions from being deployed. 
  • Make integrity your first goal: Make your infrastructure immutable and set up an automatic mechanism to detect state drift.
  • Modularize and scale your infrastructure: Arrange your code base so it can be delegated and managed by different team members using a privilege-based access control system.

Increasingly, IaC tools like Spacelift automate the IaC best practices above, baking them into the platform from day one.

Terraform and IaC

Terraform provides a single language (HCL) that can describe infrastructure for every major public and private cloud platform. But its key differentiating feature is that it uses a declarative approach, rather than an imperative one. 

In Terraform, you define the desired “end” state for a given infrastructure, as opposed to the steps required to achieve that state.

Declarative Definitions

Effective IaC isn’t just about replacing manual steps with code. All virtualized platforms have a command line interface (for example, the ‘aws’ command in AWS or the ‘az’ command in Azure) that can be used in a script for automation purposes.

The advantage of Terraform’s declarative approach is that it abstracts away from the specific number and order of steps needed to achieve an infrastructure. 

This doesn’t just create more clarity from a specification point of view. It also helps you reason about deltas between past, present, future, and tentative versions of an infrastructure architecture. This approach lets you identify unintended changes produced by parallel changes or external actors. In short, it prevents “state drift.”

Infrastructure as Code (IaC) versus Infrastructure as a Service (IaaS)

IaaS (Infrastructure as a Service) was initially synonymous with cloud services. Over time, the term became more specific, as other “as a service” acronyms emerged. For example, “Platform as a Service” (PaaS). 

Presently, IaaS refers to the provision of managed foundational resources (compute, storage, and networks), different from other “as a service” offerings. Modern IaC can automate all “as a service” capabilities, not just foundational resources. It’s a ruling automation that replaces IaaS and PaaS.

Another IaC Example

Take the example of the DynamoDB table definition you saw earlier in this article. Imagine you want to include an additional attribute called email, together with a global secondary index, so you can look up users by their email address. To achieve this, you would add a few extra directives as follows:

resource "aws_dynamodb_table" "dynamodb-table-users" {
  attribute {
    name = "email"
    type = "s"
  global_secondary_index {
    name               = "users_by_email"
    hash_key           = "email"
    write_capacity     = 2 
    read_capacity      = 2 
    projection_type    = "INCLUDE"
    non_key_attributes = ["email"]

If after adding the above directives, you ask Terraform to suggest an action plan (by typing “terraform plan”), you’ll notice that Terraform will propose modifying the table in place. It simply adds the email global secondary index, as opposed to destroying and recreating the table.

Conventional DevOps Tooling and Its Limitations

Conventional CI/CD tools provide an effective framework to work around the stages (e.g., build, test, and deploy) that pertain to a software application pipeline. Yet these tools are agnostic to the specific semantics of the applications languages at hand. 

Jenkins, for example, does not directly differentiate between building a C++ application using Makefiles from, say, building a Scala application using sbt.

Integration isn’t automatic

While the general-purpose nature of conventional CI/CD tools lets you integrate IaC stages (e.g., running the “terraform apply” command), the tools treat Terraform as a blackbox, and vice versa. 

As a result, we can only achieve the definition of specific validations, conditions, and triggers that apply at the infrastructure “code” level by piping command line utilities. We’re missing a “single pane of glass” experience (where all parts of our infrastructure are integrated in a single  management console).

Obfuscated resources

Last but not least, a notable limitation in general-purpose CI/CD tooling is the lack of insight into the resources that an infrastructure code definition will create. 

For example, Jenkins can successfully show that a “Jar” artifact was created as a result of running a successful Maven build. Yet it can’t show that a “Lambda” or “s3 bucket” was created as a result of successfully running a Terraform definition.

Why Use Spacelift for IaC?

Spacelift is rapidly becoming the de facto tool for automating, managing, and securing IaC code bases — especially those defined using Terraform and Pulumi.

Why Spacelift vs another IaC tool? Isn’t it easier to settle for “one CI/CD tool to rule them all?” It all comes down to complexity and the level of sophistication required to manage mature IaC code bases effectively. 

For a small infrastructure platform, supported by one or two engineers, any tool that offers a minimum level of automation is sufficient.

The difficulties appear when the number of projects goes beyond the remit of a single small team, and the infrastructure needs to be broken up and managed in a modular fashion, with a multi-tenant model in mind. 

Spacelift was designed from the ground up to manage IaC code bases (e.g., written in Terraform). It’s far more versatile than general-purpose command line tools such as those used to build regular application code.

The typical limitations and frustrations that apply to conventional CI/CD tooling are addressed elegantly and effectively with Spacelift:

  • Workflows can be adapted to reflect bespoke or specific paradigms such as Gitflow, trunk-based development, and “mono repos.”
  • Policies can be defined using the Open Policy Agent (OPA) mechanism, and applied directly to the specific semantics of infrastructure code definitions.
  • Access control can be tightly defined at various granular levels, and identity can be resolved using the enterprise’s central identity provider.
  • All resources resulting from the application of code definitions can be visualized and verified directly within the tool, without requiring access to the cloud provider’s web console.
  • State drift detection can be configured to run not only on-demand, preceding the application of “apply” stages, but also recurrently, to alert of changes created by external actors.
  • As with conventional CI/CD tools, all IaC stages can be configured to run “pre” and “post” commands or scripts. 

Future versions of Spacelift also plan first-class integration of Ansible. While Ansible is an imperative, rather than declarative IaC tool, it will allow Spacelift to work more effectively with legacy, mutable (and thus, operating system-centric) infrastructures as well.

You can check all of the above features today, for free, by going here and creating a trial account.

Share this post

twitter logo