Search code examples
amazon-web-servicesterraformterraform-provider-awsamazon-vpc

Terraform build ontop of the AWS VPC module


I'm using the AWS VPC module (terraform-aws-modules/vpc/aws) to create my VPC with public, private, and internal subnets. I want to define more subnets in my own module so that I can add per-environment subnets. The problem I'm having is with the routing tables. I want to create 3 routing tables per env and reuse the 3 NATs that the aws module creates for me (1 per AZ) for the private subnet routes.

How do I set the correct nat_gateway_ids in my aws_route resources ensuring that the NAT and subnets AZs match?

Structure:

global/network/vpc/main.tf

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = ******
  cidr = "10.0.0.0/16"

  azs             = var.azs # 3 AZs in the same region
  private_subnets = local.private_subnet_cidrs # 1 of each per az
  public_subnets  = local.public_subnet_cidrs
  intra_subnets   = local.intra_subnet_cidrs

  enable_ipv6            = false
  enable_nat_gateway     = true # One NAT per zone, not subnet.
  enable_vpn_gateway     = true
  one_nat_gateway_per_az = true

  tags = {
    Terraform = "true"
  }
}

modules/network/subnets/main.tf

Defines 3 subnets (public, private, internal) per AZ

modules/network/routing_tables/main.tf

Defines the routing tables for use with the 3 subnets above. Match subnets AZs to a NAT in the same AZ defined by the terraform-aws-modules/vpc/aws module.


Solution

  • There might be a way to achieve what you want, but it might not be as straight forward as you would want. For example, by having the NAT gateway IDs, you can use the aws_nat_gateway data source to fetch the subnets respective gateways are in:

    data "aws_nat_gateway" "default" {
      for_each = toset(module.vpc.natgw_ids)
      id       = each.value
    }
    

    Since this data source should also return the subnet ID, you could then pass the value to the data source that queries subnets:

    data "aws_subnet" "natgw_subnets" {
      for_each = data.aws_nat_gateway.default
      id       = each.value.subnet_id
    }
    

    Among other attributes, this data source exports the availability_zone attribute, which you can then output, e.g:

    output "nat_gateway_azs" {
      description = "AZs in which NAT gateways are hosted."
      value       = values(data.aws_subnet.natgw_subnets)[*].availability_zone
    }
    

    Not sure if this is the right answer, but I guess you can make something of it.