Back to blog

Level-up your Codebase with Infrastructure-as-code

Written by Rasmus Hag Løvstad, Full Stack Developer03 August, 2021

After reading this blog post, you will have gained insights into the benefits of using infrastructure-as-code utilities like Terraform to achieve higher code quality, faster development cycles and better agility for your organization. This allows developers to spend more time on what really matters - implementing features and creating value for the business.

If your team does manual server management, you might have encountered one or more of the following problems:

  • Too much time is spent on infrastructure tasks, and tasks related to management of infrastructure are hard to estimate.
  • Domain-specific knowledge about the infrastructure of each project is unevenly distributed among team members, and documentation is lacking.
  • Only specific team members have the required permissions to perform changes in the infrastructure - this is often a sysadmin or a lead developer.
  • Changes to the infrastructure cause problems for codebases using continuous delivery, since the infrastructure has to be changed manually and is decoupled from the current state of the application.

This blog post will introduce the concept of infrastructure-as-code - a process of managing server environments and infrastructure through machine-readable definition files that can be source controlled alongside the code rather than interactive configuration tools like command line utilities or web interfaces. We will describe Terraform as a baseline tool for achieving this, but many of the principles mentioned can be achieved using similar tooling like Chef, Puppet or Ansible.

A Simple Example using Terraform

Terraform is an open source software tool that takes configuration files written in a language called HCL and executes actions accordingly to perform changes to some server architechture.

Here is an example use case: We want to deploy a hello-world container image to Google Cloud Run. This can be achieved in Terraform using the following code:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "3.69.0"
    }
  }
}

provider "google" {
  project     = "my-project-id"
  region      = "europe-west3"
}

resource "google_cloud_run_service" "default" {
  name     = "cloudrun-srv"
  location = "europe-west3"

  template {
    spec {
      containers {
        image = "us-docker.pkg.dev/cloudrun/container/hello"
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }
}

You might have noticed that these configuration files are written in a declarative programming style. It describes what infrastructure we want, but not how to set it up. Terraform takes care of that part while giving us a singular interface instead of multiple web GUIs and CLIs.

Let us inspect this code snippet for a moment. The first two blocks describe some configuration details for Terraform and is not very relevant for the scope of this blog post. The third block describes a resource, which is an infrastructure object that is managed by Terraform. When you run terraform apply , Terraform will analyse the difference between the current state of the application and the state described in the HCL file, and then perform the corresponding migrations. In this case, this will consist of creating a Google Cloud Run service called "cloudrun-srv" using the "hello" image.

The Benefits of Infrastructure-as-code

Terraform is just one example of infrastructure-as-code tooling, and has many benefits compared to manual infrastructure management such as..

  • Terraform files can be version-controlled and stored alongside the rest of the codebase.
  • Terraform file syntax can be checked statically on every push using terraform fmt and dry-run using terraform plan.
  • Terraform can be used to automatically apply changes to infrastructure as part of a continuous delivery pipeline, which gives fewer headaches when having to migrate the software system to introduce new features.
  • Changes to infrastructure can be validated, reviewed and discussed on the same level as code, and can be tested in different environments before reaching production.
  • Every team member with sufficient write access to the repository can contribute infrastructure changes.
  • The infrastructure is self-documenting. No domain-knowledge about the server setup is trapped inside a single developer's head, and everyone can read all there is to know about the software system.
  • Terraform code can be split into modules which can be re-used later, which increases development speed.

A Word on Working Software

The third principle behind the Agile Manifesto says the following

Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.

Part of building working software is building the infrastructure that the software depends on. A server with a database dependency is not working software if it does not have a database to connect to. To be able to deliver working software frequently, one must trust the integrity of the codebase and repository such that a branch can always be pushed to production and continue to be working software. When a piece of code does not declare its infrastructure state correctly, it may cease to be working software if the infrastructure breaks.

Continuous delivery of declarative infrastructure delegates the integrity to the codebase such that one can always deploy any branch and know that the platform it runs on will migrate accordingly. This allows the developers to deliver working software more frequently and increases the agility of the project.

Conclusion

For the reasons above, Terraform (and infrastructure-as-code in general) can be very useful tools to deliver working software faster, with better documentation, colaboration and agility. To get started integrating Terraform with your existing infrastructure, we can recommend starting with the excellent documentation made by HashiCorp, the company behind Terraform.