Introducción

Ha llegado el momento de escribir y ejecutar tu primera configuración real de Terraform. En lugar de empezar con AWS o Azure (que requieren cuentas y credenciales), usaremos el proveedor hashicorp/local, que trabaja exclusivamente con archivos en tu sistema de archivos local. Esto es perfecto para aprender porque:

  • No necesitas ninguna cuenta de nube ni tarjeta de crédito
  • Los resultados son inmediatos y visibles (puedes ver los archivos creados)
  • Los errores no tienen consecuencias (si algo falla, simplemente lo corriges)
  • El ciclo completo tarda segundos, no minutos

Al finalizar esta lección habrás ejecutado el ciclo completo de Terraform por primera vez y comprenderás exactamente qué ocurre en cada paso.


  1. Estructura Básica de un Archivo .tf

Un proyecto de Terraform es un directorio que contiene uno o más archivos con extensión .tf. Terraform lee todos los archivos .tf del directorio actual (no de subdirectorios) y los trata como una única configuración.

Convención de nombres de archivos

Aunque puedes nombrar los archivos .tf como quieras, hay una convención ampliamente adoptada:

Archivo Contenido habitual
main.tf Recursos principales de la configuración
providers.tf Declaración y configuración de proveedores
variables.tf Declaración de variables de entrada
outputs.tf Declaración de variables de salida
versions.tf Restricciones de versión de Terraform y proveedores
terraform.tfvars Valores de las variables (no commitear si contiene secretos)

Para proyectos simples (como nuestro primer ejemplo), es perfectamente válido poner todo en un único archivo main.tf.

Los bloques fundamentales de HCL

# Bloque terraform: configuración global de Terraform
terraform {
  # Versión mínima de Terraform requerida
  required_version = ">= 1.0.0"

  # Proveedores requeridos y sus versiones
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

# Bloque provider: configuración del proveedor
provider "local" {
  # El proveedor "local" no necesita configuración adicional
  # porque no accede a servicios externos
}

# Bloque resource: define un recurso de infraestructura
resource "local_file" "mi_archivo" {
  content  = "Hola, Terraform!"
  filename = "/tmp/mi-archivo.txt"
}

# Bloque variable: declara una variable de entrada
variable "nombre" {
  description = "El nombre a incluir en el archivo"
  type        = string
  default     = "Mundo"
}

# Bloque output: declara un valor de salida
output "ruta_del_archivo" {
  description = "La ruta donde se creó el archivo"
  value       = local_file.mi_archivo.filename
}

  1. El Proveedor hashicorp/local

El proveedor local de HashiCorp permite gestionar archivos y directorios en el sistema de archivos local de la máquina donde se ejecuta Terraform. Sus recursos principales son:

Recurso Descripción
local_file Crea un archivo con contenido especificado
local_sensitive_file Crea un archivo con contenido sensible (permisos restrictivos, no aparece en logs)
local_directory Crea un directorio

El recurso local_file tiene los siguientes argumentos principales:

Argumento Tipo Descripción
filename string (obligatorio) Ruta completa donde se creará el archivo
content string Contenido del archivo en texto plano
content_base64 string Contenido del archivo en Base64 (para archivos binarios)
file_permission string Permisos del archivo en octal (por defecto "0777")
directory_permission string Permisos de los directorios creados (por defecto "0777")

  1. Creando el Primer Proyecto

Paso 0: Preparar el directorio de trabajo

# Crear un directorio para nuestro primer proyecto
mkdir ~/terraform-primer-proyecto

# Entrar en el directorio
cd ~/terraform-primer-proyecto

El archivo de configuración completo

Crea un archivo llamado main.tf con el siguiente contenido:

# ============================================================
# main.tf - Primera configuración de Terraform
# ============================================================

# ----------------------------
# Configuración global
# ----------------------------
terraform {
  # Especificamos que necesitamos Terraform 1.0.0 o superior
  # El operador >= significa "mayor o igual que"
  required_version = ">= 1.0.0"

  # Declaramos los proveedores que necesitamos
  required_providers {
    local = {
      # Identificador del proveedor en el Terraform Registry
      # Formato: <namespace>/<nombre_del_proveedor>
      source = "hashicorp/local"

      # ~> 2.0 significa: cualquier versión >= 2.0.0 y < 3.0.0
      # Esto evita que una futura versión 3.0 con cambios incompatibles
      # se instale automáticamente
      version = "~> 2.0"
    }
  }
}

# ----------------------------
# Configuración del proveedor
# ----------------------------
# El proveedor "local" no requiere configuración adicional
# porque solo accede al sistema de archivos local
provider "local" {}

# ----------------------------
# Recursos
# ----------------------------

# Este recurso crea un archivo de texto en el sistema local
# "local_file" es el tipo de recurso del proveedor "local"
# "saludo" es el nombre que le damos nosotros a este recurso
resource "local_file" "saludo" {
  # content: el contenido que tendrá el archivo
  # Puede ser cualquier texto, incluyendo saltos de línea con \n
  content = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"

  # filename: la ruta completa donde se creará el archivo
  # Terraform creará los directorios intermedios si no existen
  filename = "${path.module}/output/saludo.txt"

  # path.module es una variable especial de Terraform que
  # contiene la ruta al directorio donde está este archivo .tf
  # De esta forma, el archivo se crea en una subcarpeta "output"
  # dentro de nuestro directorio de proyecto

  # file_permission: permisos del archivo en formato octal
  # "0644" significa: propietario puede leer/escribir,
  #                   grupo y otros solo leer
  file_permission = "0644"
}

# ----------------------------
# Outputs (valores de salida)
# ----------------------------

# Los outputs son valores que Terraform muestra tras el apply
# y que pueden ser consumidos por otros módulos o configuraciones
output "ruta_del_archivo" {
  description = "La ruta completa donde se creó el archivo"
  # Para referenciar un atributo de un recurso:
  # <tipo_recurso>.<nombre_local>.<nombre_del_atributo>
  value = local_file.saludo.filename
}

output "contenido_del_archivo" {
  description = "El contenido que se escribió en el archivo"
  value       = local_file.saludo.content
}

  1. Paso 1: terraform init

Con el archivo main.tf creado, ejecuta:

terraform init

Deberías ver una salida similar a esta:

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/local versions matching "~> 2.0"...
- Installing hashicorp/local v2.5.1...
- Installed hashicorp/local v2.5.1 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Qué ha ocurrido exactamente:

  1. Terraform leyó el bloque required_providers y encontró que necesita hashicorp/local ~> 2.0
  2. Contactó al Terraform Registry para encontrar la versión más reciente compatible (2.5.1)
  3. Descargó el binario del proveedor a .terraform/providers/registry.terraform.io/hashicorp/local/2.5.1/
  4. Creó el archivo .terraform.lock.hcl con el hash criptográfico del proveedor descargado

Estructura del directorio después de init:

terraform-primer-proyecto/
├── main.tf
├── .terraform/
│   └── providers/
│       └── registry.terraform.io/
│           └── hashicorp/
│               └── local/
│                   └── 2.5.1/
│                       └── linux_amd64/
│                           └── terraform-provider-local_v2.5.1_x5
└── .terraform.lock.hcl

  1. Paso 2: terraform plan

terraform plan

Salida esperada:

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.saludo will be created
  + resource "local_file" "saludo" {
      + content              = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0644"
      + filename             = "./output/saludo.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + contenido_del_archivo = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"
  + ruta_del_archivo      = "./output/saludo.txt"

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.

Cómo leer el plan:

  • El + delante de resource "local_file" "saludo" indica que este recurso será creado
  • Los atributos marcados con (known after apply) son calculados por el proveedor tras la creación (como los hashes MD5, SHA256 del contenido)
  • El resumen final Plan: 1 to add, 0 to change, 0 to destroy es la información más importante
  • La sección "Changes to Outputs" muestra qué valores de salida se producirán

  1. Paso 3: terraform apply

terraform apply

Terraform mostrará el plan de nuevo y pedirá confirmación:

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

Escribe yes y pulsa Enter:

local_file.saludo: Creating...
local_file.saludo: Creation complete after 0s [id=a1b2c3d4e5f6...]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

contenido_del_archivo = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"
ruta_del_archivo = "./output/saludo.txt"

Verifica que el archivo fue creado:

# Verificar que el directorio output y el archivo existen
ls -la output/

# Ver el contenido del archivo
cat output/saludo.txt

Deberías ver:

¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.

  1. Paso 4: terraform show

terraform show

Este comando muestra el estado actual en formato legible:

# local_file.saludo:
resource "local_file" "saludo" {
    content              = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"
    content_base64sha256 = "abc123..."
    content_base64sha512 = "def456..."
    content_md5          = "ghi789..."
    content_sha1         = "jkl012..."
    content_sha256       = "mno345..."
    content_sha512       = "pqr678..."
    directory_permission = "0777"
    file_permission      = "0644"
    filename             = "./output/saludo.txt"
    id                   = "stu901..."
}


Outputs:

contenido_del_archivo = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n"
ruta_del_archivo = "./output/saludo.txt"

Ahora puedes ver todos los atributos del recurso, incluyendo los hashes del contenido que antes mostraban (known after apply).


  1. El Archivo terraform.tfstate Después del Apply

Inspecciona el archivo de estado que Terraform ha creado:

cat terraform.tfstate
{
  "version": 4,
  "terraform_version": "1.9.0",
  "serial": 1,
  "lineage": "f3a1b2c3-d4e5-6789-abcd-ef0123456789",
  "outputs": {
    "contenido_del_archivo": {
      "value": "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n",
      "type": "string"
    },
    "ruta_del_archivo": {
      "value": "./output/saludo.txt",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "managed",
      "type": "local_file",
      "name": "saludo",
      "provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "content": "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n",
            "content_base64": null,
            "content_base64sha256": "abc123...",
            "content_base64sha512": "def456...",
            "content_md5": "ghi789...",
            "content_sha1": "jkl012...",
            "content_sha256": "mno345...",
            "content_sha512": "pqr678...",
            "directory_permission": "0777",
            "file_permission": "0644",
            "filename": "./output/saludo.txt",
            "id": "jkl012..."
          },
          "sensitive_attributes": [],
          "private": "bnVsbA=="
        }
      ]
    }
  ],
  "check_results": null
}

Estructura del archivo tfstate:

  • version: versión del formato del archivo de estado (actualmente 4)
  • terraform_version: versión de Terraform que creó este estado
  • serial: número que se incrementa con cada cambio (útil para detectar conflictos)
  • lineage: ID único de este "linaje" de estado (evita confundir estados de proyectos distintos)
  • outputs: valores de salida calculados
  • resources: lista de todos los recursos gestionados con todos sus atributos

  1. Paso 5: terraform destroy

Cuando ya no necesitas los recursos, puedes eliminarlos con:

terraform destroy
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # local_file.saludo will be destroyed
  - resource "local_file" "saludo" {
      - content              = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n" -> null
      - content_base64sha256 = "abc123..." -> null
      - file_permission      = "0644" -> null
      - filename             = "./output/saludo.txt" -> null
      - id                   = "jkl012..." -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - contenido_del_archivo = "¡Hola, Terraform! Este es mi primer archivo gestionado con IaC.\n" -> null
  - ruta_del_archivo      = "./output/saludo.txt" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

local_file.saludo: Destroying... [id=jkl012...]
local_file.saludo: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

Verifica que el archivo fue eliminado:

ls output/       # El directorio puede seguir existiendo pero el archivo no
cat output/saludo.txt  # Debe dar error: No such file or directory

  1. Ejercicio Completo: Tres Archivos con Variables

Enunciado

Crea una configuración de Terraform que genere 3 archivos locales con contenidos diferentes usando variables. El ejercicio consiste en:

  1. Crear un directorio ~/terraform-ejercicio-01-04/
  2. Definir una variable proyecto (string, default "MiProyecto")
  3. Definir una variable entorno (string, default "desarrollo")
  4. Crear 3 archivos:
    • config.txt: información sobre el proyecto y entorno
    • README.txt: instrucciones de uso del proyecto
    • metadata.json: metadatos en formato JSON con fecha y configuración
  5. Mostrar como outputs las rutas de los 3 archivos creados

Solución Detallada

Crea el directorio y el archivo de configuración:

mkdir ~/terraform-ejercicio-01-04
cd ~/terraform-ejercicio-01-04

Crea el archivo variables.tf:

# variables.tf
# Este archivo declara todas las variables de entrada de nuestra configuración

variable "proyecto" {
  # description: documentación de para qué sirve esta variable
  description = "Nombre del proyecto"

  # type: tipo de dato de la variable
  # Los tipos básicos son: string, number, bool
  # Los tipos complejos son: list, map, object, set, tuple
  type = string

  # default: valor que se usa si no se proporciona otro valor
  # Si no hay default, la variable es obligatoria
  default = "MiProyecto"
}

variable "entorno" {
  description = "Entorno de despliegue (desarrollo, staging, produccion)"
  type        = string
  default     = "desarrollo"

  # validation: regla para verificar que el valor es válido
  # Esto previene errores antes de que Terraform intente crear recursos
  validation {
    condition     = contains(["desarrollo", "staging", "produccion"], var.entorno)
    error_message = "El entorno debe ser 'desarrollo', 'staging' o 'produccion'."
  }
}

variable "autor" {
  description = "Nombre del autor de la configuración"
  type        = string
  default     = "Estudiante Terraform"
}

Crea el archivo main.tf:

# main.tf
# Configuración principal con los recursos a crear

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

provider "local" {}

# -------------------------------------------------------
# Recurso 1: archivo de configuración del proyecto
# -------------------------------------------------------
resource "local_file" "config" {
  # Usamos la función templatefile() para generar contenido dinámico
  # pero para mantenerlo simple, usamos interpolación de strings directa

  # La sintaxis ${var.nombre} inserta el valor de una variable
  # La sintaxis ${expresión} evalúa cualquier expresión HCL
  content = <<-EOT
    # Configuración del Proyecto
    # ==========================
    # Este archivo fue generado automáticamente por Terraform
    # No lo edites manualmente: los cambios se perderán en el próximo apply

    proyecto  = ${var.proyecto}
    entorno   = ${var.entorno}
    autor     = ${var.autor}
    gestionado_por = Terraform
  EOT
  # <<-EOT ... EOT es un "heredoc": permite escribir texto de varias líneas
  # El guión después de << elimina la indentación inicial

  filename        = "${path.module}/output/${var.entorno}/config.txt"
  file_permission = "0644"
}

# -------------------------------------------------------
# Recurso 2: archivo README
# -------------------------------------------------------
resource "local_file" "readme" {
  content = <<-EOT
    PROYECTO: ${upper(var.proyecto)}
    =============================

    Entorno: ${var.entorno}
    Autor: ${var.autor}

    DESCRIPCIÓN
    -----------
    Este es el proyecto ${var.proyecto} ejecutándose en el entorno de ${var.entorno}.

    INSTRUCCIONES
    -------------
    1. Asegúrate de tener Terraform >= 1.0.0 instalado
    2. Ejecuta: terraform init
    3. Ejecuta: terraform plan
    4. Ejecuta: terraform apply
    5. Para limpiar: terraform destroy

    NOTAS
    -----
    - Todos los archivos en el directorio "output/" son gestionados por Terraform
    - No modifiques estos archivos manualmente
    - Los cambios deben hacerse en los archivos .tf y luego aplicarse con terraform apply
  EOT
  # upper() es una función de Terraform que convierte texto a mayúsculas
  # Terraform tiene decenas de funciones built-in: upper(), lower(), length(),
  # join(), split(), replace(), format(), tostring(), tonumber(), etc.

  filename        = "${path.module}/output/${var.entorno}/README.txt"
  file_permission = "0644"
}

# -------------------------------------------------------
# Recurso 3: archivo de metadatos en JSON
# -------------------------------------------------------
resource "local_file" "metadata" {
  # jsonencode() convierte un objeto HCL a JSON válido
  # Esta es una función muy útil para generar archivos de configuración JSON
  content = jsonencode({
    # Las claves del objeto se convierten en claves JSON
    proyecto  = var.proyecto
    entorno   = var.entorno
    autor     = var.autor
    version   = "1.0.0"
    terraform = {
      # terraform.workspace es una variable especial que devuelve
      # el nombre del workspace actual (por defecto "default")
      workspace = terraform.workspace
      gestionado = true
    }
    archivos_generados = [
      # Referenciamos atributos de los otros recursos
      # Esto crea una dependencia implícita: metadata se crea después de config y readme
      local_file.config.filename,
      local_file.readme.filename,
    ]
  })

  filename        = "${path.module}/output/${var.entorno}/metadata.json"
  file_permission = "0644"
}

Crea el archivo outputs.tf:

# outputs.tf
# Define los valores que Terraform mostrará después del apply

output "archivo_config" {
  description = "Ruta del archivo de configuración"
  value       = local_file.config.filename
}

output "archivo_readme" {
  description = "Ruta del archivo README"
  value       = local_file.readme.filename
}

output "archivo_metadata" {
  description = "Ruta del archivo de metadatos JSON"
  value       = local_file.metadata.filename
}

output "resumen" {
  description = "Resumen de los archivos creados"
  value = {
    proyecto        = var.proyecto
    entorno         = var.entorno
    archivos_creados = 3
    directorio      = "${path.module}/output/${var.entorno}/"
  }
}

Ahora ejecuta la configuración:

# Inicializar
terraform init

# Ver el plan
terraform plan

# Aplicar con los valores por defecto
terraform apply -auto-approve

# Ver los archivos creados
ls -la output/desarrollo/
cat output/desarrollo/config.txt
cat output/desarrollo/README.txt
cat output/desarrollo/metadata.json

# Aplicar con valores personalizados (sobrescribe los defaults)
terraform apply -var="proyecto=TiendaOnline" -var="entorno=produccion" -var="autor=Juan Garcia" -auto-approve

# Ahora hay archivos en dos subdirectorios
ls -la output/
ls -la output/produccion/

Verifica el contenido de metadata.json (debería ser JSON válido y bien formateado):

{
  "archivos_generados": [
    "./output/produccion/config.txt",
    "./output/produccion/README.txt"
  ],
  "autor": "Juan Garcia",
  "entorno": "produccion",
  "proyecto": "TiendaOnline",
  "terraform": {
    "gestionado": true,
    "workspace": "default"
  },
  "version": "1.0.0"
}

Limpia todos los recursos creados:

terraform destroy -auto-approve

  1. Errores Comunes y Cómo Resolverlos

Error: "provider not found"

Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/local:
│ could not connect to registry.terraform.io

Causa: No hay conexión a internet o el Terraform Registry está inaccesible.

Solución: Verifica tu conexión a internet. Si estás detrás de un proxy corporativo, configura las variables de entorno:

export HTTP_PROXY="http://proxy.empresa.com:8080"
export HTTPS_PROXY="http://proxy.empresa.com:8080"
export NO_PROXY="localhost,127.0.0.1"
terraform init

Error: "state lock"

Error: Error acquiring the state lock
│
│ Error message: Failed to obtain lock: failed to lock state file
│ Lock Info:
│   ID:        abc123
│   Path:      terraform.tfstate
│   Operation: OperationTypeApply
│   Who:       usuario@maquina
│   Version:   1.9.0
│   Created:   2024-01-15 10:30:00

Causa: Otro proceso de Terraform está ejecutando en el mismo directorio, o un proceso anterior se interrumpió sin liberar el bloqueo.

Solución:

# Si estás seguro de que no hay otro proceso ejecutándose:
terraform force-unlock <ID_del_lock>
# Por ejemplo: terraform force-unlock abc123

Error: "permission denied" al crear archivos

Error: Unable to open file for writing
│
│   with local_file.config,
│   on main.tf line 25, in resource "local_file" "config":
│   25:   filename = "/etc/mi-config.txt"
│
│ open /etc/mi-config.txt: permission denied

Causa: Estás intentando crear un archivo en un directorio donde el usuario que ejecuta Terraform no tiene permisos de escritura.

Solución: Usa un directorio donde tengas permisos (como tu directorio home o una subcarpeta del proyecto):

# En lugar de /etc/mi-config.txt, usa:
filename = "${path.module}/output/mi-config.txt"
# O una ruta en tu directorio home:
filename = "/home/tuusuario/output/mi-config.txt"

Error: "Invalid function argument"

Error: Invalid function argument
│
│   on main.tf line 42, in resource "local_file" "metadata":
│   42:     proyecto  = var.proyecto
│
│ Invalid value for "v" parameter: cannot parse as JSON

Causa: Intentaste usar jsondecode() con un string que no es JSON válido, o jsonencode() con un tipo incompatible.

Solución: Verifica que el argumento que pasas a las funciones sea del tipo correcto. Usa terraform console para probar expresiones:

# terraform console abre un REPL interactivo para evaluar expresiones HCL
terraform console
> jsonencode({nombre = "Terraform", version = 1})
"{\"nombre\":\"Terraform\",\"version\":1}"
> exit

Error: "This object does not have an attribute"

Error: Unsupported attribute
│
│   on outputs.tf line 5, in output "archivo_config":
│    5:   value = local_file.config.ruta
│
│ This object does not have an attribute named "ruta".

Causa: Estás accediendo a un atributo que no existe en el recurso. El atributo correcto es filename, no ruta.

Solución: Consulta la documentación del proveedor o usa terraform show para ver los atributos disponibles:

# Después de apply, ver todos los atributos del recurso
terraform state show local_file.config

Advertencia: "Changes to Outputs are outside of the Terraform plan"

Si ves esta advertencia, significa que el estado real no coincide con lo que Terraform esperaba encontrar (alguien modificó o eliminó el archivo manualmente). Simplemente ejecuta terraform apply de nuevo para que Terraform vuelva a aplicar su configuración.


Resumen del Módulo 1 y Qué Viene en el Módulo 2

Lo que has aprendido en el Módulo 1

A lo largo de estas cuatro lecciones has construido una base sólida en Terraform:

Lección 1 (01-01): Entendiste qué es Infrastructure as Code y por qué Terraform es la herramienta estándar del sector. Aprendiste el ciclo Write → Plan → Apply y cómo Terraform se compara con otras herramientas como Ansible, CloudFormation y Pulumi.

Lección 2 (01-02): Instalaste Terraform en tu sistema operativo usando el método más adecuado (apt, brew, chocolatey o binario manual). Aprendiste a gestionar múltiples versiones con tfenv y a resolver los errores más comunes durante la instalación.

Lección 3 (01-03): Comprendiste los cuatro pilares de Terraform: proveedores (plugins que conectan con plataformas externas), recursos (unidades de infraestructura), estado (mapa entre configuración y realidad) y el ciclo plan/apply. Memorizaste los comandos principales y cuándo usar cada uno.

Lección 4 (01-04 — esta lección): Ejecutaste tu primera configuración real de Terraform usando el proveedor hashicorp/local. Recorriste el ciclo completo init → plan → apply → show → destroy, inspeccionaste el archivo terraform.tfstate, usaste variables y la función jsonencode(), y resolviste los errores más comunes.

Conceptos clave del Módulo 1

Concepto Descripción
IaC Gestionar infraestructura mediante código versionable
Proveedor Plugin que conecta Terraform con una plataforma (AWS, local, etc.)
Recurso Componente de infraestructura que Terraform crea y gestiona
Estado Archivo terraform.tfstate que mapea código con infraestructura real
terraform init Descarga proveedores y configura el directorio de trabajo
terraform plan Muestra cambios sin ejecutarlos (siempre usar antes del apply)
terraform apply Ejecuta los cambios y actualiza el estado
terraform destroy Elimina todos los recursos gestionados
Variables Parámetros de entrada que hacen la configuración reutilizable
Outputs Valores de salida que Terraform muestra tras el apply

Qué aprenderás en el Módulo 2: Lenguaje HCL en Profundidad

El Módulo 2 se adentra en el lenguaje HCL y te dará las herramientas para escribir configuraciones sofisticadas:

  • 01: Sintaxis HCL completa: Tipos de datos, expresiones, funciones, condicionales y bucles
  • 02: Variables y Outputs: Variables de entrada, locales, de entorno y sensibles. Outputs con dependencias.
  • 03: Bloques resource y data: Ciclo de vida de recursos, count, for_each, data sources
  • 04: Proveedores en profundidad: Configuración avanzada, múltiples instancias del mismo proveedor, alias

Con las herramientas del Módulo 2 podrás escribir configuraciones reales de producción que gestionen docenas o cientos de recursos de forma dinámica y reutilizable.

© Copyright 2026. Todos los derechos reservados