En pocas palabras
Herramientas de IaC que describen recursos de nube en HCL, calculan un plan de cambios contra el estado real y lo aplican. OpenTofu es el fork open source de Terraform gestionado por la Linux Foundation.
Qué problema resuelve
Infraestructura creada a mano en consolas, irreproducible entre entornos, sin historial de cambios ni revisión.
Cuándo utilizarlo
Cualquier entorno de nube con más de unos pocos recursos. Ejemplo: replicar la configuración de Cloud Run, VPC y Cloud SQL de un país en otro.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
Terraform u OpenTofu
En 2023 HashiCorp cambió la licencia de Terraform a BSL 1.1; la comunidad creó OpenTofu bajo MPL 2.0. Ambos comparten sintaxis HCL y la mayoría de proveedores. OpenTofu añade funciones como el cifrado del estado en el cliente. La elección depende de licencia, soporte comercial (HCP Terraform) y ecosistema de la organización.
Ciclo de trabajo
tofu init # descarga proveedores y configura el backend
tofu plan # calcula diferencias entre código y realidad
tofu apply # aplica el plan revisado
En CI, el plan se publica como comentario en el pull request y el apply se ejecuta solo tras la aprobación y el merge.
Ejemplo: servicio de Cloud Run
terraform {
backend "gcs" {
bucket = "krediya-tfstate"
prefix = "originacion/prod"
}
}
resource "google_cloud_run_v2_service" "api" {
name = "api-solicitudes"
location = "us-east1"
template {
service_account = google_service_account.api.email
scaling {
min_instance_count = 1
max_instance_count = 20
}
containers {
image = "us-east1-docker.pkg.dev/krediya/apps/api-solicitudes:${var.version}"
resources {
limits = { cpu = "1", memory = "512Mi" }
}
env {
name = "DB_PASSWORD"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.db.secret_id
version = "latest"
}
}
}
}
}
}
Estructura y estado
| Práctica | Por qué |
|---|---|
| Un estado por entorno y dominio | Limita el radio de impacto de un apply |
| Módulos versionados | Reutilizar patrones (servicio + SA + alertas) entre países |
| Backend remoto con bloqueo | Evita aplicaciones concurrentes (GCS tiene bloqueo nativo) |
| Secretos fuera del código | Usa Secret Manager; el estado puede contener valores sensibles |
| Detección de drift | plan programado que alerta si alguien cambió algo a mano |
Antipatrones frecuentes
- Un único estado gigante para toda la organización: planes de 20 minutos y miedo a aplicar.
applydesde portátiles con credenciales personales.terraform importmasivo sin refactorizar: se replica el desorden de la consola en código.
Módulo reutilizable
# modules/servicio-cloud-run/variables.tf
variable "nombre" { type = string }
variable "imagen" { type = string }
variable "region" { type = string }
variable "max_instancias" {
type = number
default = 10
validation {
condition = var.max_instancias <= 50
error_message = "Más de 50 instancias requiere revisión de conexiones a la base de datos."
}
}
# entornos/prod/originacion.tf
module "api_solicitudes" {
source = "git::https://github.com/krediya/terraform-modules.git//servicio-cloud-run?ref=v3.2.0"
nombre = "api-solicitudes"
imagen = var.imagen_api
region = "us-east1"
max_instancias = 20
}
El módulo agrupa cuenta de servicio, servicio, alertas y permisos con las convenciones de la organización. Fijar ref a una versión evita que un cambio del módulo afecte a todos los entornos a la vez.
Pruebas de módulos
# tests/servicio.tftest.hcl
variables {
nombre = "prueba"
imagen = "us-docker.pkg.dev/cloudrun/container/hello"
region = "us-east1"
}
run "valida_limite_instancias" {
command = plan
variables { max_instancias = 80 }
expect_failures = [var.max_instancias]
}
run "usa_cuenta_de_servicio_dedicada" {
command = plan
assert {
condition = google_cloud_run_v2_service.this.template[0].service_account != ""
error_message = "El servicio debe usar una cuenta de servicio dedicada."
}
}
terraform test (o tofu test) ejecuta los run en orden; con command = plan no crea recursos.
Refactorizar sin destruir
moved {
from = google_cloud_run_v2_service.api
to = module.api_solicitudes.google_cloud_run_v2_service.this
}
import {
to = google_storage_bucket.documentos
id = "krediya-documentos-prod"
}
removed {
from = google_storage_bucket.temporal
lifecycle { destroy = false } # dejar de gestionarlo sin borrarlo
}
Estos bloques sustituyen a comandos manuales sobre el estado (state mv, import, state rm) y quedan revisados en el pull request.
Flujo en CI
| Paso en el PR | Herramienta |
|---|---|
| Formato y validación | fmt -check, validate, tflint |
| Seguridad y políticas | Trivy/Checkov, Conftest sobre el plan |
| Plan publicado como comentario | GitHub Actions / GitLab CI, Atlantis, HCP Terraform, Spacelift |
| Apply tras merge | Identidad de CI con OIDC, sin claves, con aprobación en producción |
Versiona también .terraform.lock.hcl y declara versiones de proveedores en required_providers, para que todos usen las mismas.
Criterios de implementación
Empieza por los recursos nuevos y trae los existentes gradualmente con bloques import. Ejecuta análisis estático (tflint, Trivy o Checkov) en el pipeline como parte de continuous compliance. Compara con Crossplane si la organización gestiona ya todo desde Kubernetes.
Continúa en las fuentes
Documentación oficial para verificar detalles y explorar más.