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.
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.