
Q.1 What is terraform
Terraform is an IAC tool created by Hashicorp. It lets you define, provision and manage infrastructure using code instead of manual setup.
In simple terms, you can tell Terraform to create 2 servers and a database… and Terraform creates it for you and manages it as well.
Some of the Key Concepts you must know:
1. IAC – Infrastructure As Code
- Infrastructure is written in configuration file (.tf)
- Version controlled, using git
- repeatable and consistent, i.e. you can use the same configuration file in any other location and it will spin the same infrastructure.
2. Declarative
You describe what you want, not how to do it. Terraform figures out the steps needed to reach that stage.
3. Cloud agnostic
It can work with multiple cloud providers such as AWS, Azure and also on premises servers.
4. State management
Terraform keeps a state file to track what it has created. It knows what to add, change or destroy.
Following is a simple example showing how terraform creates an EC2 instance in AWS
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-0abcdef12345"
instance_type = "t2.micro"
}
Once you have the code above, you can follow the steps below to provision them:
terraform init
terraform plan
terraform apply
In the end, we can say that it enables fast and automated infrastructure provisioning, having consistent environments (dev, qa, prod).
We can also create and reuse modules and it is also great for team collaboration.
Terraform is used for infrastructure provisioning and Ansible is used for configuration management.
Q.2 You have multiple environments – dev, stage, prod for your application and you want to use the same code for all of these environment. How can you do that?
To answer this question, you need to keep one thing in mind, i.e. Code/logic remains the same across all environment, you only separate the input, a.k.a values per environment. You change values not logic.
Thereby using the same infrastructure code with environment-specific variables, separate state, and reusable modules, so dev, stage, and prod differ only by configuration—not logic
Which means, three things to keep in mind to implement such scenario:
- Modules
reusable infrastructure logic. Create your infrastructure as modules. For example, if you want to create an EC2 instance, make sure you create a module for EC2 and re-use it for evert environment - Environment-specific variable
use environment specific variables for dev, qa, prod etc. - Separate state per environment
every environment should have separate state file per environment. it is a MUST. else, you can have overlap in states and can mess up the environments.
Following is the recommended folder structure
terraform/
├── modules/
│ └── app/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── dev/
│ ├── main.tf
│ ├── terraform.tfvars
│
├── stage/
│ ├── main.tf
│ ├── terraform.tfvars
│
└── prod/
├── main.tf
├── terraform.tfvars
Now, let’s look at each of the three points mentioned above, in detail
Module (Shared code)
# modules/app/main.tf
resource "aws_instance" "app" {
instance_type = var.instance_type
ami = var.ami
}
Environment-specific config (Different values for different environment, each calling same code)
# dev/terraform.tfvars
instance_type = "t3.micro"
# prod/terraform.tfvars
instance_type = "t3.large"
Separate state (CRITICAL) Each environment must have its own state
backend "s3" {
bucket = "terraform-states"
key = "dev/terraform.tfstate"
}
Q.3 Explain the concept of declarative syntax in terraform and how it contributes to infrastructure management?
Step 1. What is declarative sytax
Terraform uses a declarative syntax, which means you describe what you want the final infrastructure to look like, not how to create it step by step. i.e. you simply tell Terraform that these are the infrastructure pieces I want, create them and it does it for you.
You provide a DESIRED state to the Terraform. Something like, ” I want a VM with these two properties connected to a network” , instead of saying ” Create a VM, then attach it to a network and then assign an IP and so on… “
Declarative approach is “WHAT”-focused, instead of Imperative approach, which is “HOW”-focused. Let us understand this a bit more with an example below:
Imperative (how-focused):
create network
create vm
attach vm to network
Declarative (what-focused – Terraform):
resource "aws_instance" "web" {
instance_type = "t3.micro"
ami = "ami-123456"
}
You don’t tell Terraform how to create, but simply what to create.
Step 2. How does Declarative syntax works in Terraform
Desired state definition:
Terraform configuration files (*.tf) define the desired state of infrastructure:
- Resources
- Their properties
- Relationships between resources
Example: The code snippet below creates a S3 bucket with versioning enabled.
resource "aws_s3_bucket" "logs" {
bucket = "my-app-logs"
versioning {
enabled = true
}
}
State Comparison (Plan phase)
Terraform keeps a state file that tracks what already exists. When we run “terraform plan” following is what happens:
- Reads your configuration file (Desired state)
- Reads the current state (actual state)
- calculates a diff (What needs to be changed)
Example output:
+ create → new resource
~ update → modify existing resource
- destroy → remove resource
Execution (Apply phase)
When you run terraform apply, Terraform does the following:
- Determines the correct order of operation
- Handles dependencies automatically
- Applies only what is required to reach the desired state
Step 3. How declarative syntax improves infrastructure management
- Predictability and Safety
Terraform plan shows changes before they happen
Reduces accidental deletions or misconfigurations - Idempotency (Safe re-runs)
Running terraform multiple times results in:
No changes to infrastructure if it already matches the configurations.
No duplicates
No unintended side-effects - Clear Infrastructure as Code (IaC)
Declarative configs read like documents and are versional controlled as well - Automatic dependency management
Terraform builds a dependency graph from references, i.e. creates resources in right order. Also updates dependent resources when something related changes. - Provider Agnostic approach
The same declarative model works across AWS, Azure, GCP and so on.. just change the provider and rest of the logic remains the same.
To summarize: Terraform = declare intent, not procedure
You decide what infrastructure should exist and terraform decides how to make it happen.
Q.4 what are the key components of a terraform configuration file?
Following are some of the key components of a terraform configuration file explained below:
- Terraform block
- Provider block
- Resource block
- Variable block
- Output block
- Local values
- Data Source block
- Module block
- Backend Configuration
- Provisioners
Let’s look at all of them in detail
1. Terraform Block
Defines Terraform-wide settings like required versions and providers. Thereby, ensuring consistent Terraform and provider versions across environments.
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
2. Provider Block
Configures how Terraform talks to an external API (AWS, Azure, GCP). This block primarily defines authentication, region and provider-specific settings.
provider "aws" {
region = "us-east-1"
}
3. Resource Block
The most important component – it declares the infrastructure you want Terraform to create/manage.
resource "aws_instance" "web" {
ami = "ami-0abc123"
instance_type = "t3.micro"
}
4. Variable Block
Allows parameterization of configurations, thereby making them reusable and environment-agnostic
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t3.micro"
}
5. Output Block
Exports value after Terraform apply. Useful for debugging, integrations and CI/CD pipelines.
output "instance_public_ip" {
value = aws_instance.web.public_ip
}
6. Local Block
Defines reusable expressions or computed values. Reduces duplication and improves readability as well.
locals {
common_tags = {
Project = "demo"
Owner = "devops"
}
}
7. Data Source Block
Fetches existing infrastructure information without creating any new. Thus, it allows Terraform to reference resources not created or managed by it.
data "aws_ami" "latest_amazon_linux" {
most_recent = true
owners = ["amazon"]
}
8. Module Block
Think of it like calling a class in an object oriented language. It reuses Terraform configurations as building blocks. Encourages DRY (Don’t repeat yourself) principle, consistency and best practices.
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
cidr = "10.0.0.0/16"
}
9. Backend Configuration (State Management)
Defines where Terraform state is stored. Enables collaboration, locking and recovery.
terraform {
backend "s3" {
bucket = "tf-state-bucket"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
10. Provisioners (“local-exec” and “remote-exec”)
Runs scripts or commands on resources. Can be locally or remote, i.e. where resources are created.
provisioner "local-exec" {
command = "echo Instance created"
}
Q.4 How does Terraform maintain state, and why is state management important in infrastructure as code?
Terraform maintains state to keep track of the relationship between your configuration file, a.k.a the desired state and the real infrastructure a.k.a current state it manages. State is the backbone of Terraform’s Infrastructure as Code IaC model.
Terraform state is a snapshot of your infrastructure stored in a file called “terraform.tfstate”
This file records the following
- What resources terraform manages
- Resource IDs (e.g. EC2 instance ID, S3 bucket ARN)
- Resources attributes (IP Address, name, metadata)
- Dependency relationship
Terraform does not scan your cloud account every time, instead it relies on “state” to know what already exists.
How Terraform maintains state (Step by Step) -> Terraform workflow with state.
- Initial run (terraform apply)
Terraform creates resources
Cloud provider returns IDs (e.g. i-o123bc4)
terraform writes these IDs to terraform state file
2. Subsequent runs
Reads configuration (.tf)
reads current state from terraform.tfstate file
Queries the provider for drift
calculates diferences
Generates an execution plan
That is how terraform know how to create, update, replace or do nothing to resources specified in .tf config file
Now, lets look at where is state stored?
Option 1. Local state
-> Stored on your machine
Problems:
Not safe when teams are involved
No locking
Easy to lose the file
Option 2. Remote state (Recommended)
-> Stored on S3 + DynamoDB (AWS)
State is stored centrally
DynamoDB provides locking
Prevents concurrent updates
terraform {
backend "s3" {
bucket = "tf-state-prod"
key = "app/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tf-locks"
}
}
Why state locking matters?
Without locking:
When two engineers run terraform apply, both modify infrastructure and state corruption occurs.
With locking:
Terraform acquires a lock, others are blocked from making updates, thus, resulting in safe, consistent updates.
Why state management is critical?
1. Resource Tracking
Terraform needs state to know which resources it owns and their real-world IDs
Without state, terraform might recreate them all
2. Change Detection
State enables terraform to detect drift, apply minimal changes and avoid destructive operations
3. Dependency Resolution
Terraform uses state to build a dependency graph. Ensures correct creation and deletion order.
4. Team Collaboration
remote state enables multiple engineers to work together.
What happens if state is lost?
Worst case scenario: Terraform forgets existing resources and on next apply, it tries to recreate everything. Thus, resulting in downtime or duplicate resources.
Drift -> When someone changes the infrastructure manually. Thereby Terraform state != real world. Terraform detects drift during plan phase and shows => “~ resources will be updated”
Sensitive data in state, how is it handled?
State may contain sensitive data such as password, token, etc. It is best practice to encrypt state, restrict access using IAM and never commit state file to Git.
State file = source of truth.
Locking = prevent corruption
Drift detection = infra consistency.
Q.5) Describe the process of initializing a Terraform project. What does the terraform init command do?
Initializing a terraform project is the first step you take when working with a new or existing terraform project/configuration. This process prepares your working directory so Terraform can safely and predictably manage infrastructure.
terraform init:
- Prepares the working directory
- Configures the backend
- Downloads the providers and modules
- Locks provider versions
It is mandatory to run “terraform init” before plan and apply, and must be rerun when providers, modules, or backend configuration changes.
Process of initializing a Terraform Project
Step 1. Create or Clone a Terraform configuration.
You start with a directory containing terraform files, such as main.tf, variables.tf, providers.tf etc. These files define the providers, resources, modules and backends.
Step 2. Run terraform init
From the root of the directory, you run “terraform init”. This command initializes terraform working directory.
What does terraform init do?
Terraform init command performs several important setup tasks:
1. Initializes the backend (State storage)
Configures where the terraform state (terraform.tfstate) will be stored.
It could be local filesystem or remote S3 bucket.
If the backend configuration changes, terraform init may prompt to migrate state.
Backend initialization step is important because now terraform knows where to read/write state, which is critical for collaboration and sharing
2. Downloads and installs providers
reads the “required_providers” block in your configuration
Downloads the correct provider versions from the Terraform Registry and stores them in .terraform/ directory
providers are the plugins terraform uses to talk to APIs like AWS, Azure
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
3. Initializes and downloads modules
If your configuration references modules, then terraform downloads them at this stage and stores them in .terraform/modules path.
Modules can be local, git repo or in terraform registry.
4. Validates provider and module compatibility
Ensure provider versions satisfy constraints. Detects configuration issues early before planning or applying.
5. Creates or updates the lock file
Records exact provider versions and checksums. Ensures consistent provider versions across machines and CI pipelines.
Common Terraform init options
terraform init -upgrade # Upgrade providers/modules
terraform init -reconfigure # Reinitialize backend configuration
terraform init -migrate-state # Migrate existing state to a new backend
Typical Terraform workflow
terraform init
terraform validate
terraform plan
terraform apply