Descripción General
Una conexión de red conocida como enlace de VPC peering te permite transportar tráfico entre dos VPC utilizando direcciones IP privadas. Puedes utilizar VPC peering para implementar recursos en la nube en una red virtual definida por el usuario. Las VPC permiten la comunicación entre instancias como si estuvieran en la misma red. Estos recursos permiten un transporte más seguro de datos.
¿Qué es VPC Peering y Cómo Funciona?
VPC peering es un método de conexión entre dos o más nubes privadas virtuales (VPCs). Una conexión de VPC peering se define como "un enlace de red entre dos VPC que permite enviar tráfico utilizando direcciones IP privadas (IPv4 o IPv6)." Las instancias en una VPC pueden comunicarse entre sí como si estuvieran en la misma red una vez unidas mediante una conexión de VPC peering.
Resumen de AWS VPC Peering Connection
AWS crea una conexión de VPC peering utilizando la arquitectura actual de una VPC; no es ni una puerta de enlace ni una conexión VPN, y no requiere ningún hardware físico adicional. En la comunicación, no hay un solo punto de fallo ni limitación de ancho de banda. 💻🔗
Para establecer una conexión de VPC peering, debes realizar lo siguiente:
El propietario de la VPC solicitante pide al propietario de la VPC aceptadora que cree una conexión de VPC peering. Tú u otra cuenta de AWS pueden controlar la VPC aceptadora, pero no puede tener un bloque CIDR idéntico al de la VPC solicitante.
El propietario de la VPC aceptadora aprueba la solicitud de conexión de VPC peering para iniciar la conexión.
Cada propietario de VPC en la conexión de VPC peering debe agregar manualmente una ruta que apunte al rango de direcciones IP de la otra VPC en una o más de sus tablas de enrutamiento de VPC para permitir el tráfico entre las VPC utilizando direcciones IP privadas.
Para asegurarte de que el tráfico hacia y desde la VPC emparejada no esté restringido, actualiza las reglas del grupo de seguridad relacionadas con tu instancia según sea necesario. Puedes utilizar un grupo de seguridad de la VPC emparejada como origen o destino en las reglas de tu grupo de seguridad si ambas VPC están en la misma región.
Cuando utilizas los parámetros de conexión de VPC peering predeterminados, un nombre de host DNS público es utilizado por las instancias EC2 hacia la dirección IP pública de la instancia. Para cambiar este comportamiento, habilita la resolución de nombres DNS para tu conexión de VPC. Después de habilitar la resolución de nombres DNS, si las instancias en ambos lados de la conexión de VPC peering se dirigen mutuamente utilizando un nombre de host DNS público, el nombre de host se resuelve a la dirección IP privada de la instancia.
Archivos Terraform
-
001-vpc.tf:
- Descripción: Define la infraestructura de la VPC.
- Propósito: Establece la red básica para la infraestructura.
- Funcionalidades: Configura subredes, tablas de rutas y grupos de seguridad.
# Definición de la primera VPC
module "vpc_a_1" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.1"
name = "vpc-a-1-${var.env}"
cidr = "172.16.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 1)
private_subnets = ["172.16.0.0/24"]
public_subnets = ["172.16.1.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
map_public_ip_on_launch = true
public_subnet_tags = {
orion = "public-subnet-a-1"
}
private_subnet_tags = {
orion = "private-subnet-a-1"
}
}
# Definición de la segunda VPC
module "vpc_b_2" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.1"
name = "vpc-b-2-${var.env}"
cidr = "10.1.0.0/16" # CIDR para la segunda VPC
azs = slice(data.aws_availability_zones.available.names, 0, 2)
private_subnets = ["10.1.0.0/24"]
public_subnets = ["10.1.1.0/24"]
enable_nat_gateway = true
single_nat_gateway = false
enable_dns_hostnames = true
map_public_ip_on_launch = true
public_subnet_tags = {
orion = "public-subnet-b-2"
}
private_subnet_tags = {
orion = "private-subnet-b-2"
}
}
-
002-sg.tf:
- Descripción: Define los grupos de seguridad.
- Propósito: Controla el tráfico de red dentro de la infraestructura.
- Funcionalidades: Establece reglas de seguridad para permitir o denegar el tráfico entre las vpc para este propósito.
resource "aws_security_group" "web_sg_a_1" {
name = "web-security-group-a-1-${var.env}"
description = "Permite el trafico HTTP desde el CIDR de la VPC"
vpc_id = module.vpc_a_1.vpc_id # Reemplaza "tu-vpc-id" con el ID de tu VPC
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [module.vpc_a_1.vpc_cidr_block] # Reemplaza con el CIDR de tu VPC
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [module.vpc_b_2.vpc_cidr_block] # Reemplaza con el CIDR de tu VPC secundaria
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-security-group-a-1-${var.env}"
}
}
resource "aws_security_group" "web_sg_b_2" {
name = "web-security-group-b-2-${var.env}"
description = "Permite el trafico HTTP desde el CIDR de la VPC"
vpc_id = module.vpc_b_2.vpc_id # Reemplaza "tu-vpc-id" con el ID de tu VPC
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [module.vpc_b_2.vpc_cidr_block] # Reemplaza con el CIDR de tu VPC secundaria
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [module.vpc_a_1.vpc_cidr_block] # Reemplaza con el CIDR de tu VPC primaria
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-security-group-b-2-${var.env}"
}
}
-
003-ec2.tf:
- Descripción: Configura las instancias EC2.
- Propósito: Define las características y cantidad de instancias necesarias.
- Funcionalidades: Especifica tipo de instancia, AMI y reglas de seguridad, adicionalmente se aprovisiona con apache para propósitos de pruebas y conexión entre ellas por el peering.
################################################################################
# EC2 Module
################################################################################
module "ec2_a_1" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "5.6.1"
name = "ec2-vpc-a-1-${var.env}"
instance_type = "t3a.micro"
subnet_id = element(module.vpc_a_1.private_subnets, 0)
vpc_security_group_ids = [aws_security_group.web_sg_a_1.id]
user_data = file("apache-config.sh")
user_data_replace_on_change = true
create_iam_instance_profile = true
iam_role_description = "IAM role for EC2 instance"
iam_role_policies = {
AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
metadata_options = {
http_tokens = "required"
}
}
module "ec2_b_2" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "5.6.1"
name = "ec2-vpc-b-2-${var.env}"
instance_type = "t3a.micro"
subnet_id = element(module.vpc_b_2.private_subnets, 0)
vpc_security_group_ids = [aws_security_group.web_sg_b_2.id]
user_data = file("apache-config.sh")
user_data_replace_on_change = true
create_iam_instance_profile = true
iam_role_description = "IAM role for EC2 instance"
iam_role_policies = {
AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
metadata_options = {
http_tokens = "required"
}
}
-
004-peering.tf:
- Descripción: Configura el peering de VPC.
- Propósito: Conecta dos VPC para la comunicación privada.
- Funcionalidades: Define recursos para el peering y enrutamiento.
resource "aws_vpc_peering_connection" "vpc_peer" {
vpc_id = module.vpc_a_1.vpc_id
peer_vpc_id = module.vpc_b_2.vpc_id
peer_region = local.aws_region
tags = {
Name = "Requester ${module.vpc_b_2.name}"
Side = "Requester"
}
}
resource "aws_vpc_peering_connection_options" "peer_options" {
vpc_peering_connection_id = aws_vpc_peering_connection.vpc_peer.id
accepter {
allow_remote_vpc_dns_resolution = true
}
requester {
allow_remote_vpc_dns_resolution = true
}
}
resource "aws_route" "primary_to_secondary" {
for_each = toset(module.vpc_a_1.private_route_table_ids)
route_table_id = each.value
destination_cidr_block = module.vpc_b_2.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.vpc_peer.id
}
resource "aws_route" "secondary_to_primary" {
for_each = toset(module.vpc_b_2.private_route_table_ids)
route_table_id = each.value
destination_cidr_block = module.vpc_a_1.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.vpc_peer.id
}
Otros Archivos
-
apache-config.sh:
- Descripción: Script de configuración de Apache.
- Propósito: Configura Apache en instancias EC2.
- Funcionalidades: Define la configuración del servidor web.
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
IPV4=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4)
# Crear el contenido HTML
hostname=$(hostname)
content="Deployed via Terraform\nHostname: $hostname\nIP-v4: $IPV4"
# Escribir el contenido en el archivo index.html
echo -e "$content" | sudo tee -a /var/www/html/index.html
-
demo.tfvars:
- Descripción: Archivo de variables Terraform.
- Propósito: Almacena valores para la ejecución de Terraform.
- Funcionalidades: Define variables para personalizar la infraestructura.
tf_version = "1.5.7"
env = "demo"
project = "vpc-tf"
owner = "franco.navarro"
cost = "0001-vpc-demo"
-
main.tf:
- Descripción: Archivo principal de Terraform.
- Propósito: Orquesta la creación de recursos.
- Funcionalidades: Incluye otros archivos, define proveedores y recursos.
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
data "aws_availability_zones" "available" {}
data "aws_subnets" "public" {}
data "aws_ami" "latest_linux" {
most_recent = true
filter {
name = "name"
values = ["*amzn2-ami-hvm-*"] # Filtra por AMIs de Amazon Linux 2
}
filter {
name = "architecture"
values = ["x86_64"] # Filtra por arquitectura x86_64 (64-bit)
}
filter {
name = "root-device-type"
values = ["ebs"] # Filtra por AMIs respaldadas por EBS (Elastic Block Store)
}
}
locals {
aws_account_id = data.aws_caller_identity.current.account_id
aws_region = data.aws_region.current.name
}
-
variables.tf:
- Descripción: Define variables Terraform.
- Propósito: Declara variables para la configuración.
- Funcionalidades: Parametriza la infraestructura.
variable "env" {
type = string
description = "Environment name."
}
variable "project" {
description = "Project Name or service"
type = string
}
variable "owner" {
description = "Owner Name or service"
type = string
}
variable "cost" {
description = "Center of cost"
type = string
}
variable "tf_version" {
description = "Terraform version that used for the project"
type = string
}
Screeshots:
Pruebas de conexión entre EC2's
Primero vemos que localmente cada ec2 tiene un servicio web que nos muestra su ip local:
Luego hacemos la consulta cruzada entre instancias y nos resuelve el curl:
🚀 En resumen, estos archivos de Terraform proporcionan la configuración necesaria para desplegar una infraestructura en la nube de AWS. Desde la definición de la red hasta la configuración de las instancias EC2 y el establecimiento de reglas de seguridad, cada archivo desempeña un papel crucial en la construcción y gestión de la infraestructura.
💡 Si tienes alguna pregunta o sugerencia para mejorar estos archivos, no dudes en ponerte en contacto. ¡Tu colaboración es bienvenida y valorada! Juntos, podemos construir y optimizar una infraestructura sólida y eficiente en la nube.
✉️ Si estás interesado en colaborar, por favor contáctame por este medio o en linkedin.
¡Gracias por tu interés y apoyo! 🙌
Extra:
Infracost (aprox de los recursos usados en esta demo):
Destruimos los recursos: