· nervico-team · arquitectura-cloud · 12 min read
Infraestructura como código: Terraform vs CDK vs Pulumi
Comparativa práctica de Terraform, AWS CDK y Pulumi: diferencias reales en productividad, curva de aprendizaje, ecosistema, y cuándo elegir cada herramienta de infraestructura como código.
Si tu infraestructura existe solo en la consola de AWS, no existe realmente. Existe como conocimiento tácito en la cabeza de quien la creó. Cuando esa persona se va de vacaciones, se cambia de empresa o simplemente olvida por qué configuró algo de una manera específica, tu equipo hereda una infraestructura que nadie entiende completamente.
Infraestructura como código resuelve este problema. Toda la infraestructura se define en ficheros de texto que se versionan en Git, se revisan en pull requests y se despliegan de forma automatizada. Si algo se rompe, puedes reconstruirlo exactamente como estaba. Si necesitas un entorno idéntico a producción, lo creas ejecutando un comando.
El concepto es claro. La decisión difícil es qué herramienta usar. Las tres opciones principales son Terraform, AWS CDK y Pulumi. Cada una tiene una filosofía diferente, una curva de aprendizaje diferente y un ecosistema diferente. Este artículo las compara con profundidad técnica, ejemplos reales y una recomendación honesta.
Por qué infraestructura como código no es opcional
El coste de la infraestructura manual
La infraestructura creada manualmente en la consola tiene estos problemas:
No es reproducible: Si necesitas crear un segundo entorno (staging, disaster recovery), tienes que repetir cada paso manualmente. Cada repetición introduce variaciones.
No tiene historial: No sabes quién creó un recurso, cuándo ni por qué. No hay registro de cambios. No hay forma de hacer rollback.
No es revisable: Los cambios en infraestructura no pasan por ningún proceso de revisión. Alguien puede modificar un Security Group en producción sin que nadie lo sepa.
No escala: Con 5 recursos, la gestión manual es factible. Con 50, es frágil. Con 500, es imposible.
Los beneficios concretos de IaC
- Reproducibilidad: El mismo código produce la misma infraestructura. Siempre.
- Versionado: Git tiene el historial completo de cada cambio. Quién, cuándo, por qué, qué código de review.
- Revisión: Los cambios pasan por pull request. Otro ingeniero revisa antes de aplicar.
- Automatización: CI/CD aplica los cambios automáticamente tras la aprobación.
- Documentación: El código es la documentación. Si la infraestructura está en Terraform, el fichero de Terraform describe exactamente qué existe.
Terraform: el estándar de facto
Qué es Terraform
Terraform es una herramienta open source creada por HashiCorp en 2014. Define infraestructura en un lenguaje declarativo llamado HCL (HashiCorp Configuration Language). Soporta más de 3.000 proveedores: AWS, GCP, Azure, Cloudflare, GitHub, Datadog, PagerDuty, y prácticamente cualquier servicio con una API.
Cómo funciona
El flujo de trabajo de Terraform tiene tres pasos:
terraform init: Descarga los proveedores necesarios.terraform plan: Compara el estado deseado (el código) con el estado actual (el state file) y muestra qué va a crear, modificar o destruir.terraform apply: Ejecuta los cambios.
El state file es el componente crítico. Es un fichero JSON que almacena el estado actual de la infraestructura. Terraform lo compara con tu código para calcular qué cambios necesita hacer. Si el state file se corrompe o se pierde, Terraform no sabe qué existe y puede intentar recrear recursos que ya existen.
Almacenamiento del state: Nunca guardes el state file en Git. Usa un backend remoto:
- S3 + DynamoDB (recomendado en AWS): S3 almacena el fichero, DynamoDB gestiona el locking para evitar cambios concurrentes.
- Terraform Cloud/Enterprise: Backend gestionado por HashiCorp con UI, colaboración y governance.
Ejemplo: VPC con subnets en Terraform
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "production-vpc"
Environment = "production"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${count.index + 1}"
Type = "public"
}
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "private-subnet-${count.index + 1}"
Type = "private"
}
}Ventajas de Terraform
Multi-cloud real: El mismo lenguaje y flujo de trabajo para AWS, GCP, Azure y cientos de otros proveedores. Si tu estrategia incluye multi-cloud, Terraform es la única opción viable entre las tres.
Ecosistema masivo: Más de 3.000 providers, miles de módulos públicos en el Terraform Registry, amplia documentación comunitaria.
Plan antes de aplicar: terraform plan muestra exactamente qué va a cambiar antes de hacerlo. Es una red de seguridad que previene errores.
Madurez: 10 años de desarrollo. La mayoría de problemas comunes tienen soluciones documentadas.
Limitaciones de Terraform
HCL no es un lenguaje de programación: No tiene bucles for complejos, no tiene funciones definidas por el usuario, no tiene clases ni herencia. Los workarounds con count, for_each y dynamic blocks funcionan pero son verbosos y difíciles de leer.
State management es complejo: El state file es un punto de fallo. State locking, state migrations, importación de recursos existentes: todo requiere conocimiento específico.
Drift detection limitada: Terraform solo detecta drift cuando ejecutas terraform plan. Si alguien modifica un recurso en la consola, Terraform no se entera hasta el siguiente plan.
Velocidad de adopción de nuevos servicios AWS: Los providers de Terraform los mantiene la comunidad (o HashiCorp). Cuando AWS lanza un nuevo servicio, puede tardar semanas o meses en estar disponible en Terraform. CDK tiene acceso inmediato.
AWS CDK: infraestructura en lenguajes que ya conoces
Qué es CDK
AWS CDK (Cloud Development Kit) permite definir infraestructura en TypeScript, Python, Java, C# o Go. En lugar de un lenguaje específico como HCL, escribes código en un lenguaje que tu equipo ya domina. CDK genera plantillas de CloudFormation que AWS ejecuta.
Cómo funciona
- Escribes código: Defines tu infraestructura usando clases y constructos de CDK en tu lenguaje elegido.
cdk synth: CDK sintetiza el código en una plantilla de CloudFormation (JSON/YAML).cdk deploy: Sube la plantilla a CloudFormation, que ejecuta los cambios.
CDK no gestiona el state directamente. CloudFormation lo hace. Cada stack de CDK corresponde a un stack de CloudFormation, y CloudFormation mantiene el estado.
Ejemplo: VPC con subnets en CDK (TypeScript)
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class NetworkStack extends Stack {
public readonly vpc: ec2.Vpc;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
this.vpc = new ec2.Vpc(this, 'ProductionVpc', {
maxAzs: 2,
natGateways: 1,
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
cidrMask: 24,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
cidrMask: 24,
},
{
name: 'Isolated',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
cidrMask: 24,
},
],
});
}
}Observa la diferencia: CDK crea la VPC, las subnets, las tablas de rutas, el Internet Gateway, el NAT Gateway y todas las asociaciones con un solo constructo. En Terraform, necesitarías definir cada recurso individualmente.
Constructos: la abstracción clave
CDK organiza la infraestructura en tres niveles de abstracción:
L1 (CfnResources): Mapeo directo 1:1 con CloudFormation. Máximo control, mínima abstracción. Equivalente a los resources de Terraform.
L2 (Higher-level constructs): Constructos con valores por defecto sensatos y métodos auxiliares. El ejemplo de VPC anterior es L2. Configura automáticamente Security Groups, tablas de rutas y gateways con buenas prácticas.
L3 (Patterns): Constructos que combinan múltiples recursos para patrones comunes. Por ejemplo, ApplicationLoadBalancedFargateService crea un cluster ECS, un servicio Fargate, un ALB, target groups, listener rules y auto-scaling en un solo constructo.
Ventajas de CDK
Lenguajes reales: Autocompletado, type checking, refactoring, tests unitarios. Tu IDE sabe qué propiedades existen. Los errores de tipo se detectan antes de desplegar.
Abstracciones potentes: Los constructos L2 y L3 encapsulan buenas prácticas. Un desarrollador junior puede crear una arquitectura sólida sin conocer cada detalle de CloudFormation.
Acceso inmediato a nuevos servicios AWS: CDK se genera a partir de la especificación de CloudFormation. Cuando AWS lanza un nuevo servicio, está disponible en CDK el mismo día.
Tests unitarios: Puedes testear tu infraestructura con Jest, pytest o JUnit. Verificar que tu VPC tiene el número correcto de subnets, que tu bucket S3 tiene cifrado activado, que tu Lambda tiene el timeout configurado correctamente.
Compartir código: Crea librerías de constructos personalizados para tu organización. Un constructo “MiEmpresaRestApi” que incluye API Gateway, Lambda, DynamoDB, alarmas de CloudWatch y tags de compliance. Reutilizable por todos los equipos.
Limitaciones de CDK
Dependencia total de CloudFormation: CDK genera CloudFormation. Los límites de CloudFormation son los límites de CDK: 500 recursos por stack, tiempos de rollback largos, debugging de errores a nivel de CloudFormation (no de CDK).
Solo AWS: CDK es exclusivo de AWS. Si necesitas gestionar recursos en GCP, Azure o servicios de terceros, necesitas otra herramienta.
CloudFormation drift: Si alguien modifica un recurso fuera de CDK/CloudFormation, CloudFormation puede entrar en estado inconsistente. La detección de drift existe pero no es perfecta.
Curva de aprendizaje de los constructos: Aunque uses un lenguaje que conoces, los constructos de CDK tienen su propia API que necesitas aprender. La documentación es extensa pero no siempre clara.
Pulumi: el competidor emergente
Qué es Pulumi
Pulumi es una herramienta de infraestructura como código que, como CDK, permite usar lenguajes de programación reales (TypeScript, Python, Go, C#, Java). A diferencia de CDK, Pulumi no depende de CloudFormation. Tiene su propio motor de ejecución y soporta múltiples proveedores cloud.
Cómo funciona
- Escribes código: Similar a CDK, defines infraestructura en tu lenguaje elegido.
pulumi preview: Equivalente aterraform plan. Muestra qué va a cambiar.pulumi up: Aplica los cambios directamente contra las APIs de los proveedores.
Pulumi gestiona su propio state, que puede almacenarse en:
- Pulumi Cloud: Backend gestionado (gratuito para uso individual, de pago para equipos).
- S3, Azure Blob, GCS: Backends auto-gestionados.
- Local: Solo para desarrollo.
Ejemplo: VPC con subnets en Pulumi (TypeScript)
import * as aws from '@pulumi/aws';
import * as awsx from '@pulumi/awsx';
const vpc = new awsx.ec2.Vpc('production-vpc', {
cidrBlock: '10.0.0.0/16',
numberOfAvailabilityZones: 2,
natGateways: { strategy: 'Single' },
subnetStrategy: 'Auto',
subnetSpecs: [
{ type: awsx.ec2.SubnetType.Public, cidrMask: 24 },
{ type: awsx.ec2.SubnetType.Private, cidrMask: 24 },
{ type: awsx.ec2.SubnetType.Isolated, cidrMask: 24 },
],
});
export const vpcId = vpc.vpcId;
export const publicSubnetIds = vpc.publicSubnetIds;
export const privateSubnetIds = vpc.privateSubnetIds;Ventajas de Pulumi
Multi-cloud con lenguajes reales: La combinación que ni Terraform ni CDK ofrecen. Lenguajes de programación reales con soporte multi-cloud.
Sin CloudFormation: Pulumi interactúa directamente con las APIs de los proveedores. Sin los límites de 500 recursos por stack, sin tiempos de rollback de CloudFormation, sin la capa de abstracción adicional.
Ecosystem Crosswalk (awsx): Componentes de alto nivel similares a los constructos L3 de CDK. Menos maduros pero en desarrollo activo.
Policy as Code: Pulumi CrossGuard permite definir políticas de compliance en código que se evalúan antes de cada despliegue. “Ningún bucket S3 puede ser público” se expresa como una política ejecutable.
Limitaciones de Pulumi
Menor adopción: Terraform tiene 10 años de ecosistema. CDK tiene el respaldo de AWS. Pulumi es más reciente y tiene menos recursos comunitarios, menos ejemplos y menos ingenieros que lo conocen.
Backend gestionado: Pulumi empuja hacia su servicio cloud gestionado. Los backends auto-gestionados funcionan pero requieren más configuración.
Documentación menos madura: Comparada con Terraform o CDK, la documentación de Pulumi tiene más gaps, especialmente para casos de uso avanzados.
Contratación: Encontrar ingenieros con experiencia en Pulumi es significativamente más difícil que encontrar ingenieros con experiencia en Terraform.
La comparativa directa
| Criterio | Terraform | AWS CDK | Pulumi |
|---|---|---|---|
| Lenguaje | HCL | TS, Python, Java, C#, Go | TS, Python, Go, C#, Java |
| Multi-cloud | Nativo | No (solo AWS) | Nativo |
| State management | Propio (S3+DynamoDB) | CloudFormation | Propio (Pulumi Cloud/S3) |
| Adopción en el mercado | Dominante | Creciente | Emergente |
| Curva de aprendizaje | Media (HCL) | Baja-Media | Baja-Media |
| Tests unitarios | Limitados | Nativos | Nativos |
| Abstracciones de alto nivel | Módulos | Constructos L2/L3 | Crosswalk (awsx) |
| Acceso a nuevos servicios AWS | Semanas/meses | Inmediato | Días/semanas |
| Ecosistema | Masivo | Grande | Creciente |
| Debugging | Plan + state | CloudFormation events | Preview + logs |
Cuándo elegir cada herramienta
Elige Terraform cuando
- Tu estrategia es multi-cloud o lo será en el futuro.
- Tu equipo ya conoce Terraform. El coste de cambiar a CDK o Pulumi rara vez se justifica si el equipo es productivo con Terraform.
- Necesitas gestionar recursos fuera de AWS: DNS en Cloudflare, monitoring en Datadog, repositorios en GitHub. Terraform tiene providers para todo.
- Prefieres un lenguaje declarativo que describe el estado final sin lógica de programación compleja.
Elige CDK cuando
- Tu infraestructura es 100% AWS y no hay planes de multi-cloud.
- Tu equipo es de desarrollo (no de operaciones) y domina TypeScript o Python. CDK permite que desarrolladores gestionen infraestructura sin aprender HCL.
- Necesitas abstracciones potentes: Los constructos L2 y L3 de CDK son los más maduros y completos del mercado.
- Quieres tests unitarios de infraestructura integrados en tu pipeline de CI.
- Necesitas acceso inmediato a nuevos servicios AWS el día que se lanzan.
Elige Pulumi cuando
- Necesitas multi-cloud con lenguajes reales. Es la única herramienta que ofrece ambas cosas.
- Los límites de CloudFormation son un problema para tu arquitectura (stacks grandes, despliegues lentos).
- Tu equipo quiere una experiencia moderna con un producto que evoluciona rápidamente.
- Policy as Code es un requisito de tu organización.
Patrones comunes de IaC
Estructura de proyecto
Independientemente de la herramienta, organiza tu infraestructura por capas:
infrastructure/
networking/ # VPC, subnets, NAT, VPN
security/ # IAM roles, policies, Security Groups
data/ # RDS, DynamoDB, ElastiCache, S3
compute/ # ECS, Lambda, EC2
monitoring/ # CloudWatch, alarms, dashboards
cicd/ # CodePipeline, GitHub Actions configCada capa es un módulo (Terraform), stack (CDK) o proyecto (Pulumi) independiente. Los cambios en networking no deberían requerir redesplegar compute.
GitOps para infraestructura
El flujo ideal:
- El ingeniero crea una rama y modifica el código de infraestructura.
- Abre un pull request. El CI ejecuta
plan/synth/previewy publica el resultado como comentario en el PR. - Otro ingeniero revisa el cambio y los recursos que se van a crear, modificar o destruir.
- Tras la aprobación, el merge a main dispara el despliegue automático.
Este flujo garantiza que cada cambio de infraestructura es revisado, documentado y reversible.
Gestión de entornos
No copies código para cada entorno. Usa parametrización:
- Terraform: Variables y workspaces (o directorios separados con módulos compartidos).
- CDK: Props de los stacks y Context values.
- Pulumi: Stack configurations y config files.
El código es el mismo. Los parámetros cambian: nombres, tamaños de instancia, número de réplicas, dominios.
Importación de infraestructura existente
Si ya tienes infraestructura creada manualmente, las tres herramientas permiten importarla:
- Terraform:
terraform importpara recursos individuales, o herramientas comoterraformerpara importación masiva. - CDK:
cdk import(experimental) o CloudFormation resource import. - Pulumi:
pulumi importcon generación automática de código.
La importación nunca es perfecta. Espera invertir tiempo en ajustar el código generado para que coincida con tu estilo y estructura.
Conclusión
Infraestructura como código no es una opción. Es un requisito para cualquier equipo que quiera operar infraestructura de forma profesional. La herramienta que elijas importa menos que el hecho de elegir una y usarla consistentemente.
Si tienes un equipo DevOps que ya conoce Terraform, sigue con Terraform. Si tienes un equipo de desarrollo TypeScript que gestiona infraestructura AWS, CDK es probablemente la opción más productiva. Si necesitas multi-cloud con la potencia de un lenguaje de programación, evalúa Pulumi.
Lo que no es aceptable es no usar ninguna. Cada recurso creado manualmente en la consola es una deuda operativa que alguien tendrá que pagar.
En NERVICO ayudamos a equipos a adoptar infraestructura como código con la herramienta adecuada para su contexto. Solicita una auditoría gratuita y evaluamos el estado de tu infraestructura y la estrategia de IaC más adecuada.