Infrastructure as Code (IaC) is a modern approach to managing and provisioning computing resources through machine-readable configuration files rather than physical hardware or interactive configuration tools. This method allows for more consistent and scalable infrastructure management, enabling automation and reducing the risk of human error.
Why Terraform?
Terraform, developed by Hashicorp is one of the most popular IaC tools due to its open-source nature, flexibility, and support for multiple cloud platforms. It lets users define and provision data center infrastructure using a high-level configuration language.
In this article, you will learn how to use Terraform as an IaC tool.
Understanding the Basics
What is Terraform?
Terraform is an open-source Infrastructure as Code (IaC) tool that allows you to define and provision infrastructure using a high-level configuration language called Hashicorp Configuration Language (HCL). *Terraform manages resources such as virtual machines, storage, and networking for various cloud providers through a *declarative approach, where you simply define the desired state of your infrastructure and Terraform ensures that it matches that state.
Overview of Architecture and Workflow
A typical Terraform workflow as shown in FIG 1.1 involves:
- Writing configuration files to define the desired state.
- Initializing the configuration directory with
terraform init
. - Creating an execution plan with
terraform plan
. - Applying the changes with
terraform apply
. - Managing the infrastructure state and making updates as needed.
- Destroying the infrastructure with
terraform destroy
if required.
Key Components
Providers
Providers are responsible for managing the lifecycle of resources. They offer a set of resources and data sources that Terraform can manage. Each provider requires a configuration to define the credentials and regions where Terraform would operate. Examples of providers include AWS, Azure, GCP, etc.
Example configuration
provider "aws" {
region = "us-east-1"
}
Resources
Resources are the fundamental building blocks of Terraform configurations. They represent components of your infrastructure, such as virtual machines, databases, or networking components. Each resource is defined with a type, name, and a set of properties.
Example resource definition:
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Modules
Modules are reusable configurations that help organize and structure your code. They allow you to group multiple resources and encapsulate complex infrastructure patterns.
Example module usage
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.77.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
}
Setting up your Environment
Visit the Terraform downloads page and download or install the version of Terraform concerning your operating system.
For Linux systems (Ubuntu/Debian) follow this:
STEP 1
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
STEP 2
Verify the installation with this
Terraform –version
STEP 3
For this article, we will be provisioning our infrastructure using AWS.
Use this link to install the aws cli for your operating system
STEP 4
Run aws configure
to set your variables after installing the aws cli. Terraform needs to be able to use these credentials for infrastructure provisioning.
Writing Your First Configuration
Basic Configuration File
Terraform configuration files are written in Hashicorp Configuration Language (HCL). The basic structure as shown in **FIG 1.2 **above includes
Provider Configuration:
Specifies the cloud provider and its settings.
provider "aws" {
region = "us-east-1"
}
Resource Definition:
Declares the resources to be managed.
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
resource: This tells Terraform that this is a resource block.
aws_instance: This is the actual resource we want to provision in aws.
example: This is a specific name given to the resource so that we can reference it elsewhere in our terraform code
Variables:
Defines variables for dynamic values.
variable "ami_name" {
type = string
description = "The name of the machine image (AMI) to use for the server."
default = “ubuntu-local”
}
variable: This indicates a variable block.
ami_name: This is the name of the variable. Hence, it can be referenced anywhere in the terraform code.
description: The description should explain the variable and what value is expected.
default: If present, the variable is considered optional and the default value will be used if no value is set when calling the module or running Terraform.
Outputs:
Specify outputs to display after applying the configuration.
output "instance_id" {
value = aws_instance.example.id
}
Writing your first main.tf
file
Create a directory for your terraform config files
mkdir terraform-practise
Create the main.tf
file in this directory. This file would contain your Terraform configuration
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Next, we initialize the directory
terraform init
Understanding the Initialization Process and Its Output
- Provider Plugins: Terraform downloads the necessary provider plugins specified in your configuration. In our case aws.
- Backend Initialization: Terraform sets up the backend for storing the state of your infrastructure.
-
Directory Structure: Terraform creates a
.terraform
directory to store the provider plugins and state files.
A sample output would look like this
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.27.0...
- Installed hashicorp/aws v3.27.0 (signed by HashiCorp)
Terraform has been successfully initialized!
Terraform Commands
To view the entire list of commands, do terraform –help
. Here are some commands and their uses
-
terraform init
: Initializes a Terraform working directory by downloading the necessary provider plugins and setting up the backend for state management. This should be run first before any other terraform command. -
terraform fmt
: This command is used to ensure the configuration files are properly formatted and easy to read. It helps maintain a consistent style across the files. -
terraform validate
: Checks whether the configuration is valid. -
terraform plan
: This command is used to preview the changes that Terraform will make to the infrastructure. It helps in verifying the resources that will be created, modified, or destroyed. -
terraform apply
: This command executes the actions proposed in the execution plan. It prompts for approval before making any changes unless the-auto-approve
flag is used. -
terraform destroy
: This command is used to terminate and remove all resources defined in the Terraform configuration. It prompts for approval before making any changes unless the-auto-approve
flag is used. -
terraform show
: This command is used to inspect the current state of the infrastructure managed by Terraform. It can also show the details of a specific plan file. -
terraform refresh
: This command reconciles the state file with the real-world resources to detect any drift between the two.
Practical Example: Setting Up an EC2 Instance with a VPC
In this example, we will provision an EC2 instance within a VPC. This configuration will include
- Creating a VPC
- Subnets
- An internet gateway
- Route tables
- EC2 instance with appropriate security groups
For this demonstration, we will create a new folder in our main directory named learn-terraform-aws.
mkdir learn-terraform-aws
cd learn-terraform-aws
We would then create our main.tf
file responsible for holding our terraform configurations
touch main.tf
First, we will define the VPC resource in the main.tf
file
provider "aws" {
region = "us-east-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "main-vpc"
}
}
Next, we define the public and private subnets within the VPC
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "public-subnet"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "private-subnet"
}
}
After this, we create our internet gateway to allow access to the VPC
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "main-gateway"
}
}
Define a route table and associate it with the public subnet
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "public-route-table"
}
}
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
Now we create our EC2 Instance
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.public.id
tags = {
Name = "web-server"
}
}
You would realize that we are simply declaring the state of our infrastructure like we would if we were to go to the AWS console. Also, The specific name of the resource blocks for our file is being reused as and when necessary. For instance, in the aws_instance
resource, we made use of aws_subnet.public.id
which is a named resource in our configuration telling terraform which resource to get this id from.
Variables and Outputs
Add variables and outputs to make the configuration more flexible and provide useful information after the infrastructure is provisioned.
Create a variables.tf
file and add this code
variable "aws_region" {
description = "The AWS region to deploy resources"
default = "us-east-1"
}
variable "instance_type" {
description = "Type of EC2 instance"
default = "t2.micro"
}
Now create an outputs.tf
file and add this code as well
output "instance_id" {
value = aws_instance.web.id
}
output "public_ip" {
value = aws_instance.web.public_ip
}
Now ensure that all three files are in the same directory and run the following commands
STEP 1. Initialize the directory
terraform init
STEP 2. Create an Execution Plan
terraform plan
STEP 3. Apply the configuration
terraform apply
STEP 4. After terraform apply
is complete, you will see the instance ID and public IP of the newly created EC2 instance.
Reference Links
Conclusion
In this article, we've explored the foundational aspects of using Terraform for infrastructure provisioning. From understanding the core concepts and basic commands to diving into practical scenarios like setting up an EC2 instance with a VPC, we've covered essential topics that will help you get started with Terraform.
Reach out to me via LinkedIn , X via Email.
Happy Learning 🚀
Top comments (7)
Great introduction to Terraform! Keep up the good work!
My pleasure @litlyx . Thank you
Wonderful article on IaC.
My pleasure. Do well to check out my other articles on DevOps
Thank you very clair and useful.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.