📌 Key Takeaways

  • Terraform is used by 80%+ of DevOps teams managing multi-cloud infrastructure
  • IaC proficiency adds ₹3-6 LPA salary premium for DevOps engineers in Bangalore
  • HashiCorp Terraform Associate is among the top 10 most-requested certifications in Indian cloud job postings
  • Mastering Terraform opens doors to AWS, Azure, GCP and 1,800+ other providers
  • Average salary hike after Terraform training: 65% (Thick Brain placement data)

Infrastructure as Code (IaC) has fundamentally changed how cloud infrastructure is built and managed. Instead of clicking through cloud consoles or running one-off CLI commands, engineers define infrastructure — virtual machines, networks, databases, load balancers — as versioned, reviewable, reproducible code. Terraform, HashiCorp's open-source IaC tool, has become the industry standard for this practice. In 2026, the ability to write production-quality Terraform code is a non-negotiable skill for every DevOps engineer and cloud architect.

📊 Terraform Market Snapshot — 2026

80%+
DevOps teams using Terraform for multi-cloud
1,800+
Terraform providers available
Top 10
Most-requested certification in Indian cloud job postings
65%
Average salary hike post-Terraform training (TBT data)

What is Terraform?

Terraform is an open-source Infrastructure as Code tool created by HashiCorp. It lets you define infrastructure resources (servers, databases, networking, DNS, access policies) in HCL (HashiCorp Configuration Language) — a declarative, human-readable language — then apply those definitions to create and manage real infrastructure across any cloud or on-premise environment.

The core Terraform workflow is three steps: Write (define resources in .tf files), Plan (terraform plan shows exactly what will be created/changed/destroyed), Apply (terraform apply makes it happen). This preview-before-apply approach makes infrastructure changes safe and auditable.

💡 Why Terraform in 2026? Terraform has won the IaC wars. Its declarative approach, multi-cloud support, and massive provider ecosystem make it the default choice for infrastructure automation across the entire industry.

Why Terraform Over Cloud-Native IaC Tools?

Terraform vs CloudFormation (AWS)

AWS CloudFormation is AWS-only. Terraform works across 1,800+ providers. If your organisation uses AWS today but might adopt Azure or GCP services tomorrow, Terraform lets you use the same workflow and language for everything. For multi-cloud strategies, Terraform is almost always the preferred choice.

Terraform vs Ansible

Ansible is a configuration management tool (great for installing software, configuring OS settings, managing application deployments). Terraform is an infrastructure provisioning tool (creating and managing cloud resources). They are complementary — most production environments use Terraform to provision infrastructure and Ansible to configure what runs on it.

Terraform vs Pulumi

Pulumi lets you write IaC in general-purpose languages (Python, TypeScript, Go). Terraform uses its own HCL language. HCL is simpler to learn and Terraform has a larger community and ecosystem — making it the dominant choice in the industry despite Pulumi's technical advantages for developers.

Core Terraform Concepts

Providers

Providers are plugins that allow Terraform to interact with APIs. The AWS provider lets you manage EC2, S3, VPC. The Azure provider manages VMs, storage accounts, VNets. You declare which providers you need in your configuration and Terraform downloads them automatically.

Resources

Resources are the fundamental unit in Terraform — each resource block describes one infrastructure object. An aws_instance creates an EC2 instance; an azurerm_virtual_machine creates an Azure VM. Resources declare desired state; Terraform figures out how to achieve it.

State

Terraform maintains a state file (terraform.tfstate) that maps your configuration to the real-world resources. State is how Terraform knows what exists, what needs to be created, and what needs to be updated or destroyed. In teams, state is stored remotely (S3 bucket, Azure Blob, Terraform Cloud) with state locking to prevent concurrent modifications.

Modules

Modules are reusable Terraform configurations. A vpc module might encapsulate all the resources needed to create a production-grade VPC (subnets, route tables, NAT gateways, security groups) so teams can create consistent VPCs across all environments with a single module call.

Workspaces

Workspaces let you manage multiple environments (dev/staging/prod) from the same Terraform configuration with separate state files. Combined with variable files, they enable environment-specific deployments without code duplication.

Terraform Learning Roadmap: 6-Stage Path

This roadmap is used in Thick Brain Technology's Terraform & IaC for DevOps training program — 60 hours of live training, real cloud labs, and HashiCorp certification preparation.

🏗️
Stage 1

HCL & Fundamentals

HCL syntax, variables, locals, data sources, output values.

Beginner
🔄
Stage 2

Core Workflow

Init, Plan, Apply, Destroy, Terraform CLI commands.

Beginner
📦
Stage 3

State Management

Remote state, state locking, terraform import, state commands.

Intermediate
🧩
Stage 4

Modules & Reusability

Module creation, module sources, Terraform Registry, versioning.

Intermediate
☁️
Stage 5

Cloud Providers (AWS/Azure/GCP)

Provisioning compute, networking, storage, and Kubernetes clusters.

Advanced
⚙️
Stage 6

CI/CD & Production IaC

GitOps, Atlantis, Terraform Cloud, policy enforcement.

Advanced

Top Terraform Certifications 2026

These are the certifications that appear most frequently in senior Terraform/DevOps job descriptions across Bengaluru, Hyderabad and Pune.

🏆 Most Respected
HashiCorp Terraform Associate (003)
By HashiCorp. Covers IaC concepts, core workflow, state management, modules, variables, and Terraform Cloud. Best first certification for Terraform engineers.
☁️ AWS
AWS Certified DevOps Engineer
Covers AWS-specific IaC with CloudFormation and Terraform integration, CI/CD pipelines, and infrastructure automation on AWS.
☁️ Azure
Azure DevOps Engineer Expert (AZ-400)
Validates Azure-specific IaC using ARM, Bicep, and Terraform on Azure. Focuses on CI/CD and infrastructure automation.
☁️ GCP
Google Cloud Professional Cloud DevOps Engineer
Covers GCP-specific infrastructure automation using Terraform, deployment pipelines, and SRE practices.
🎓 Practitioner
Thick Brain Terraform & IaC for DevOps
60 hours live training, real AWS + Azure labs, module design patterns, HashiCorp cert preparation, CI/CD integration, and placement support until hired.

Terraform / IaC Engineer Salary Guide 2026

Salary data based on Bangalore market rates, job postings, and Thick Brain placement data (2025–2026).

RoleExperienceBangalore Salary (2026)
DevOps Engineer (Terraform)1-3 years₹8 – 14 LPA
Senior DevOps / IaC Engineer3-6 years₹14 – 22 LPA
Cloud Infrastructure Engineer5-8 years₹20 – 32 LPA
Platform / SRE Engineer6-10 years₹22 – 38 LPA
Cloud Architect (Multi-Cloud IaC)8+ years₹35 – 55 LPA

Source: Naukri.com, LinkedIn Jobs, Thick Brain placement data, June 2026

🚀 Ready to master Terraform?

Book a free 60-minute demo class — write your first Terraform configuration live. No payment, no commitment.

100 Terraform Interview Questions & Answers (2026)

The most comprehensive Terraform interview question bank for Bangalore tech companies — covering HCL, state management, modules, providers (AWS/Azure/GCP), CI/CD, and certification prep. Use search and category filters to focus your preparation.

Showing 100 questions
Terraform is an open-source Infrastructure as Code (IaC) tool by HashiCorp. It solves the problem of managing cloud infrastructure manually — instead of clicking through cloud consoles or running one-off CLI commands, you define infrastructure as code, version it, review it, and apply it consistently. Terraform supports over 1,800 providers including AWS, Azure, GCP, Kubernetes, and GitHub.
The core workflow is: Write (define infrastructure in .tf files using HCL), Plan (run terraform plan to see a dry run of changes), Apply (run terraform apply to execute the plan and provision resources). This preview-before-apply approach makes infrastructure changes safe, auditable, and repeatable.
HCL (HashiCorp Configuration Language) is a declarative configuration language designed for readability and maintainability. Terraform files are typically written in HCL, which supports comments, variables, functions, and modules. Terraform also supports JSON format for machine-generated configs. HCL is the preferred format for human-written Terraform code.
Resource blocks create, update, or destroy infrastructure objects (e.g., aws_instance, aws_s3_bucket). Data source blocks fetch read-only information from external sources (e.g., aws_ami, aws_subnet) to use in your configuration. Data sources do not create or modify resources — they only provide data that you can reference elsewhere.
Variables allow you to parameterise your Terraform configuration. Define them in variables.tf or inline. Example: variable "instance_type" { description = "EC2 instance type" type = string default = "t3.micro" }. Access via var.instance_type. Variables can be assigned via default values, terraform.tfvars, environment variables (TF_VAR_*), or CLI flags (-var).
Variables are inputs to a Terraform module — they can be overridden by callers. Locals are computed values within the same module — they cannot be overridden. Use locals for intermediate calculations, formatting, or to reuse a value across multiple resources. Example: locals { resource_name = "my-${var.environment}-app" }. Access via local.resource_name.
Output values expose information from a Terraform module to the caller. They are like "return values". Example: output "instance_id" { value = aws_instance.web.id }. Use outputs to share resource IDs, IPs, DNS names, or any other computed value. Outputs are also shown after terraform apply and can be referenced by other Terraform configurations via terraform_remote_state.
terraform init initialises a Terraform working directory. It: (1) Downloads and installs the required provider plugins. (2) Initialises the backend configuration (remote state). (3) Downloads module dependencies. (4) Sets up the working directory for use. You must run terraform init before any other Terraform commands in a new directory.
terraform plan creates an execution plan — it shows what changes Terraform will make (add, modify, delete) without actually applying them. terraform apply executes the plan and applies the changes to real infrastructure. Always review the plan before applying, especially in production environments.
terraform destroy is used to delete all infrastructure resources managed by a Terraform configuration. It is the opposite of terraform apply. Use with extreme caution in production — it can delete everything. Always run terraform plan -destroy to preview what will be destroyed before executing terraform destroy.
Terraform state (terraform.tfstate) is a JSON file that maps your configuration to real-world resources. It tracks resource IDs, metadata, and dependencies. Without state, Terraform cannot know what it previously created. State is critical for: (1) Detecting drift (manually made changes). (2) Dependency management. (3) Resource updates and deletion. Never commit state files to Git — use remote state instead.
Remote state stores the state file in a shared location (S3, Azure Blob, Terraform Cloud). Configure it in the backend block. Example: terraform { backend "s3" { bucket = "my-tf-state" key = "prod/terraform.tfstate" region = "ap-south-1" } }. Remote state enables team collaboration, state locking, and prevents state loss. It is mandatory for production Terraform usage.
State locking prevents concurrent modifications to the same state file. Without locking, two engineers running terraform apply simultaneously could corrupt the state. AWS S3 + DynamoDB enables locking — DynamoDB stores a lock ID. When a user runs apply, a lock is acquired; other users get an error. The lock is released automatically after completion. State locking is essential for team collaboration.
terraform import brings existing infrastructure (created manually or outside Terraform) under Terraform management. Example: terraform import aws_instance.web i-0a1b2c3d4e5f. After import, the resource appears in state but you still need to write the matching Terraform config manually. Use cases: migrating legacy resources to IaC, or recovering when state was lost.
Use terraform state mv. Example: terraform state mv aws_instance.web module.new_web.aws_instance.web. This moves the resource from one state location to another without destroying it. Useful when refactoring configurations or moving resources between modules. You can also use terraform state mv to rename a resource.
The state file often contains sensitive information — passwords, API keys, IAM keys, and other secrets in plain text. Best practices: (1) Use remote state with encryption at rest. (2) Never commit state to Git. (3) Use sensitive = true in output variables to prevent displaying secrets. (4) Enable access logging and restrict access to the state file via IAM policies. (5) Use Vault or external secrets for sensitive values instead of hardcoding them.
The terraform state command family provides subcommands to inspect and modify state manually: terraform state list (list all resources in state), terraform state show (show details of a specific resource), terraform state mv (move resource to a different location in state), terraform state rm (remove a resource from state without destroying it). Use these commands cautiously — they bypass the usual workflow.
State drift occurs when real-world resources are modified outside of Terraform (e.g., manually changing EC2 instance type via console). To detect drift: run terraform plan — it shows the diff between state and real resources. To fix drift: (1) Update the Terraform code to match the real state. (2) Use terraform import to bring manual changes into state. (3) Redeploy to revert to code if manual changes are undesirable. Prevent drift by always using Terraform for changes and enforcing CI/CD.
terraform destroy physically destroys the real infrastructure resource (e.g., deletes an EC2 instance) and removes it from state. terraform state rm only removes the resource from state — it does NOT delete the real resource. The resource still exists but Terraform no longer manages it. Use state rm when you want to stop managing a resource without deleting it.
Configure the backend block: backend "s3" { bucket = "tf-state-bucket" key = "env/prod/terraform.tfstate" region = "ap-south-1" dynamodb_table = "tf-state-lock" encrypt = true }. The DynamoDB table must have a primary key of LockID (String). When one engineer runs terraform apply, a lock record is written to DynamoDB — any concurrent apply fails immediately. The lock is released automatically after apply completes. This prevents state corruption from race conditions.
A module is a container for related resources — a directory of .tf files with defined inputs (variables.tf) and outputs (outputs.tf). Use modules to: (1) Encapsulate and reuse infrastructure patterns. (2) Reduce code duplication. (3) Enforce consistency across environments. Example: a vpc module can be reused across development, staging, and production environments.
Create a directory (e.g., modules/ec2) with: main.tf (resource definitions), variables.tf (input parameters), outputs.tf (return values). Call it from the root module: module "web" { source = "./modules/ec2" instance_type = "t3.micro" }. Modules enforce consistency — change the security group rule in one place and all EC2 instances using that module get the update.
The Terraform Registry (registry.terraform.io) is a repository of pre-built, community-validated modules. Use them by specifying the source: module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.0.0" }. The registry supports versioning, documentation, and provider constraints. Using registry modules accelerates development and follows industry best practices.
Source specifies where the module code is located — local path, Terraform Registry, Git repository, or HTTP URL. Version (used with registry sources) pins a specific version of the module to prevent breaking changes. Example: source = "terraform-aws-modules/vpc/aws" version = "5.0.0". Always specify a version for production modules.
Module nesting means calling a module from within another module. This is used to compose higher-level abstractions. Example: a webserver module might call a vpc module, an ec2 module, and an rds module. Use nesting to build complex, reusable infrastructure patterns. Keep nesting depth reasonable (2-3 levels) to avoid complexity.
Modules communicate via inputs (variables) and outputs. The parent module passes values to the child module via variables. The child module returns values to the parent via outputs. Example: parent passes vpc_id to the ec2 module; the ec2 module returns instance_id as an output, which the parent can then use or pass to another module.
count is a meta-argument that creates multiple instances of a resource or module. Example: resource "aws_instance" "web" { count = 3 ... } creates 3 EC2 instances. Access each instance via aws_instance.web[0]. Use count for simple, static lists of resources. For more complex conditionals, use for_each.
for_each creates resources based on a map or set of strings, allowing resource-specific keys. Example: for_each = { "web" = "t3.micro", "db" = "t3.medium" }. Unlike count (which uses integer indices), for_each uses string keys, making resources easier to reference and modify. Use for_each when you need to create resources with distinct configurations.
depends_on explicitly defines a dependency between resources when Terraform's automatic dependency detection fails. Example: resource "aws_instance" "web" { depends_on = [aws_iam_role_policy.web] }. Use it sparingly — Terraform's implicit dependency graph is usually correct. Use depends_on only for hidden dependencies (e.g., when a resource uses a value that isn't directly referenced).
Terraform supports conditionals using: (1) count — set count = var.create ? 1 : 0 to conditionally create a resource. (2) for_each — use a conditional map to create resources based on conditions. (3) condition in variables — validate input values. (4) Ternary operatorvar.env == "prod" ? "large" : "small" for dynamic values. (5) locals with conditional functions (merge, lookup) to build dynamic structures.
Basic EC2 resource: resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" vpc_security_group_ids = [aws_security_group.web.id] subnet_id = aws_subnet.public.id }. Use a data source to get the latest AMI: data "aws_ami" "amazon_linux" { most_recent = true owners = ["amazon"] }. For production, use user_data for post-provisioning configuration.
Create an S3 bucket: resource "aws_s3_bucket" "my_bucket" { bucket = "my-unique-bucket-name" }. Enforce encryption: resource "aws_s3_bucket_server_side_encryption_configuration" "encrypt" { bucket = aws_s3_bucket.my_bucket.id rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } }. Also set a bucket policy to block public access: resource "aws_s3_bucket_public_access_block" "block" { bucket = aws_s3_bucket.my_bucket.id block_public_acls = true }.
Use the terraform-aws-modules/eks/aws module. Example: module "eks" { source = "terraform-aws-modules/eks/aws" version = "19.0.0" cluster_name = "my-cluster" cluster_version = "1.28" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets }. The module handles control plane, node groups, IAM, and security groups. For production, configure node_groups with scaling policies and add-ons like VPC CNI and CoreDNS.
Define multiple provider blocks with aliases: provider "aws" { region = "us-east-1" alias = "east" } provider "aws" { region = "ap-south-1" alias = "south" }. Then specify the alias when creating resources: resource "aws_instance" "web_east" { provider = aws.east ... }. This allows deploying resources across multiple regions from a single Terraform configuration.
Define IAM resources declaratively: resource "aws_iam_role" "ec2_role" { name = "ec2-exec-role" assume_role_policy = jsonencode({ Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] }) }. Attach a policy: resource "aws_iam_role_policy_attachment" "s3_read" { role = aws_iam_role.ec2_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess" }. Use aws_iam_policy for custom policies with JSON documents.
Create a log group and flow log resource: resource "aws_cloudwatch_log_group" "vpc_flow_logs" { name = "vpc-flow-logs" } resource "aws_flow_log" "vpc" { iam_role_arn = aws_iam_role.flow_logs.arn log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn log_destination_type = "cloud-watch-logs" resource_id = aws_vpc.main.id traffic_type = "ALL" }. Flow logs are essential for security auditing and network troubleshooting.
The aws_availability_zones data source returns a list of availability zones in the current region. Example: data "aws_availability_zones" "available" { state = "available" }. Use it to create resources across multiple AZs dynamically: subnet_ids = data.aws_availability_zones.available.names. This makes configurations region-agnostic and portable.
Create a load balancer: resource "aws_lb" "app" { name = "app-lb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.lb.id] subnets = aws_subnet.public[*].id }. Add listeners, target groups, and rules. For ALB, define a listener: resource "aws_lb_listener" "app" { load_balancer_arn = aws_lb.app.arn port = 80 protocol = "HTTP" default_action { type = "forward" target_group_arn = aws_lb_target_group.app.arn } }.
aws_lb_target_group defines a group of targets (EC2 instances, IPs, Lambda functions) to route traffic to. It includes health check settings, stickiness, and protocol. aws_lb_listener_rule defines routing rules on a listener — path-based routing, host-based routing, and prioritisation. Example: listener_rule { condition { path { values = ["/api/*"] } } action { type = "forward" target_group_arn = aws_lb_target_group.api.arn } }.
Use AWS Secrets Manager with Terraform: resource "aws_secretsmanager_secret" "db_password" { name = "prod/db/password" } resource "aws_secretsmanager_secret_version" "db_password" { secret_id = aws_secretsmanager_secret.db_password.id secret_string = "my-secure-password" }. Then reference it in other resources using a data source: data "aws_secretsmanager_secret_version" "db_password" { secret_id = aws_secretsmanager_secret.db_password.id }. Never hardcode secrets in .tfvars or state files.
Use the Azure RM provider: resource "azurerm_virtual_machine" "web" { name = "web-vm" location = "eastus" resource_group_name = azurerm_resource_group.rg.name network_interface_ids = [azurerm_network_interface.web.id] vm_size = "Standard_B1s" storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "18.04-LTS" version = "latest" } storage_os_disk { name = "osdisk" caching = "ReadWrite" create_option = "FromImage" } os_profile { computer_name = "webvm" admin_username = "adminuser" admin_password = "Password1234!" } }. Use ssh_public_key instead of password for production.
Create an AKS cluster: resource "azurerm_kubernetes_cluster" "aks" { name = "aks-cluster" location = "eastus" resource_group_name = azurerm_resource_group.rg.name kubernetes_version = "1.28" default_node_pool { name = "default" node_count = 3 vm_size = "Standard_DS2_v2" } identity { type = "SystemAssigned" } }. Use the azurerm_kubernetes_cluster_node_pool resource for additional node pools with different configurations.
The Azure RM provider (hashicorp/azurerm) is the official provider for Azure resources. Authenticate using: (1) Service Principal (client_id, client_secret, tenant_id, subscription_id). (2) Azure CLI (run az login first). (3) Managed Identity (when running on Azure). Best practice: use a Service Principal with least privilege and store credentials securely (e.g., environment variables or vault).
Create a Key Vault: resource "azurerm_key_vault" "kv" { name = "my-key-vault" location = "eastus" resource_group_name = azurerm_resource_group.rg.name tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" }. Add secrets: resource "azurerm_key_vault_secret" "db_password" { name = "db-password" value = "my-secure-password" key_vault_id = azurerm_key_vault.kv.id }. Grant access via an access policy: resource "azurerm_key_vault_access_policy" "policy" { key_vault_id = azurerm_key_vault.kv.id tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_user_assigned_identity.app.principal_id secret_permissions = ["Get", "List"] }.
Create a VNet: resource "azurerm_virtual_network" "vnet" { name = "my-vnet" location = "eastus" resource_group_name = azurerm_resource_group.rg.name address_space = ["10.0.0.0/16"] }. Add subnets: resource "azurerm_subnet" "public" { name = "public" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = ["10.0.1.0/24"] }. Create a subnet for each tier (public, private, database).
Create a load balancer: resource "azurerm_lb" "app" { name = "app-lb" location = "eastus" resource_group_name = azurerm_resource_group.rg.name sku = "Standard" frontend_ip_configuration { name = "frontend" public_ip_address_id = azurerm_public_ip.lb.id } }. Create a backend address pool: resource "azurerm_lb_backend_address_pool" "app" { loadbalancer_id = azurerm_lb.app.id name = "backend" }. Attach the VM to the backend pool via its network interface.
Store secrets in Key Vault as described in Q44. To use them in other resources, use the azurerm_key_vault_secret data source: data "azurerm_key_vault_secret" "db_password" { name = "db-password" key_vault_id = azurerm_key_vault.kv.id }. Reference it: value = data.azurerm_key_vault_secret.db_password.value. Note: the secret value will be part of the state file — ensure state encryption and access controls are in place.
azurerm_resource_group creates an Azure Resource Group — a logical container for resources. Example: resource "azurerm_resource_group" "rg" { name = "prod-rg" location = "eastus" }. Almost all Azure resources in Terraform require a resource_group_name parameter referencing the resource group. Use a single resource group per environment for simpler management.
Create a storage account: resource "azurerm_storage_account" "storage" { name = "mystorageaccount" location = "eastus" resource_group_name = azurerm_resource_group.rg.name account_tier = "Standard" account_replication_type = "LRS" min_tls_version = "TLS1_2" }. For production, use account_replication_type = "GRS" for geo-redundancy. Add storage containers and files as needed.
Enable Azure Monitor at resource creation: resource "azurerm_monitor_diagnostic_setting" "example" { name = "example-logging" target_resource_id = azurerm_storage_account.storage.id storage_account_id = azurerm_storage_account.logs.id log { category = "StorageRead" enabled = true retention_policy { enabled = true days = 30 } } }. Use Terraform to configure logs, metrics, and alerts. Azure Monitor integrates with Log Analytics for advanced analytics.
Use the Google provider: resource "google_compute_instance" "web" { name = "web-vm" machine_type = "e2-micro" zone = "us-central1-a" boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-2004-lts" } } network_interface { network = "default" access_config { } } }. Use a data source for the latest image: data "google_compute_image" "ubuntu" { family = "ubuntu-2004-lts" project = "ubuntu-os-cloud" }.
Create a GKE cluster: resource "google_container_cluster" "gke" { name = "gke-cluster" location = "us-central1" node_version = "1.28" initial_node_count = 3 node_config { machine_type = "e2-standard-2" oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"] } remove_default_node_pool = true } resource "google_container_node_pool" "nodes" { cluster = google_container_cluster.gke.name node_count = 3 node_config { machine_type = "e2-standard-2" } }. Use the google_container_cluster resource for control plane and google_container_node_pool for worker nodes.
The Google provider (hashicorp/google) is the official provider for GCP resources. Authenticate using: (1) Service Account (JSON key file) set via GOOGLE_APPLICATION_CREDENTIALS environment variable. (2) Application Default Credentials (ADC) using gcloud auth application-default login. (3) GCE Metadata service when running on GCP. Best practice: use a service account with least privilege and store the key securely.
Use Google Secret Manager with Terraform: resource "google_secret_manager_secret" "db_password" { secret_id = "db-password" replication { auto {} } } resource "google_secret_manager_secret_version" "db_password" { secret = google_secret_manager_secret.db_password.id secret_data = "my-secure-password" }. Access the secret using a data source: data "google_secret_manager_secret_version" "db_password" { secret = google_secret_manager_secret.db_password.id }.
Create a VPC network: resource "google_compute_network" "vpc" { name = "my-vpc" auto_create_subnetworks = false }. Add subnets: resource "google_compute_subnetwork" "public" { name = "public" network = google_compute_network.vpc.id region = "us-central1" ip_cidr_range = "10.0.1.0/24" }. For private subnets, use private_ip_google_access = true to enable access to Google APIs.
Best practices: (1) Use a pipeline (GitHub Actions, GitLab CI, Jenkins) to execute terraform init, terraform plan, and terraform apply automatically on PR or main branch. (2) Store state remotely (S3, Terraform Cloud) for team access. (3) Use -auto-approve only for production after manual approval step. (4) Plan and apply in separate stages — plan on PR, apply on merge to main. Example GitHub Actions workflow: terraform init && terraform plan -out plan.out (PR), then terraform apply plan.out (merge).
Atlantis is a self-hosted GitOps tool for Terraform. It listens to pull requests and automatically runs terraform plan. When a PR is merged, it runs terraform apply. Atlantis comments on PRs with the plan output and allows approvers to approve and apply via comment (atlantis approve). Benefits: (1) Full audit trail. (2) No manual Terraform commands. (3) Standardised workflows. Thick Brain's Terraform course includes setting up Atlantis.
Terraform Cloud is HashiCorp's managed platform for Terraform. Adds: (1) Remote state management. (2) Run automation (plan/apply via API). (3) Policy as Code (Sentinel). (4) Cost estimation. (5) Team collaboration with roles and permissions. Use Terraform Cloud for enterprise teams that want to offload infrastructure management. Use OSS Terraform for small teams or on-premise deployments.
Best practice: Directory-based environments — separate directories for environments/dev/, environments/prod/ each with their own terraform.tfvars and backend config. Use modules/ for reusable components. Use terraform workspace as an alternative for small projects. In CI/CD, use terraform plan -var-file="environments/dev/terraform.tfvars" for environment-specific deployment.
Example workflow: name: Terraform on: push: branches: [main] jobs: terraform: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: hashicorp/setup-terraform@v2 with: terraform_version: 1.6.0 - name: Init run: terraform init - name: Plan run: terraform plan -out plan.out - name: Apply run: terraform apply plan.out. For production, add manual approval using environment or review steps.
Dynamic blocks allow you to generate nested configuration blocks dynamically. Example: dynamic "ingress" { for_each = var.ingress_rules content { from_port = ingress.value.from to_port = ingress.value.to protocol = ingress.value.protocol } }. Use dynamic blocks when the number or content of nested blocks varies based on input. They reduce code duplication and make configurations more flexible.
Lifecycle rules control resource creation, modification, and deletion behavior. Options: create_before_destroy (create new resource before destroying old), prevent_destroy (prevent accidental deletion, require terraform destroy with -force), ignore_changes (ignore certain attributes after creation). Example: lifecycle { create_before_destroy = true }. Use prevent_destroy for critical resources like databases.
terraform fmt reformats Terraform configuration files to a standard style (consistent indentation, spacing, and block layout). It is the equivalent of a code linter. Run it as part of your CI/CD pipeline to enforce consistency across the team. Example: terraform fmt -recursive -check (validate without rewriting).
terraform validate checks a Terraform configuration for syntax errors, invalid resource references, and provider compatibility. It does not access any remote resources or state. Run it after terraform fmt and before terraform plan in CI/CD pipelines to catch errors early.
terraform refresh updates the state file to match real-world infrastructure without making changes. It is useful for detecting drift or manually correcting state after external changes. In modern Terraform, terraform plan automatically refreshes state — so explicit terraform refresh is rarely needed.
Define provider versions in the required_providers block: terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }. Use ~> (compatible with minor versions), !=, >=, etc. Pinning versions prevents unexpected changes from provider updates. Run terraform init -upgrade to upgrade to the latest allowed version.
Terraform workspaces create multiple state files from the same configuration. Simple to use, but shares the same code. Environment directories (e.g., environments/dev/) use separate folders with different config and state backends. Recommended for production use because it makes environment drift visible and allows different configurations per environment.
Provisioners are used to execute scripts on a resource after creation (local-exec, remote-exec). Example: provisioner "remote-exec" { inline = ["sudo apt update", "sudo apt install nginx -y"] }. Use provisioners sparingly — they can cause state drift and are not idempotent. For configuration management, prefer user_data (AWS), cloud-init, or Ansible over provisioners.
Best practices: (1) Single responsibility — each module does one thing (e.g., a VPC module, an EC2 module). (2) Composable modules — combine small modules into larger ones. (3) Well-defined interfaces — clearly document inputs and outputs. (4) Versioned — use version tags for all shared modules. (5) Tested — write unit tests for module logic. (6) Documented — include READMEs with examples.
terraform taint marks a resource for forced recreation on the next apply, even if no config change is detected. Deprecated in Terraform 0.15.2+. terraform apply -replace="aws_instance.web" is the modern replacement — it forces recreation and shows a plan before replacement. Use -replace for manual resource replacement (e.g., certificate rotation, AMI upgrade).
The HashiCorp Certified: Terraform Associate (003) is an entry-level certification that validates your understanding of Terraform concepts, workflows, and best practices. Topics: IaC concepts (16%), Terraform purpose (10%), basics (30%), state management (23%), modules (9%), Terraform Cloud (9%). The exam is multiple choice, 57 questions, 60 minutes, costs USD 70.50.
Terraform Associate is the entry-level certification — focuses on core Terraform workflows and best practices. Terraform Practitioner (expected 2026) is an advanced certification covering complex module design, multi-cloud strategies, and production-scale IaC. Most engineers start with Associate and move to Practitioner after 1-2 years of hands-on experience.
Preparation: (1) Complete the official HashiCorp learning tracks (Terraform Fundamentals, Terraform Associate). (2) Hands-on practice — write Terraform for real AWS/Azure resources. (3) Take practice exams — use exampro or official HashiCorp practice questions. (4) Review exam objectives — focus on state, modules, remote state, and Terraform Cloud. (5) Thick Brain's Terraform course includes comprehensive preparation and mock exams.
(1) Salary premium — certified engineers earn 25-40% more than non-certified peers. (2) Job opportunities — Terraform Associate is listed in 60%+ of DevOps and cloud engineer roles in Bangalore. (3) Credibility — validates practical IaC skills to employers. (4) Career growth — certification is often a prerequisite for senior roles.
IaC trends for 2026+: (1) Policy as Code (OPA, Sentinel) integrated with Terraform. (2) AI-assisted IaC — GitHub Copilot generating Terraform modules. (3) CDK for Terraform (CDKTF) — write Terraform in TypeScript/Python/Go. (4) GitOps + Terraform — fully automated deployment pipelines. Despite these trends, HCL-based Terraform remains the industry standard for multi-cloud IaC.
A backend determines where Terraform stores the state file. Local state (local) is for individual use only. Remote state (s3, azurerm, gcs, terraform cloud) is for teams. The backend block is the first thing you configure in a Terraform project and cannot be changed without migrating state.
Define a variable as a list or map. Example: variable "security_groups" { type = list(string) }. In the module call: security_groups = ["sg-123", "sg-456"]. For complex data, use type = any or type = object({...}). Use maps for key-value pairs (e.g., type = map(string)).
If state is corrupted: (1) Restore from backup — use the most recent valid state file. (2) Use terraform state list to inspect and terraform state rm to remove problematic resources, then re-import. (3) Manual resolution — edit the state JSON directly (use terraform state push to re-upload). (4) Terraform Cloud — provides automated backups and version history. Prevention: use remote state with locking, enable versioning, and never edit state manually.
terraform graph generates a visual representation of the dependency graph of a Terraform configuration. It outputs DOT format, which can be converted to an image using Graphviz. Use it to understand complex module dependencies and to identify circular dependencies or unnecessary connections.
Use Sentinel (HashCorp's policy as code language) in Terraform Cloud/Enterprise. Example policy: import "tfplan" main = rule { all tfplan.resources.aws_instance as instance { instance.applied.lifecycle = "create" } }. Sentinel policies run before plan or apply and can enforce restrictions (e.g., block public S3 buckets, require specific tags). For OSS Terraform, use OPA Gatekeeper with Terraform.
terraform apply prompts for confirmation before applying changes. terraform apply -auto-approve skips the confirmation prompt. Use -auto-approve only in CI/CD pipelines with proper controls (e.g., after a plan is approved via PR review). Never use -auto-approve in production without a manual approval step.
terraform providers lists all provider requirements and versions in the current configuration. It also shows the provider versions used in the current lock file. Useful for auditing provider versions and checking for compatibility issues.
Use a centralised state storage location (e.g., S3 bucket in a master account) with specific IAM policies granting access to each sub-account. Use terraform_remote_state data source to access state from different configurations. Example: data "terraform_remote_state" "vpc" { backend = "s3" config = { bucket = "tf-state-bucket" key = "vpc/terraform.tfstate" region = "us-east-1" } }. This allows sharing outputs across configurations.
terraform console starts an interactive shell for evaluating Terraform expressions. Use it for: (1) Testing interpolation syntax (var.instance_type, local.resource_name). (2) Debugging complex function calls (join(",", var.list)). (3) Inspecting data source outputs. It is a powerful tool for learning and debugging, not for production use.
For local modules, use Git tags: git tag v1.0.0. For modules in the Terraform Registry, use semantic versioning in the versions.tf file. For modules from Git sources: source = "git::https://github.com/org/terraform-module.git?ref=v1.0.0". Versioning is critical for stability — always pin a version in production code.
Senior Terraform engineers should be prepared for: (1) Designing a reusable VPC module with subnets, NAT gateways, and route tables. (2) Handling state migration between backends. (3) Implementing policy as code with OPA or Sentinel. (4) Multi-region and multi-cloud strategies. (5) Terraform performance optimisation and state management. (6) CI/CD integration with GitHub Actions, Atlantis, or Terraform Cloud.
The .terraform.lock.hcl file records the exact version hashes of every provider used in the configuration. It ensures that all team members and CI/CD pipelines use the same provider versions, even when new versions are released. Commit the lock file to Git. To upgrade providers, run terraform init -upgrade.
This error means another Terraform process is currently holding the state lock (e.g., someone else is running terraform apply). Solutions: (1) Wait for the other process to complete. (2) Force unlock if the process is stuck: terraform force-unlock LOCK_ID. (3) Identify the process using the Lock ID (which is written in the error message). Use force-unlock with caution — it can cause state corruption if the other process is still running.
Best practices: (1) Environment variablesAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, ARM_CLIENT_ID, ARM_CLIENT_SECRET. (2) Shared configuration files~/.aws/credentials, ~/.azure/credentials. (3) Identity federation — AWS IRSA, Azure Managed Identity, GCP Workload Identity. (4) Vault — retrieve credentials from HashiCorp Vault.
terraform workspace manages workspaces: terraform workspace new dev (create), terraform workspace list (list), terraform workspace select dev (switch). Workspaces allow managing multiple states from the same configuration. Use terraform.workspace to get the current workspace name in your configuration.
Define the Lambda function: resource "aws_lambda_function" "app" { filename = "app.zip" function_name = "my-app" role = aws_iam_role.lambda.arn handler = "index.handler" runtime = "nodejs18.x" source_code_hash = filebase64sha256("app.zip") }. Use archive_file data source to package code. Integrate with API Gateway or EventBridge for event-driven execution.
aws_lb_target_group defines a target group for load balancing. Example with health check: resource "aws_lb_target_group" "web" { name = "web-tg" port = 80 protocol = "HTTP" vpc_id = aws_vpc.main.id health_check { enabled = true path = "/" healthy_threshold = 2 unhealthy_threshold = 2 timeout = 5 interval = 30 } }. Health checks are critical for routing traffic only to healthy instances.
Best practices: (1) Run terraform fmt and terraform validate in CI on every PR. (2) Run terraform plan in CI and post the output as a comment on the PR. (3) Require approve for terraform apply for production changes. (4) Use Atlantis to automate the whole process. (5) Code review the plan — review the intended changes, not just the code.
Terraform Cloud is HashiCorp's SaaS offering — runs in HashiCorp's infrastructure. Terraform Enterprise is a self-managed version that runs on your own infrastructure (private cloud or on-premise). Use Terraform Cloud for most teams. Use Terraform Enterprise when you have strict data residency, compliance, or air-gapped requirements.
Use HashiCorp Vault with Terraform's vault provider. Vault manages secret rotation and provides short-lived credentials. Terraform retrieves dynamic secrets at apply time. Example: data "vault_aws_access_credentials" "creds" { backend = "aws" role = "my-role" }. Use Vault's dynamic credentials feature — secrets have a short TTL and are automatically rotated. For AWS, use aws_iam_access_key with rotation via lifecycle rules.
terraform apply -target=aws_instance.web applies changes only to the specified resource and its dependencies. terraform destroy -target=aws_instance.web destroys only the specified resource. Use with caution — targeting bypasses the full dependency graph and can lead to inconsistencies. Prefer full apply or destroy for production changes.
A microservice module should include: (1) Compute — AWS ECS service, Lambda function, or EC2 auto-scaling group. (2) Networking — load balancer, security group, DNS record. (3) Database — RDS or DynamoDB (optional). (4) Monitoring — CloudWatch alarms, logs, and metrics. (5) Variables — image tag, instance count, environment name. (6) Outputs — service URL, load balancer address. This reusable module can be called for each microservice across environments.
(1) Not explaining state management — senior engineers must handle remote state, locking, and team workflows. (2) Overusing count and depends_on — use for_each and implicit dependencies. (3) Ignoring remote state — always use remote state in team settings. (4) No module design — senior engineers should demonstrate module reusability. (5) Lack of CI/CD integration — discuss how Terraform fits into a pipeline. (6) Not handling secrets — mention Vault or AWS Secrets Manager.
The demand for Terraform engineers is stronger than ever in 2026. As organisations accelerate multi-cloud adoption and digital transformation, the need for automated, reproducible infrastructure grows. Terraform skills are transferable across AWS, Azure, GCP, and on-premise environments. Engineers who combine Terraform with Kubernetes, CI/CD, and security best practices are among the highest-paid IT professionals in Bangalore.
Thick Brain Technology's Terraform & IaC for DevOps course includes comprehensive interview preparation: (1) 60 hours of live training covering all Terraform domains. (2) Real AWS and Azure labs — hands-on practice with actual cloud resources. (3) Mock interview sessions — simulate real Terraform technical interviews. (4) Module design challenges — build reusable modules for common scenarios. (5) CI/CD integration — use GitHub Actions and Atlantis in practice. (6) Placement support — help with job applications and referrals. Book a free demo to start your Terraform journey.

Frequently Asked Questions

Terraform is used to provision and manage cloud infrastructure as code. Instead of manually creating servers, networks, and databases through cloud consoles, you define them in .tf files and Terraform creates them consistently and reproducibly. It works across AWS, Azure, GCP, and 1,800+ other platforms.
No programming background is required. Terraform uses HCL (HashiCorp Configuration Language) which is a declarative configuration language designed to be simple and readable. Basic familiarity with YAML or JSON helps, but most DevOps engineers pick up HCL within a few days of practice.
Yes — at USD 70.50, the HashiCorp Terraform Associate is one of the best-value DevOps certifications available. It is increasingly listed as a requirement or preferred qualification in DevOps and cloud engineer job postings in India, and demonstrates practical IaC skills that employers can verify.
With structured training, most learners become proficient in 6-8 weeks. Thick Brain Technology's Terraform & IaC course covers AWS and Azure providers, module design, remote state, and CI/CD integration — you'll be job-ready in 2-3 months.
Thick Brain Technology offers comprehensive live online Terraform training with real AWS and Azure labs, module design patterns, and HashiCorp certification preparation. The course includes CI/CD integration and placement support. Book a free demo to see our live Terraform labs.

Conclusion: Master Terraform in 2026

Terraform has won the Infrastructure as Code wars. In 2026, writing Terraform for multi-cloud environments is a core competency for any DevOps engineer or cloud architect. Engineers who combine Terraform with Kubernetes, CI/CD pipelines, and cloud platforms (AWS/Azure/GCP) are among the most sought-after professionals in Bangalore's tech market.

The demand for Terraform engineers is stronger than ever. The ability to write production-quality Terraform code is a non-negotiable skill for every DevOps engineer and cloud architect. Certifications like the HashiCorp Terraform Associate validate these skills and command a significant salary premium.

Thick Brain Technology's Terraform & IaC for DevOps course teaches production-grade Terraform from first principles — covering AWS and Azure providers, module design, remote state, GitOps workflows, and CI/CD integration. Book a free demo class to write your first Terraform configuration live.

🏗️

Master Terraform with Real Cloud Labs

Book a free demo class and write your first Terraform configuration live. No payment required.

Share this article