In this article, we'll take a look at what Infrastructure as code [IaC] is and how Terraform is an Infrastructure as code tool for building infrastructure in the cloud.
What is Infrastructure as Code?
Infrastructure as Code allows you to define and manage infrastructure using code, instead of clicking through a console of cloud providers like "AWS, GCP, DIGITAL OCEAN" or the command line. This implies that one can manage an entire infrastructure in the same way one manages application code.
There are two approaches to IaC and they are "Imperative" and "Declarative". The Imperative approach defines our configuration as a string of commands that is executed in a certain order.
Example: Running a "Bash script" to provision resources using AWS CLI.
While the Declarative approach defines the desired state of our infrastructure using the resources needed and properties the resources should have.
Examples: Terraform, Ansible, Cloud Formation.
In this article, we will be talking about one of the declarative approaches, Terraform.
What is Terraform?
Terraform is an open-source infrastructure as code (IaC) tool that allows users to manage their infrastructure in a declarative and version-controlled way. It was developed by HashiCorp and was first released in 2014.
Terraform uses a declarative configuration language to define infrastructure resources, their dependencies, and the desired state of the infrastructure. It supports a wide range of infrastructure platforms, including cloud providers like Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), and many more.
With Terraform, users can create, modify, and delete infrastructure resources in a reproducible and scalable way. Terraform can be used to manage a wide range of infrastructure components, such as virtual machines, databases, networks, load balancers, and more.
One of the key benefits of Terraform is that it allows users to manage infrastructure as code, which means that infrastructure configurations can be version-controlled, shared, and reused across teams and projects. This approach improves collaboration, reduces errors, and increases the overall quality of infrastructure management.
Terraform also provides a range of features to improve infrastructure management, including the ability to plan changes before they are applied, the ability to work with multiple environments (e.g., development, staging, and production), and the ability to manage complex infrastructures using modules.
There are several important concepts to understand when working with Terraform, but some of the most fundamental ones include:
Infrastructure as code (IaC): Terraform follows the principles of IaC, which means that infrastructure is defined and managed using code. This allows for repeatability, consistency, and scalability of infrastructure management.
Terraform configuration language (HCL): HCL is a declarative language used to write Terraform configurations. It allows for the definition of infrastructure resources, their properties, and relationships in a readable and maintainable way.
Resources: Resources are the building blocks of infrastructure in Terraform. They represent the actual infrastructure components, such as virtual machines, databases, networks, and more.
Providers: Providers are plugins that allow Terraform to interact with various infrastructure platforms, such as AWS, Azure, Google Cloud, and more. They provide resource definitions and API access to these platforms.
Modules: Modules are reusable blocks of Terraform configurations that can be used across projects. They allow for code reuse, organization, and abstraction of infrastructure components.
State: As mentioned before, state represents the current state of the infrastructure managed by Terraform. It's important to manage state carefully to ensure consistency and safety of the infrastructure.
Understanding these concepts is crucial for effectively working with Terraform and creating maintainable and scalable infrastructure.
Terraform is a command-line tool that provides several commands for managing infrastructure as code. Some of the most commonly used Terraform commands include:
terraform init
: This command initializes a new or existing Terraform working directory by downloading the necessary provider plugins and initializing the backend.terraform plan
: This command creates an execution plan that shows what changes Terraform will make to the infrastructure to bring it to the desired state.terraform apply
: This command applies the changes specified in the Terraform configuration files and brings the infrastructure to the desired state.terraform destroy
: This command destroys all the resources created by Terraform, effectively deleting the infrastructure.terraform validate
: This command validates the Terraform configuration files, checking for syntax errors and missing required values.terraform state
: This command provides subcommands for managing the Terraform state file, including viewing, modifying, and importing state.terraform output
: This command displays the output values defined in the Terraform configuration files.terraform graph
: This command generates a visual representation of the Terraform resource dependency graph.
There are many other Terraform commands and subcommands available depending on the specific use case and requirements. It's important to familiarize yourself with the available commands and use them appropriately to manage infrastructure as code effectively.
Manage any Infrastructure
- Terraform has built-in plugins called providers which allow Terraform to interact with various cloud platforms and other services through their different application programming interfaces (APIs).
Example:
# AWS
provider "aws" {
region = "us-east-1"
}
# Azure
provider "azurerm" {
# Configuration options
}
HashiCorp and Terraform community have written over 1,000 providers to manage resources on Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, and DataDog, etc. Use the Terraform Registry to find the providers and services you already use.
- In Terraform, aside from the provider block, there is also the resource block. In this block, you define the resources you wish to deploy concerning the provider such as compute, network, etc.
Example:
# Azure resources
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
# AWS resources
resource "aws_vpc" "example" {
cidr_block = "10.0.0.0/16"
}
- Terraform data sources allow one to access data from APIs or other Terraform state backends. Examples of data sources include machine image IDs from a cloud provider or Terraform outputs from other configurations. This also helps in making your configuration more flexible, and dynamic and also lets you reference values from other configurations, helping you scope your configuration while still referencing any dependent resource attributes.
Example:
# Data sources for AWS
data "aws_instance" "foo" {
instance_id = "i-instanceid"
filter {
name = "image-id"
values = ["ami-xxxxxxxx"]
}
filter {
name = "tag:Name"
values = ["instance-name-tag"]
}
}
# Get Resources from a Resource Group Azure
data "azurerm_resources" "example" {
resource_group_name = "example-resources"
}
# Get Resources with specific Tags
data "azurerm_resources" "example" {
resource_group_name = "example-resources"
required_tags = {
environment = "production"
role = "webserver"
}
}
- As deployment grows more complex on Terrafor, one has to consider modules to make it easier to organize our infrastructure.
An Example would be, Kubernetes clusters for testing and development. Provisioning a Kubernetes cluster in a cloud provider like AWS requires a lot of configuration and resources but with modules, that configuration can be hidden behind a basic configuration interface. one can simply import the module, specify whatever inputs the module author provided, and provision a complete stack.
Example:
# VPC module
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
There are more modules and resources present on Terraform registry, you can find a module that fits your need.
Deployment of infrastructure with Terraform on any provider requires the following steps:
a. Identify the infrastructure for your project. this is also known as the scope and it means the basic structures, systems, and services required for the project. Example: choosing your provider and the resources needed for the project such as provider: AWS or Azure, resources: VPC, Nat Gateway, Ec2 instances, etc.
b. Write the configuration for your infrastructure. In this section you start by defining your provider section as shown above using any text editor of your choice and also defining the resources using code in terraform, making sure terraform is already installed in the machine.
c. Install the plugins Terraform needs to manage the infrastructure. After writing the configuration of your infrastructure, use the command terraform init
to install the plugins. This plugin is specific to the provider specified.
d. Preview the changes Terraform will make to match your configuration. To preview these changes, we use the command terraform plan
, this gives us a list of the resources to be created, destroyed or modified.
e. Make the planned changes. We use the command terraform apply
to make the changes shown when we use the terraform plan
command.
f. terraform destroy
is a command used to destroy the infrastructure built with terraform apply
.