🏗️ Complete Guide to Terraform and Infrastructure as Code (IaC)
Terraform (developed by HashiCorp) is the world's most popular Infrastructure as Code (IaC) tool. It allows you to define, provision and update cloud infrastructure resources (AWS, Azure, GCP, Kubernetes, etc.) using declarative and interpretable configuration files for both humans and CI/CD systems.
1. What is IaC and why use Terraform?
Before IaC, infrastructure was created manually from web consoles (by clicking on graphical interfaces) or imperative Bash/Python scripts. This led to serious problems such as lack of auditing, unexplained differences between environments (configuration drift), and non-repeatable human errors.
Declarative vs Imperative Approach: In Terraform you specify what end state you want (example: "I want 3 EC2 instances and a PostgreSQL database") and Terraform takes care of calculating the exact steps needed to achieve it.
2. Fundamental Concepts
- Provider: Plugin that translates the HCL code into calls to the APIs of cloud providers (AWS, Azure, GCP, Cloudflare, etc.).
- Resource: The fundamental block of infrastructure that Terraform will create or manage (example: an S3 bucket, an Azure VNet, a virtual machine).
- Data Source: Allows you to consult or read existing infrastructure information outside of our Terraform template.
- State: File (
terraform.tfstate) that acts as a local or remote database linking the HCL code blocks with the real IDs in the cloud.
- Variables & Outputs: Dynamic input parameters and return values (such as a public IP address or DNS) after provisioning.
3. Basic HCL Syntax (HashiCorp Configuration Language)
Terraform uses files with extension .tf written in HCL. A typical project contains files organized by purpose (main.tf, variables.tf, outputs.tf, providers.tf).
# Configuración del proveedor de AWS
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
# Declaración de variables
variable "aws_region" {
type = string
default = "us-east-1"
description = "Región de AWS para los recursos"
}
variable "environment" {
type = string
default = "dev"
description = "Entorno de ejecución (dev, staging, prod)"
}
# Creación de un recurso (Bucket S3)
resource "aws_s3_bucket" "app_storage" {
bucket = "mc-app-data-${var.environment}-2026"
tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
# Output: Retorna la URL del bucket tras crearlo
output "s3_bucket_arn" {
value = aws_s3_bucket.app_storage.arn
description = "ARN del bucket S3 creado"
}4. Terraform CLI Lifecycle
To work effectively with Terraform in your terminal or in a CI/CD pipeline, you must know the essential commands of its workflow:
terraform init
# 2. Formatea el código automáticamente según el estándar oficial HCL
terraform fmt
# 3. Valida la sintaxis del código sin conectarse a la nube
terraform validate
# 4. Muestra un plan de ejecución (compara código vs infraestructura real)
terraform plan -out=tfplan
# 5. Aplica los cambios planificados en la nube
terraform apply tfplan
# 6. Destruye toda la infraestructura creada por este código (Usar con precaución)
terraform destroy5. The State Archive (terraform.tfstate)
The state file is the operating core of Terraform. Maintains the mapping between the HCL definitions in your code and the actual physical entities in the cloud.
- Why is it critical? Without state, Terraform doesn't know if a code change means "creating a new resource" or "modifying an existing one."
- Dangers of saving the state locally: If you work as a team and store
terraform.tfstateon your laptop, your colleagues will not see your changes, or resources could be stepped on, causing infrastructure corruption.
6. Remote Backends & State Locking
Remote Backends are used to solve collaborative work. They store the state file securely and prevent simultaneous executions through locks (Locks).
terraform {
backend "s3" {
bucket = "mc-tfstates-central-prod"
key = "infra/core-network/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-locks" # Evita que 2 personas ejecuten apply a la vez
}
}7. Good Infrastructure Practices as Code
- NEVER commit file
.tfstateor secrets to Git: Add.tfstate,.tfstate.backupand.terraform/to your.gitignore.
- Use descriptive variables and validations: Always define appropriate types (
string,number,list) and default values.
- Modularize from day 1: Don't accumulate thousands of lines in a single
main.tffile. Divide the infrastructure into independent modules.
- Automate in CI/CD: Run
terraform planautomatically on every Pull Request andterraform applyonly when merging to the main branch.