Infrastructure

🏗️ Infraestructura Terraform como código

Terraform de HashiCorp es la herramienta de infraestructura como código (IaC) estándar de la industria. Le permite definir la infraestructura de la nube en un lenguaje de configuración declarativo (HCL), planificar cambios antes de aplicarlos y mantener el estado para realizar un seguimiento de lo que se ha aprovisionado.

Conceptos básicos

  • Proveedores: complementos que interactúan con API (AWS, GCP, Azure, Kubernetes, GitHub, etc.).
  • Recursos — La unidad fundamental. Cada recurso se asigna a un objeto de infraestructura real (por ejemplo, aws_instance).
  • Fuentes de datos: consulta la infraestructura existente administrada fuera de Terraform.
  • Estado: un archivo JSON (local o remoto) que asigna su configuración a recursos del mundo real.
  • Módulos: colecciones de recursos reutilizables y parametrizadas.
  • Espacios de trabajo: entornos de estado aislado para la misma configuración (dev/staging/prod).

Sintaxis HCL

HashiCorp Configuration Language (HCL) es la sintaxis declarativa de Terraform. Está diseñado para ser legible por humanos y escribible por máquinas.

hcl
variable "environment" {
  description = "Deployment environment (dev, staging, prod)"
  type        = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

variable "instance_count" {
  description = "Number of EC2 instances"
  type        = number
  default     = 2
}

variable "allowed_cidrs" {
  description = "CIDR blocks allowed to reach the load balancer"
  type        = list(string)
  default     = ["0.0.0.0/0"]
}

# locals.tf
locals {
  common_tags = {
    Project     = "mc-platform"
    Environment = var.environment
    ManagedBy   = "terraform"
    Owner       = "platform-team"
  }
  name_prefix = "mc-${var.environment}"
}

Proveedores y configuración de backend

hcl
terraform {
  required_version = ">= 1.7.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.25"
    }
  }

  # Remote state in S3 with DynamoDB locking
  backend "s3" {
    bucket         = "mc-terraform-state-prod"
    key            = "platform/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "mc-terraform-locks"
    kms_key_id     = "alias/terraform-state"
  }
}

provider "aws" {
  region = "us-east-1"

  default_tags {
    tags = local.common_tags
  }
}

provider "aws" {
  alias  = "us-west-2"
  region = "us-west-2"
}

Gestión del Estado

Nunca confirme archivos de estado Utilice siempre un backend remoto (S3, Terraform Cloud, GCS) con bloqueo de estado. Los archivos de estado locales pueden provocar una deriva irreversible de la infraestructura cuando se comparten en equipos.

bash
terraform state list                             # list all managed resources
terraform state show aws_instance.web_server     # inspect a specific resource
terraform state mv aws_instance.old aws_instance.new  # rename resource
terraform state rm aws_instance.imported         # stop managing (does NOT destroy)

# Import existing infrastructure
terraform import aws_s3_bucket.assets mc-assets-prod

# Refresh state to match real-world (use carefully)
terraform apply -refresh-only

Módulos

Los módulos encapsulan patrones de infraestructura reutilizables. Maxi's Computers mantiene un registro de módulos interno para componentes comunes.

hcl
module "vpc" {
  source  = "git::https://github.com/maxiscomputers/terraform-modules.git//vpc?ref=v3.2.0"

  name             = "${local.name_prefix}-vpc"
  cidr_block       = "10.0.0.0/16"
  azs              = ["us-east-1a", "us-east-1b", "us-east-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
  single_nat_gateway = var.environment != "prod"
  tags = local.common_tags
}

module "eks" {
  source  = "git::https://github.com/maxiscomputers/terraform-modules.git//eks?ref=v2.1.0"

  cluster_name    = "${local.name_prefix}-eks"
  cluster_version = "1.29"
  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnet_ids

  node_groups = {
    general = {
      instance_types = ["m6i.xlarge"]
      min_size       = 2
      max_size       = 10
      desired_size   = 3
    }
  }
}

# outputs.tf
output "vpc_id"          { value = module.vpc.vpc_id }
output "eks_endpoint"    { value = module.eks.cluster_endpoint }
output "eks_ca_data"     { value = module.eks.cluster_ca_certificate }

Espacios de trabajo

bash
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
terraform workspace list
terraform workspace select prod

# Use workspace name in configuration
resource "aws_s3_bucket" "app_data" {
  bucket = "mc-app-${terraform.workspace}-data"
  # ...
}

Flujo de trabajo CLI estándar

bash
terraform init -upgrade

# 2. Format and validate
terraform fmt -recursive
terraform validate

# 3. Plan — preview changes (always review before applying!)
terraform plan -var-file="environments/prod.tfvars" -out=tfplan

# 4. Apply — execute the plan
terraform apply tfplan

# 5. Targeted apply (use sparingly)
terraform apply -target=module.eks -var-file="environments/prod.tfvars"

# 6. Destroy (DANGER — requires explicit approval)
terraform destroy -var-file="environments/prod.tfvars"

Mejores prácticas en MC

  • Versiones del proveedor de pines con restricciones ~> para evitar cambios importantes inesperados.
  • Utilice terraform plan en CI: publique el resultado del plan como un comentario de solicitud de extracción antes de fusionarlo.
  • Almacenar .tfvars de forma segura: nunca confirme valores confidenciales; utilice secretos de CI o integración con Vault.
  • Etiquete cada recurso con local.common_tags para asignación de costos y cumplimiento.
  • Ejecute terraform fmt como gancho de confirmación previa para aplicar un formato coherente.
  • Utilice el indicador -out para que el plan aplicado sea exactamente el que se revisó.
  • Estado separado por entorno: nunca comparta un solo archivo de estado entre prod/staging/dev.