Última revisión: mayo de 2026
Crea los servicios de AWS del examen SAA-C03 con Terraform puro: bloque a bloque, cada uno vinculado a un dominio del examen. El mismo código funciona en OpenTofu.
Al final de este laboratorio, habrá aprovisionado, con Terraform simple, una pila web de alta disponibilidad multi-AZ de libro de texto: una VPC personalizada con subredes públicas y privadas en dos AZs, un Balanceador de Carga de Aplicación con acceso a internet, un Grupo de Autoescalado de instancias EC2 en el nivel privado y una base de datos RDS multi-AZ para que la aplicación se comunique. Cinco pilares del examen en cinco pasos.
Cada recurso es Terraform simple; el mismo código funciona sin modificaciones en OpenTofu. Sin variables, sin módulos, sin estado remoto. Suelte los fragmentos en un único main.tf, ejecute terraform init una vez, luego terraform apply paso a paso.
>= 1.5 o OpenTofu >= 1.6.us-east-1 (región predeterminada para este laboratorio; elija la que desee, pero la búsqueda de AMI en el Paso 3 asume que la región tiene Amazon Linux 2023).skip_final_snapshot = true para que la destrucción sea limpia; nunca use esa configuración en producción.La mayor parte de este laboratorio es de la Capa Gratuita o cercano a ella: la VPC, ALB, ASG, grupos de seguridad, IAM y la monitorización de CloudWatch son gratuitos. Los dos elementos que generan facturación en estado inactivo:
Si es sensible al coste, configure db_instance.multi_az = false para el laboratorio y lea la documentación de Multi-AZ por separado. El examen sigue recompensando el conocimiento del atributo aunque no ejecute el patrón completo de HA. Destruya al finalizar.
Fijamos el proveedor de AWS ~> 5.60 y elegimos us-east-1 (cualquier región con al menos dos AZs funciona). El bloque data obtiene la lista de AZs disponibles en tiempo de planificación; codificar nombres de AZs como us-east-1a es un antipatrón de SAA-C03 porque el mapeo de nombres de AZ a zonas físicas es específico de cada cuenta (su us-east-1a puede ser una AZ física diferente a la mía).
Todos los recursos que creamos a continuación se etiquetan con un único nombre de proyecto a través de default_tags; Cost Explorer + las reglas de AWS Config funcionan con etiquetas, y el examen espera que etiquete todo.
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Project = "certlabpro-saa-c03"
ManagedBy = "terraform"
}
}
}
data "aws_availability_zones" "available" {
state = "available"
}Cada pregunta de alta disponibilidad de SAA-C03 asume que distribuirá la carga de trabajo en al menos dos Zonas de Disponibilidad. Creamos una VPC /16 y dividimos cuatro subredes /20: dos públicas (para el ALB), dos privadas (para las instancias EC2 y RDS). El gateway de internet se adjunta a la VPC; la tabla de rutas públicas envía 0.0.0.0/0 a través de él.
Las subredes privadas deliberadamente NO tienen un gateway NAT en este laboratorio; los gateways NAT facturan aproximadamente $32/mes en estado inactivo (por AZ) y SAA-C03 evalúa explícitamente esta compensación en preguntas de costes. Si su aplicación necesitara internet saliente desde subredes privadas en producción, agregaría un NAT (o una instancia NAT, la alternativa más económica de SAA-C03).
La VPC + subredes + IGW + tabla de rutas de este paso son el lienzo para todo lo que sigue: el ALB se conecta a las subredes públicas, las instancias del ASG residen en las privadas, y el grupo de subredes de RDS en el Paso 5 abarca ambas AZs privadas.
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "certlabpro-saa-c03-vpc" }
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = { Name = "certlabpro-saa-c03-public-${count.index}" }
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = { Name = "certlabpro-saa-c03-private-${count.index}" }
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
count = 2
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}Un Application Load Balancer es el balanceador de carga que SAA-C03 espera que elija siempre que la pregunta mencione "HTTP / HTTPS" o "enrutamiento basado en rutas" o "dirigirse a un servicio específico". Los Network Load Balancers manejan TCP/UDP y latencia ultrabaja; Classic es un legado. Un ALB es la opción.
El ALB reside en las dos subredes públicas del Paso 2; eso es lo que significa "multi-AZ" estructuralmente. Su grupo de seguridad acepta HTTP (puerto 80) desde cualquier lugar; el grupo de destino obtendrá sus miembros del ASG que crearemos en el Paso 4. La comprobación de estado es el contrato entre el ALB y el destino: si / devuelve un valor distinto de 200, el ALB deja de enviar tráfico a esa instancia.
No hay HTTPS en este laboratorio; eso requiere un certificado ACM y un nombre DNS, que son dos servicios más que no necesitamos para hacer visible el patrón de HA. Agregue ACM en producción.
resource "aws_security_group" "alb" {
name = "certlabpro-saa-c03-alb"
description = "ALB ingress on port 80 from the internet"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_lb" "web" {
name = "certlabpro-saa-c03-alb"
load_balancer_type = "application"
internal = false
subnets = aws_subnet.public[*].id
security_groups = [aws_security_group.alb.id]
}
resource "aws_lb_target_group" "web" {
name = "certlabpro-saa-c03-tg"
port = 80
protocol = "HTTP"
target_type = "instance"
vpc_id = aws_vpc.main.id
health_check {
path = "/"
matcher = "200-299"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 3
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.web.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}El Auto Scaling es el pilar de "elasticidad" de AWS Well-Architected y el segundo tema más evaluado en SAA-C03 después de Multi-AZ. Combinado con el ALB del Paso 3, un ASG le proporciona tanto tolerancia a fallos (instancias reemplazadas cuando fallan) como escalabilidad (el recuento de instancias sigue la demanda), los dos resultados sobre los que SAA-C03 sigue preguntando.
La plantilla de lanzamiento define cómo es cada nueva instancia. Utilizamos la AMI más reciente de Amazon Linux 2023, una t3.micro, el SG equivalente al del Paso 2 que acepta tráfico solo del SG del ALB (privilegio mínimo en la capa de red), y un user-data mínimo que inicia nginx para que la comprobación de estado pase.
El ASG une tres cosas: dónde se ejecutan las instancias (vpc_zone_identifier = nuestras subredes privadas, ambas AZs), cuántas deben existir (min_size = 2, max_size = 4 — dos para HA, margen para escalado), y cómo las nuevas instancias se unen al balanceador de carga (target_group_arns). Cuando el ASG lanza una instancia, esta se registra automáticamente con el grupo de destino del Paso 3.
resource "aws_security_group" "app" {
name = "certlabpro-saa-c03-app"
description = "App instances accept traffic only from the ALB SG"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-kernel-6.1-x86_64"]
}
}
resource "aws_launch_template" "app" {
name_prefix = "certlabpro-saa-c03-app-"
image_id = data.aws_ami.al2023.id
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.app.id]
metadata_options {
http_tokens = "required"
}
user_data = base64encode(<<-EOT
#!/bin/bash
dnf install -y nginx
systemctl enable --now nginx
EOT
)
}
resource "aws_autoscaling_group" "app" {
name = "certlabpro-saa-c03-app-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
min_size = 2
max_size = 4
desired_capacity = 2
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
}La joya de la corona de cualquier historia multi-AZ de SAA-C03 es una base de datos RDS Multi-AZ. La configuración multi_az = true es uno de los atributos más evaluados en todo el examen: le indica a RDS que aprovisione una réplica en espera síncrona en una segunda AZ. Cuando la primaria falla, RDS promueve automáticamente la réplica en espera; la conmutación por error típica tarda ~60 segundos sin pérdida de datos. Dos bases de datos de una sola AZ NO le darían eso; la replicación manual NO le daría eso. Multi-AZ es la respuesta a cualquier pregunta sobre "conmutación por error en menos de un minuto, cero pérdida de datos".
El grupo de subredes de la base de datos necesita subredes en al menos dos AZs; le proporcionamos las subredes privadas del Paso 2. El grupo de seguridad acepta el puerto de la base de datos (5432 para PostgreSQL) solo del SG de la aplicación, reflejando el patrón de seguridad por capas del Paso 4.
Con esta pieza final, la pila está completa: el tráfico entra al ALB en cualquier AZ pública, se distribuye a las instancias del ASG en cualquier AZ privada, y esas instancias se comunican con la instancia primaria de RDS (que tiene una réplica en espera en la otra AZ). Cualquier cosa, excepto un fallo total de la región, tiene una ruta de recuperación.
resource "aws_db_subnet_group" "main" {
name = "certlabpro-saa-c03"
subnet_ids = aws_subnet.private[*].id
}
resource "aws_security_group" "db" {
name = "certlabpro-saa-c03-db"
description = "DB accepts traffic only from the app SG"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
}
resource "aws_db_instance" "main" {
identifier = "certlabpro-saa-c03"
engine = "postgres"
engine_version = "16"
instance_class = "db.t3.micro"
allocated_storage = 20
storage_encrypted = true
multi_az = true # the SAA-C03 headline
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.db.id]
username = "appuser"
password = "ChangeMe-Not-For-Prod-1234" # use Secrets Manager in production
skip_final_snapshot = true # lab-only setting; never use on prod
apply_immediately = true
}terraform destroy desmonta todo en este laboratorio. Dos notas:
skip_final_snapshot = true, por lo que destroy se completa en unos minutos sin dejar una instantánea. Nunca establezca esa bandera en una base de datos de producción; perder la instantánea final es una pérdida permanente de datos.destroy para el propio ASG no se completa hasta que todas las instancias se hayan ido, lo que puede tardar entre 2 y 3 minutos. Sea paciente.Ctrl-C la destrucción a mitad de camino; deje que termine.SAA-C03 cubre más patrones arquitectónicos de los que un solo laboratorio puede demostrar: CloudFront para distribución global de contenido, Route 53 para conmutación por error basada en DNS, replicación entre regiones de S3, Aurora Global Database, Direct Connect, emparejamiento de VPC, Transit Gateway, ElastiCache, EFS, FSx, y muchos más.
Nos apegamos deliberadamente al patrón más evaluado en el examen: HA multi-AZ dentro de una sola región. Esa es la arquitectura que aparece en cada entrevista de Arquitecto de Soluciones y en aproximadamente el 30% de las preguntas de SAA-C03. El 70% restante – patrones globales, almacenamiento en caché, redes avanzadas, nube híbrida – se cubre conceptualmente en las secciones de Buscar y Editorial de esta página de certificación. Cada tema de replicación entre regiones o redes avanzadas merece su propio laboratorio; construir una mega-pila diluiría la disciplina de la historia de construcción de la que depende este formato.
Si desea práctica práctica con los patrones entre regiones (S3 CRR, Aurora Global, comprobaciones de estado de Route 53), estos se asignan claramente a la misma forma de Terraform simple y son buenos candidatos para laboratorios de seguimiento.