Saltar al contenido principal

Conceptos Infrastructure as Code

¿Qué es IaC?​

Infrastructure as Code (IaC) es la práctica de gestionar y aprovisionar la infraestructura mediante archivos de configuración en lugar de procesos manuales.

┌─────────────────────────────────────────────────────────────┐
│ IaC vs MANUAL │
├─────────────────────────────────────────────────────────────┤
│ │
│ APROVISIONAMIENTO MANUAL │
│ ─────────────────────── │
│ 1. Abrir la consola de AWS │
│ 2. Hacer clic en "Launch Instance" │
│ 3. Configurar manualmente... │
│ 4. Repetir para cada recurso │
│ 5. Documentar los parámetros │
│ │
│ Problemas: │
│ ❌ No reproducible │
│ ❌ Errores humanos │
│ ❌ Sin control de versiones │
│ ❌ Documentación obsoleta │
│ ❌ Difícil de auditar │
│ │
│ ──────────────────────────────────────────────────────── │
│ │
│ INFRASTRUCTURE AS CODE │
│ ────────────────────── │
│ 1. Escribir una plantilla (YAML/JSON) │
│ 2. Versionar en Git │
│ 3. Desplegar con CloudFormation │
│ 4. Automatizar vía CI/CD │
│ │
│ Ventajas: │
│ ✅ Reproducible (mismo resultado cada vez) │
│ ✅ Versionado (historial completo) │
│ ✅ Revisión de código (peer review) │
│ ✅ Documentación viva (el código ES la documentación) │
│ ✅ Automatizable (CI/CD) │
│ │
└─────────────────────────────────────────────────────────────┘

AWS CloudFormation​

Visión General​

┌─────────────────────────────────────────────────────────────┐
│ CLOUDFORMATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ COMPONENTES: │
│ │
│ ┌─────────────┐ │
│ │ TEMPLATE │ Archivo YAML/JSON que describe │
│ │ (código) │ la infraestructura deseada │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ STACK │ Instancia de una plantilla │
│ │ │ con recursos reales │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ RECURSOS AWS │ │
│ │ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ VPC │ │ EC2 │ │ RDS │ │ ALB │ │ SG │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CICLO DE VIDA: │
│ Create → Update → Delete │
│ (o Rollback si hay error) │
│ │
└─────────────────────────────────────────────────────────────┘

Estructura de una Plantilla​

Secciones​

AWSTemplateFormatVersion: "2010-09-09"
Description: Descripción de la plantilla

# 1. PARAMETERS - Variables de entrada
Parameters:
EnvironmentType:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]

# 2. MAPPINGS - Tablas de búsqueda
Mappings:
RegionAMI:
us-east-1:
AMI: ami-0123456789

# 3. CONDITIONS - Lógica condicional
Conditions:
IsProd: !Equals [!Ref EnvironmentType, prod]

# 4. RESOURCES - Los recursos a crear (OBLIGATORIO)
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
InstanceType: t3.micro

# 5. OUTPUTS - Valores exportados
Outputs:
InstanceId:
Value: !Ref MyEC2Instance
Export:
Name: MyInstanceId

Tipos de Recursos Comunes​

TipoDescripción
AWS::EC2::InstanceInstancia EC2
AWS::EC2::VPCVPC
AWS::EC2::SubnetSubred
AWS::EC2::SecurityGroupSecurity Group
AWS::RDS::DBInstanceBase de datos RDS
AWS::S3::BucketBucket S3
AWS::Lambda::FunctionFunción Lambda
AWS::ElasticLoadBalancingV2::LoadBalancerALB/NLB

Funciones Intrínsecas​

Las Más Utilizadas​

Resources:
# !Ref - Referenciar un parámetro o recurso
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType # Parámetro
SubnetId: !Ref MySubnet # Recurso

# !GetAtt - Obtener un atributo de un recurso
MyDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
Name: app.example.com
ResourceRecords:
- !GetAtt MyInstance.PublicIp # IP pública de la instancia

# !Sub - Sustitución de variables
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${AWS::StackName}-${AWS::Region}-data"

# !Join - Concatenar valores
MyTag:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Name
Value: !Join ["-", [web, !Ref EnvironmentType, server]]

# !If - Condición
MyVolume:
Type: AWS::EC2::Volume
Properties:
Size: !If [IsProd, 100, 20] # 100 GB en prod, 20 si no

# !FindInMap - Búsqueda en Mappings
MyInstance2:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]

Ejemplo Completo: Infraestructura Web​

AWSTemplateFormatVersion: "2010-09-09"
Description: Infraestructura web simple con EC2 y Security Group

Parameters:
Environment:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]
Description: Environment name

InstanceType:
Type: String
Default: t3.micro
AllowedValues: [t3.micro, t3.small, t3.medium]

KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: EC2 Key Pair for SSH access

Mappings:
RegionAMI:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
eu-west-1:
AMI: ami-0d729a60

Resources:
# Security Group
WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP and SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub "${Environment}-web-sg"
- Key: Environment
Value: !Ref Environment

# EC2 Instance
WebServer:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
SecurityGroupIds:
- !Ref WebSecurityGroup
Tags:
- Key: Name
Value: !Sub "${Environment}-web-server"
- Key: Environment
Value: !Ref Environment
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from CloudFormation!</h1>" > /var/www/html/index.html

Outputs:
InstanceId:
Description: Instance ID
Value: !Ref WebServer
Export:
Name: !Sub "${Environment}-WebServerId"

PublicIP:
Description: Public IP address
Value: !GetAtt WebServer.PublicIp

WebsiteURL:
Description: URL of the website
Value: !Sub "http://${WebServer.PublicIp}"

Comandos CLI​

# Validar una plantilla
aws cloudformation validate-template \
--template-body file://template.yaml

# Crear un stack
aws cloudformation create-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=Environment,ParameterValue=dev \
ParameterKey=KeyName,ParameterValue=my-key

# Ver el estado del stack
aws cloudformation describe-stacks \
--stack-name my-web-stack

# Ver los eventos (debug)
aws cloudformation describe-stack-events \
--stack-name my-web-stack

# Actualizar un stack
aws cloudformation update-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=Environment,ParameterValue=staging

# Eliminar un stack
aws cloudformation delete-stack \
--stack-name my-web-stack

Buenas Prácticas​

┌─────────────────────────────────────────────────────────────┐
│ BUENAS PRÁCTICAS CLOUDFORMATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ HACER │
│ ──────── │
│ • Versionar las plantillas en Git │
│ • Usar parámetros para flexibilidad │
│ • Agregar descripciones claras │
│ • Usar nombres lógicos y significativos │
│ • Validar antes de desplegar │
│ • Usar Change Sets para previsualización │
│ • Etiquetar todos los recursos │
│ │
│ ❌ EVITAR │
│ ───────── │
│ • Hardcodear valores (AMIs, IPs...) │
│ • Crear plantillas monolíticas (> 500 líneas) │
│ • Ignorar errores de validación │
│ • Desplegar sin revisión de código │
│ • Olvidar los outputs para referencias │
│ │
└─────────────────────────────────────────────────────────────┘

Resumen​

ConceptoDescripción
TemplateArchivo YAML/JSON que describe la infraestructura
StackInstancia desplegada de una plantilla
ParametersVariables de entrada configurables
ResourcesLos recursos AWS a crear
OutputsValores exportados para referencia
!RefReferenciar un recurso o parámetro
!GetAttObtener un atributo de un recurso

Próxima sección: Lab CloudFormation