AWS VPC Subredes, Tablas de Rutas y Acceso a Internet usando Terraform (2/5)

Subredes VPC/RDS, Enrutado, y Acceso a Internet

Tutorial 2 de 5 acerca del uso de Terraform y Ansible para AWS. Tras finalizar el tutorial habrá creado mediante Terraform un VPC en AWS con una instancia EC2 conectadas a una base de datos MariaDB ejecutándose sobre RDS. Posteriormente se usa Ansible para configurar e instalar el software necesario.

Prerrequisitos:

Enrutamiento sub redes VPC

Al haber eliminado el VPC por defecto, se ha eliminado la tabla de rutas. AWS necesita una nueva tabla de rutas para conectar nuestro nuevo VPC a Internet.

AWS VPC Subredes, Tablas de Rutas y Acceso a Internet usando Terraform (2/5) 1
Dos zonas, con redes privadas y públicas en una región de AWS

Mejores Prácticas: Crear tablas de rutas independientes para redes privadas y públicas en AWS con Terraform

Se crear diferentes tablas de rutas para las redes privadas y las públicas con el fin de evitar exponer por error recursos privados desde zonas públicas, VPNs o redes privadas.
Se aplican buenas prácticas de nombrado de recursos, usando un patrón que indica el uso de cada recurso.

El nombre de los recursos seguirá un patrón:

  • Cloud: un prefijo que especifica un nombre único para este cloud y proveedor. En este caso se utiliza ditwl que se obtiene de las iniciales de Demo IT Wonder Lab en minúscula.
  • Recurso: un nombre corto que identifica el tipo de recurso, en este caso usamos:
    • rt: para tablas de rutas (routing table)
    • igw: para el gateway de Internet (Internet gateway)
    • ir: para una ruta de internet (Internet route)
  • Visibilidad: para aquellos recursos que pueden ser privados o públicos, se utiliza un acrónimo de 3 letras que indica su visibilidad:
    • pub: para recursos públicos
    • pri: par recursos privados
  • Nombre: opcionalmente se añade un nombre que describe el uso que se dará al recurso, por ejemplo para las tablas de rutas de las zonas privadas A y B se usará za y zb.

Dado que estamos aprovisionando una infraestructura de bajo coste, las subredes privadas no tendrán acceso a Internet. Dar acceso a Internet a una zona privada requiere la configuración de una Instancia NAT, además se recomienda que cada zona de disponibilidad tenga su propia instancia NAT y su propia tabla de rutas para las redes privadas, incrementando el coste.

Las subredes públicas obtienen acceso a Internet utilizando un Internet Gateway.

El enrutamiento se configura en el fichero terraform.tfvars.

#------------------------
# VPC ROUTING
#------------------------

aws_main_route_table_name = "ditwl-rt-pub-main"
aws_internet_gw_name = "ditwl-igw-pub-main"
aws_internet_route = {
  name = "ditwl-ir"
  destination_cidr_block = "0.0.0.0/0"
}
aws_private_route_table_za_name = "ditwl-rt-pri-za"
aws_private_route_table_zb_name = "ditwl-rt-pri-zb"

Acceso a Internet desde subredes públicas en AWS

El fichero aws_internet_gateway.tf crea una puerta de enlace (Gateway) para Internet usando un módulo de Terraform.

#----------------------
# AWS Internet Gateway
#----------------------

#Create an Internet GW
module "aws_internet_gw" {
  source = "./modules/aws/network/internet_gateway"
  vpc_id = module.aws_network_vpc.id
  name   = var.aws_internet_gw_name
}

Tablas de rutas para sub redes

Las tablas de rutas se crean en aws_vpc_routing.tf 

El módulo «aws_main_route_table_public» en la línea 18 crea una nueva tabla de rutas, esta nueva tabla de rutas se configura como tabla de rutas por defecto (o principal) mediante el recurso de Terraform «aws_main_route_table_association» de la línea 34.

La tabla principal contiene una entrada local para el enrutamiento dentro del VPC y una ruta para salir a Internet o defecto (0.0.0.0/0) cuyo destino es el Internet Gateway «module.aws_internet_gw.id creado anteriormente y asignado como ruta en la línea 25.

Todas las sub-redes del VPC a las que no se ha asignado una tabla de rutas específica, utilizan la tabla de rutas por defecto. En este ejemplo las subredes públicas no tendrán asignada una tabla de rutas específica.

Para las subredes privadas, se crean dos tablas de rutas en las líneas 49 y 56, posteriormente se asignan a las subredes correspondientes en las líneas 63 y 69.

#-----------------------------------------
# MAIN Route Table (Default for all SUBNETS)
# Used for public zones / subnets
# It is the default route table if no other
# is specified
#-----------------------------------------

module "aws_main_route_table_public" {
  source = "./modules/aws/network/route/table"
  vpc_id = module.aws_network_vpc.id
  name   = var.aws_main_route_table_name
}

#Add an Internet GW to the VPC routing main table
module "aws_internet_route" {
  source                 = "./modules/aws/network/route/add"
  route_table_id         = module.aws_main_route_table_public.id
  gateway_id             = module.aws_internet_gw.id
  destination_cidr_block = var.aws_internet_route["destination_cidr_block"]
  name                   = var.aws_internet_route["name"]
}

# Set new main_route_table as main
resource "aws_main_route_table_association" "default" {
  vpc_id         = module.aws_network_vpc.id
  route_table_id = module.aws_main_route_table_public.id
}

#-----------------------------------------
# Private Route Table
# Used for private zone / subnet that have
# instances without a public IP address
# Each subnet should have its own route table
# as the NAT gateway lives in an availability
# zone
#-----------------------------------------

# For private networks in zone A
module "aws_private_route_table_za" {
  source = "./modules/aws/network/route/table"
  vpc_id = module.aws_network_vpc.id
  name   = var.aws_private_route_table_za_name
}

#For private networks in zone B
module "aws_private_route_table_zb" {
  source = "./modules/aws/network/route/table"
  vpc_id = module.aws_network_vpc.id
  name   = var.aws_private_route_table_zb_name
}

# Associate private networks in zone A to private route table
resource "aws_route_table_association" "route_sn_za_pro_pri_34" {
  subnet_id      = module.aws_sn_za_pro_pri_34.id
  route_table_id = module.aws_private_route_table_za.id
}

# Associate private networks in zone B to private route table
resource "aws_route_table_association" "aws_sn_zb_pro_pri_38" {
  subnet_id      = module.aws_sn_zb_pro_pri_38.id
  route_table_id = module.aws_private_route_table_zb.id
}

Grupo de subredes para RDS

Otro tipo de subred utilizada en AWS es la utilizada para RDS. En este ejemplo, usaremos una base de datos como servicio MariaDB sobre RDS.

Para configurar la base de datos, se debe crear un Grupo de subred de RDS, el grupo es una agregación de sub redes del VPC. Los mismo principios de distribución de recursos, alta disponibilidad y aislamiento de recursos aplican. Vea RDS Subnet Group para una descripción.

Mejores prácticas: Multiples Zonas de disponibilidad para RDS

Cree un grupo de subredes RDS compuesto por subredes de diferentes zonas de disponibilidad. Una base de datos utilizando AWS RDS podrá ejecutarse en cualquiera de las sub redes disponibles en el Grupo de subredes RDS permitiendo la recuperación de desastres o la actualización del software de la base de datos mediante configuraciones AZ.

Siguiendo las mejores prácticas de IT Wonder Lab, El grupo de subredes de RDS se creará usando subredes de dos zonas de disponibilidad y seguirán el siguiente patrón de nombrado:

  • Nombre del Cloud: un prefijo que identifica unívocamente a este cloud y proveedor. En este caso, el prefijo será : ditwl que se ha extraído de Demo IT Wonder Lab en minúsculas.
  • Recurso: un nombre corto identificando el tipo de recurso, en este caso:
    • rds-sn: por RDS subnet
  • Entorno: para recursos que no están compartidos en varios entornos, se utiliza un acrónimo del entorno:
    • pro: producción
    • pre: preproducción
    • dev: desarrollo
  • Visibilidad: para recursos que pueden ser públicos o privados, se utilizan 3 letras para indicar su visibilidad:
    • pub: para recursos públicos
    • pri: par recursos privados
  • Nombre/ID: nombre o identificador que describe el uso del recurso o el número de instancia del mismo, por ejemplo para para esta subred RDS se usará 01. Más adelante podríamos tener más subredes RDS numeradas 02, 03…

En este ejemplo estamos añadiendo subredes ubicadas en dos zonas de disponibilidad al grupo de subredes RDS, esto puede tener un impacto en el coste de AWS ya que las instancias RDS se podrían ejecutar en una zona de disponibilidad diferente a la de las instancias EC2 que las usan, creando costes de transferencia de datos.

Vea aws_rds_sn_pro.tf para una solución mono zona.

An RDS Subnet Group with two availability zones
AWS RDS Subnet Group

El grupo de subredes ditwl-rdssn-pro-pub-01 de RDS se muestra con fondo amarillo, la base de datos RDS podrá ser lanzada por AWS en cualquier de las dos subredes.

Atención: Base de datos AWS RDS Database accessible desde Internet

Estamos creando un grupo de redes RDS que utiliza subredes públicas ya que queremos acceder a la base de datos desde Internet.

Esto es peligroso, en un entorno real, las subredes RDS deben ser privadas y el acceso a las bases de datos se realizará por VPN o desde una máquina de la zona privada.

terraform.tfvars define el nombre y descripción del grupo de subredes de RDS. Desafortunadamente, el fichero tfvars de Terraform no permite interpolaciones como valores (referencias a otras variables, módulos o funciones), por lo que los IDs de las subredes serán especificados en aws_rds_sn_pro.tf, el fichero que crea el grupo de sub redes de RDS

    #------------------------
    # For RDS instances
    #------------------------
    aws_rds_sn_pub_pro_01 = {
      name        = "ditwl-rds-sn-pub-pro-01"
      description = "ditwl-RDS-SN-pub-PRO-01"

      #See aws_rds_sn_pro.tf for subnet_ids
      #subnet_ids  = ${module.aws_sn_za_pro_pub_32.id},${module.aws_sn_zb_pro_pub_36.id
    }

aws_rds_sn_pub_pro_01.tf utiliza un módulo para crear el grupo de subredes para RDS, y asignarle las subredes aws_sn_za_pro_pub_32 y aws_sn_zb_pro_pub_36 creadas por otro módulo y referenciadas por su ID exportado.

Puede comentar la línea 19 y descomentar la 21 para usar una sola zona de disponibilidad.

#----------------------
# SUBNET for RDS
#----------------------

  #----------------------
  # PRO
  #----------------------
  module "aws_rds_sn_pub_pro_01" {
    source      = "./modules/aws/rds/subnet"
    name        = var.aws_rds_sn_pub_pro_01["name"]
    description = var.aws_rds_sn_pub_pro_01["description"]

    # Add 2 PRIVATE Subnets from two availability zones
    subnet_ids  = [module.aws_sn_za_pro_pub_32.id, module.aws_sn_zb_pro_pub_36.id]
    # Add 1 PRIVATE Subnets from two availability zones
    #subnet_ids  = [module.aws_sn_za_pro_pub_32.id]
  }

Continúe la demo de Terraform y Ansible para AWS:

AWS VPC Subredes, Tablas de Rutas y Acceso a Internet usando Terraform (2/5)

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

ansible-aws-ec2-terraform-tags - ansible-aws-ec2-terraform-tags-ec2.png
Tutoriales de Amazon Web Services (AWS)

Integración de Ansible y Terraform

Integración de Ansible y Terraform para configuración de infraestructura en AWS mediante tags e inventario dinámico.