En este post, exploraremos cómo implementar infraestructura en AWS utilizando Terraform, desplegando componentes esenciales como una VPC, Subnets, Route Tables, un Internet Gateway y una instancia EC2 en cada subred. Aprenderás a definir y gestionar estos recursos de manera automatizada, asegurando una configuración escalable y reproducible en la nube. ¡Vamos a construir nuestra infraestructura como código paso a paso!
Pasos: Crear la VPC, Subnet Pública con su rango de IPs, Crear una Subnet Privada con su rango de IPs, Crear un Internet Gateway, Crear una Instancia EC2 dentro de la Subnet Pública, Crear una Instancia EC2 dentro de la Subnet Privada, Crear la Table de Rutas de ambas subredes, Configurar un VPC Endpoint. El VPC Endpoint ayudará a la Instancia EC2 que se encuentra en la subred Privada a comunicarse con un Bucket S3 que reside en la cuenta de AWS. Crear los archivos y directorios
Crear la VPC
crear el archivo main.tf Dentro del main.tf crear un modulo para Networking y definir las variables para el cidr, nombre de la vpc, cidr de la subred publica, cidr de la subred privada, y la variable de la zona de disponiblidad
En el modulo podemos ver un directorio source = “./networking” y tenemos la carpeta networking. Dentro del directorio networking esta el archivo main.tf que contiene variables de salida y entre otras cosas la configuración de la VPC donde se requiere asignarle el rango de ip 11.0.0.0/16. Allí mismo definimos la VPC donde le pasamos la variable cidr_block = var.vpc_cidr que aun no hemos creado.
Debemos crear el archivo terraform.tfvars también en la raíz del proyecto. Allí definimos los valores de las variables.
Dentro de terraform.tfvars le asignamos el valor a la variable -> vpc_cidr = “11.0.0.0/16” y de el resto de valores de las variables. Como queremos crear 2 subredes publicas y 2 subredes privadas enviamos los valores en forma de lista, asi como las 2 zonas de disponiblidad.
En este momento podriamos hacer un terraform init. Es el primer comando que debes ejecutar cuando comienzas un nuevo proyecto en Terraform, y lo que hace es Descargar proveedores (providers) y los instala cuando están definidos en el archivo main.tf
Abrimos la terminal, nos aseguramos de estar en la misma carpeta del proyecto y ejecutamos:
terraform init
Una vez terminado el proceso, se mostrara el mensaje Terraform has been successfully initialized!
Ahora ejecutamos el comando:
terraform plan
terraform plan analiza tu configuración (.tf) y el estado actual de la infraestructura (en el archivo terraform.tfstate) y muestra un resumen de lo que va a hacer antes de aplicar.
Recibimos el resumen de lo que terraform hará y si todo esta conforme a lo solicitado, procedemos con el comando:
terraform apply -auto-approve
El comando terraform apply es el paso final del flujo principal de Terraform. Después de terraform init y terraform plan, este comando se encarga de crear, modificar o destruir recursos en tu proveedor de infraestructura (como AWS, Azure, GCP, etc.), según lo definido en tus archivos .tf.
Deberas tener configuradas tus credenciales de acceso a AWS desde la terminal. (aws configure)
Ten cuidado con el parametro -auto-approve, es un modificador para terraform apply que le dice a Terraform que ejecute el plan sin pedir confirmación del usuario.
Crea múltiples subnets según la cantidad de CIDR definidos en la variable var.cidr_public_subnet. count es una meta-argumento de Terraform que permite hacer una cantidad dinámica de recursos. length(var.cidr_public_subnet) determina cuántas subnets crear. Por ejemplo, si cidr_public_subnet tiene 3 elementos, se crearán 3 subnets.
Asigna un rango CIDR específico a cada subnet. element() toma un valor de la lista var.cidr_public_subnet usando el índice actual (count.index). Esto asegura que cada subnet tenga un rango distinto, como: [“11.0.1.0/24”, “11.0.2.0/24”, “11.0.3.0/24”].
Revisar y aplicar
terraform plan terraform apply.
Ve a AWS -> VPC y mira la magia -> Se creará una Route Table por defecto.
Crear Internet Gateway
Deberá ser adjuntada a la VPC En el main.tf del modulo networking ->
# Setup Internet Gateway
resource "aws_internet_gateway" "dev_proj_1_public_internet_gateway" {
vpc_id = aws_vpc.dev_proj_1_vpc_us_east_1.id
tags = {
Name = "dev-proj-1-igw"
}
}
Con la línea vpc_id = aws_vpc.dev_proj_1_vpc_us_east_1.id queda adjuntado a la VPC Aplicamos terraform plan Aplicamos terraform apply -auto-approve
Verificamos los cambios en AWS
Crear una Route Table
Una RT para las subredes publicas y una RT para las subredes privadas
En la Public Route Table, se debe adjuntar el ID de la VPC utilizando:
vpc_id = aws_vpc.dev_proj_1_vpc_us_east_1.id
Además, en el CIDR block, se debe definir el rango de salida hacia y desde internet como 0.0.0.0/0 Finalmente, es necesario adjuntar el ID del Internet Gateway. En el caso de la Private Route Table de la subred privada, es mas sencillo porque no requiere internet Gateway.
Asociar las Route Table a las subnets en el mismo main.tf del módulo Networking
# Public Route Table and Public Subnet Association
resource "aws_route_table_association" "dev_proj_1_public_rt_subnet_association" {
count = length(aws_subnet.dev_proj_1_public_subnets)
subnet_id = aws_subnet.dev_proj_1_public_subnets[count.index].id
route_table_id = aws_route_table.dev_proj_1_public_route_table.id
}
# Private Route Table and private Subnet Association
resource "aws_route_table_association" "dev_proj_1_private_rt_subnet_association" {
count = length(aws_subnet.dev_proj_1_private_subnets)
subnet_id = aws_subnet.dev_proj_1_private_subnets[count.index].id
route_table_id = aws_route_table.dev_proj_1_private_route_table.id
}
Con estas dos líneas se crea la asociación entre la tabla de rutas y la subnet
Las instancias EC2 requieren: el id de una ami, el id de la VPC, un id de subred, un security group, y un public_key. Para generar un par de llaves se puede hacer con ssh-keygen y luego pasar las credenciales manualmente a terraform en terraform.tfvars.
Se debe tener en cuenta que las instancias t2.medium tienen costo. No forma parte del free tier.
Asignar una subred a la instancia ec2 en la subred pública. subnet_id = tolist(module.networking.dev_proj_1_public_subnets_ids )[0] Acá se hace una lista de las subredes publicas que se están creando, luego se toma el primer elemento de la lista y se asigna el id a la instancia EC2. Asignar una subred a la instancia ec2 en la subred privada.
La instancia EC2 en la subred pública debe tener la opcion enable_public_ip_address = true mientras que la instancia EC2 en la subred debe colocarse en false ya que no es necesario.
Crear el Security Group
module "security_group" {
source = "./security-groups"
ec2_sg_name = "SG for EC2 to enable SSH(22), HTTPS(443), HTTP(8080) and HTTP(80)"
vpc_id = module.networking.dev_proj_1_vpc_id
ec2_jenkins_sg_name = "Allow port 8080 for jenkins"
}
Cada modulo debe tener su respectiva carpeta con el nombre del recurso
source = "./ec2"
source = "./security-groups"
En la carpeta ec2 -> main.tf creamos las variables
Se debe tener un par de llaves y se deben asignar a la instancia EC2 para poder acceder a ellas por ssh.
En el archivo variables.tf agregamos las sigientes líneas:
variable "public_key" {
type = string
description = "WP Project 1 Public key for EC2 instance"
}
variable "ec2_ami_id" {
type = string
description = "WP Project 1 AMI Id for EC2 instance"
}
También agregamos la variable para la AMI.
En el archivo terraform.tfvars se indican los valores estas dos variables.