Demystifying Infrastructure as Code: Provisioning Infrastructure with Terraform
Tags: terraform, infrastructureascode, beginners, tutorial
Published: 2024-02-29 17:29:21

The practice of Infrastructure as Code (IaC) has transformed software development and IT operations, emerging as a strategic solution to the challenges of traditional infrastructure management. Arising in the last decade as a response to the need for greater agility and consistency in the cloud computing era, IaC allows teams to define and provision infrastructure through code, automating processes that were previously manual and prone to errors. Among the tools leading this revolution, Terraform stands out for its ability to manage infrastructure in a declarative manner across various cloud providers, promoting a more dynamic and efficient ecosystem. This article aims to demystify Terraform, demonstrating how it can simplify the provisioning of infrastructure, making it accessible even to those new to the IaC journey.

---
**What is Infrastructure as Code?**

Infrastructure as Code (IaC) is a modern approach to managing and provisioning IT infrastructure, where everything is handled through code and scripts, similar to software development. Instead of manually configuring hardware, networks, and operating systems, IaC allows these resources to be defined in configuration files. This brings agility, as it allows for rapid replication of environments, reduces human errors, and ensures consistency across different development, testing, and production environments.

Infrastructure as Code (IaC) has become an essential practice in modern infrastructure management, allowing teams to provision and manage IT resources in an automated and efficient manner. Various tools have been developed to meet this demand, each with its peculiarities and use cases. There is a vast list of IaC tools, and here are the main tools available on the market:

- **Terraform**: An open-source tool by HashiCorp that allows for the safe and efficient creation, modification, and versioning of infrastructure. It supports multiple cloud providers, enabling multi-cloud infrastructure management.

- **Ansible**: An open-source IT automation tool that automates software provisioning, configuration management, and application deployment. It is known for its simplicity and ability to manage complex infrastructure with simple scripts.

- **Chef**: An automation tool that turns infrastructure into code. Chef enables the automated, efficient, and scalable management of servers—within data centers or in the cloud.

- **Puppet**: An open-source configuration management system that allows managing infrastructure as code, automating the configuration and maintenance of software across various servers.

- **AWS CloudFormation**: A service from Amazon Web Services that allows modeling, provisioning, and managing AWS and third-party resources using text files or graphics. It enables the entire IT infrastructure to be modeled in a configuration file.

- **Azure Resource Manager (ARM)**: A service from Microsoft that allows provisioning, managing, and monitoring Azure resources using declarative templates. It offers resource management in groups, facilitating organization and cost control.

- **Google Cloud Deployment Manager**: A tool from Google Cloud Platform that allows managing GCP resources through declarative templates. It facilitates the automated provisioning and management of GCP resources.

- **SaltStack (now part of VMware)**: An open-source automation tool designed for the configuration and management of IT infrastructure on a large scale. It is known for its ability to effectively manage data centers and cloud environments.

- **Pulumi**: An infrastructure as a code tool that allows using known programming languages (such as Python, JavaScript, TypeScript, and Go) to define cloud resources. Pulumi supports various cloud platforms, including AWS, Azure, Google Cloud, and Kubernetes.

Each of these tools has its advantages and peculiarities, making them more suitable for certain scenarios or team preferences. Choosing the right tool depends on the specific needs of the project, the team's familiarity with the programming language or system in question, and the integration requirements with other services and infrastructures. By exploring these options, teams can find the best approach to managing their infrastructure effectively and efficiently.

---

**Why Terraform?**

Terraform, an open-source tool created by HashiCorp, allows users to define infrastructure in a high-level configuration format, which can be used to provision and manage services across various cloud providers with a single workflow. Its declarative approach specifies the "desired state" of the infrastructure, leaving it up to Terraform to figure out how to achieve that state. This not only facilitates the management of multi-cloud infrastructure but also helps maintain a record of everything that has been provisioned, improving transparency and governance.

**Getting Started with Terraform**

Starting with Terraform is simple. First, install Terraform on your system. After installation, create a configuration file (commonly named main.tf) where you will define your infrastructure using the HashiCorp Configuration Language (HCL). This file will describe the resources you want to create and manage. Then, run the terraform init command in your terminal to initialize the working directory with the necessary files. To apply your configurations and provision the infrastructure, use the terraform apply command and confirm the action. This is how, with a few simple steps, you begin to transform code into real infrastructure.

**Demystifying the Terraform Workflow**

The Terraform workflow is intuitive, and divided into three main stages: Write, Plan, and Apply. Writing is where you define your infrastructure as code using HCL (HashiCorp Configuration Language). During the Planning phase, Terraform scans the code to identify what actions are necessary to achieve the desired state defined in the configuration file, without making any changes. Finally, Apply is when Terraform applies the changes to achieve the desired state, provisioning or updating the infrastructure as needed. This flow ensures you have full visibility and control over the changes before they are applied.

**State Management with Terraform**

Terraform maintains a state file, which is crucial for managing your infrastructure. This file contains the current state of the resources managed by Terraform and helps map real resources to your configuration. Terraform needs to understand what needs to be changed in a deployment. Managing the state securely and efficiently is key to avoiding conflicts and inconsistencies, especially in team environments. Therefore, practices such as remote state storage and state locking are recommended to ensure changes are applied in a controlled and secure manner.

**Best Practices and Advanced Tips**

To keep your Terraform code organized and secure, follow some best practices: structure your configuration files logically; use modules to reuse code; keep your sensitive variables out of version control; and use access policies to control who can modify the state. Moreover, exploring advanced features like workspaces to manage different environments (such as production, development, etc.) and Terraform Cloud for team collaboration can further enhance the efficiency and security of your infrastructure management.

---

To illustrate the use of Terraform in a real-world scenario, let's propose a basic application architecture that includes network configuration, security group, database, load balancer, routing, a VM with medium specifications, and IAM for Terraform management across the three main cloud providers: _Google Cloud Platform (GCP), Amazon Web Services (AWS), and Microsoft Azure._


## Proposed Architecture

The architecture consists of a web application that uses a VM to host the application, a database to store information, a load balancer to distribute traffic, and a security group to control access to the VM and the database. Access and resource management will be controlled through IAM.

> Note: The specific steps to prepare the environment in each cloud provider (GCP, AWS, Azure) include actions such as enabling necessary APIs, creating a project or service account, setting up IAM policies, and generating credentials. These preparatory steps are crucial for ensuring that Terraform can successfully authenticate and manage resources in the cloud environment.

Before we move on to the code part, it's necessary to prepare the environment in these providers so that Terraform can connect and manage the resources within the chosen provider. _Follow the step-by-step for the chosen provider:_

---

## Google Cloud Platform (GCP)

**Create a Service Account:**

- Access the Google Cloud Console.
- In the navigation menu, go to "IAM & Admin" > "Service accounts".
- Click on "Create service account".
- Enter the name and description of the service account. Click on "Create".
- In the permissions section, assign the necessary roles (for example, Project Editor for broad access) and click on "Continue".
  (Optional) Add users who can access this service account.
- Click on "Done" to create the service account.
- Create a private key for the service account:
  On the details page of the created service account, go to the "Keys" tab.
- Click on "Add key" > "Create new key".
- Choose the key format (recommended JSON) and click on "Create".
  _A JSON file will be downloaded. Keep it in a secure location; this file will be used to authenticate Terraform.
_
## Amazon Web Services (AWS)

**Create an IAM user:**

- Access the AWS Management Console.
- In the services menu, search for and select "IAM".
- In the navigation pane, choose "Users" and click on "Add user".
- Set the user name and select "Programmatic access" for the access type.
- On the next screen, assign the appropriate permissions, either by directly assigning policies or adding the user to a group with the desired policies.
- Review and complete the user creation.
- Obtain the access keys:
  _After creating the user, you will be directed to the completion page, where you can view and copy the Access Key ID and Secret Access Key.
- Keep this information; it will be used to configure the AWS provider in Terraform._

## Microsoft Azure

**Create a Service Principal:**

- Install and authenticate with Azure CLI if you have not already done so.
- Open a terminal and execute the following command to create a service principal: `az ad sp create-for-rbac --name <your-service-principal-name> --role Contributor --scopes /subscriptions/<your-subscription-id>.`
  _Note the appId, password, and tenant returned by the command; these values will be used to authenticate Terraform._

---


To simplify and focus on the desired configuration, let's write the code part for a basic architecture applicable across the three providers: GCP (Google Cloud Platform), AWS (Amazon Web Services), and Azure. The architecture will consist of:

- A private virtual network (VPC)
- A security group/firewall to define access rules
- A database instance
- A load balancer
- A virtual machine (VM) with 16GB of RAM and 6 AMD CPUs
- IAM configuration for management by Terraform

> Note: The exact specifications (such as machine types) may vary between providers. In this example, I'll generate the initial configurations for the VM, and the configurations for the other resources will be left as a challenge for the reader.

## Organizational Chart of the Architecture

- VPC (Virtual Private Cloud): Acts as the foundation of the network that isolates your cloud resources. It's where all other components reside, ensuring they are separated from the public internet and other cloud tenants unless explicitly allowed.
- Security Group/Firewall: Controls access to the VM and database, allowing traffic only on necessary ports. This is crucial for maintaining the security of your resources by limiting access to authorized users and systems.
- Database: Stores application data. It will be a managed instance to simplify maintenance and ensure high availability and security without the need for manual intervention for backups, patches, and updates.
- Load Balancer: Distributes incoming traffic among the VMs, ensuring application availability and scalability. It helps in managing sudden spikes in traffic and provides a seamless user experience by distributing requests efficiently.
- VM (Virtual Machine): Hosts the application, configured with approximate values of 16GB of RAM and 6 AMD CPUs. This serves as the compute resource where your application code runs.
- IAM (Identity and Access Management): Defines permissions for Terraform to manage resources. This is essential for automating the provisioning and management of your infrastructure securely, ensuring that only authorized actions are performed.

## Simplified Example Code

Given space and complexity constraints, below is an outline of what would be required in Terraform terms for each provider, focusing on the VM resource as a central example. This outline serves as a basic template for initializing a VM within each cloud provider's architecture.

## GCP (Google Cloud Platform)

```
provider "google" {
  credentials = file("path/to/your-credentials-file.json") // For the scenario described, we add the path where the generated credentials are located
  project     = "your-project-id" // Note, the project settings, region, and credentials are up to the use in a real or testing environment
  region      = "your-region" // Note, the project settings, region, and credentials are up to the use in a real or testing environment
}

resource "google_compute_instance" "vm_instance" {
  name         = "example-article-vm"
  machine_type = "e2-standard-4" # Adjust as necessary for close specifications

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-10"
    }
  }

  network_interface {
    network = "default"
  }

  // Simplification. Add firewall/security group configurations as necessary
}

```

## AWS (Amazon Web Services)

```
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "vm" {
  ami           = "ami-123456" # Use an appropriate AMI
  instance_type = "t3.2xlarge" # Approximate for 16GB RAM and CPUs

  tags = {
    Name = "ExampleVM"
  }

  // Simplification. Add VPC, security groups, etc., as necessary
}

```

## Azure

```
provider "azurerm" {
  features {}
}

resource "azurerm_virtual_machine" "vm" {
  name                  = "example-article-vm"
  location              = "East US"
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.example.id]
  vm_size               = "Standard_F8s_v2" # Approximate for 16GB RAM and AMD CPUs

  storage_os_disk {
    name              = "myosdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Premium_LRS"
  }

  os_profile {
    computer_name  = "hostname"
    admin_username = "yourusername"
    admin_password = "yourP@ssw0rd!"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }

  // Simplification. Add network configurations, security group, etc., as necessary
}

```
---

**Collaboration in Terraform**

Collaboration is a fundamental pillar in software development and infrastructure management, especially when it comes to Infrastructure as Code (IaC) with Terraform. Terraform was designed with team collaboration in mind, allowing multiple users to work on the same set of configurations effectively and securely. To illustrate, we can list practical tools that facilitate collaboration in Terraform:

**Atlantis**

Atlantis is an automation tool for Terraform that integrates with GitHub, GitLab, and Bitbucket, allowing teams to collaborate and manage infrastructure as code directly through pull requests. Atlantis executes Terraform plans and applies them in response to commands in pull requests, facilitating a code review approach for changes in infrastructure.

**Terragrunt**

Terragrunt is a thin convenience wrapper for Terraform that provides additional tools for working with multiple Terraform modules, facilitating code reuse, dependency management, and remote state configuration. While not a collaboration tool per se, Terragrunt can help organize Terraform code in a way that makes it easier for teams to work together.

---

**The** adoption of Infrastructure as Code (IaC) has transformed how developers and IT operators interact with infrastructure, bringing automation, consistency, and efficiency to the provisioning of IT resources. Terraform, in particular, stands out as a powerful tool in this landscape, enabling the management of infrastructure across multiple platforms with a simple and declarative configuration language.

By embarking on the Terraform journey, professionals are able to build, change, and version infrastructure safely and efficiently, reducing the risks associated with manual resource management. The practice of IaC, with support from Terraform, promotes greater collaboration between development and operations teams, accelerating the software development lifecycle and strengthening the DevOps culture.

Reference:
Official Terraform Documentation: [Terraform Documentation](https://developer.hashicorp.com/terraform/docs)