Hello Everyone,
I am hoping that someone more clever than me can help me, I am on a roadblock and can’t figure out how to progress from here.
However not that relevant to the issue I am facing with Terraform I will try to provide some context. I am trying to create a module that will set up networking in AWS specifically for EKS to address an IPV4 exhaustion issue we are facing because we don’t control the VPC creation and we get very small CIDR blocks.
I am trying to add a new CIDR block, create subnets, Private NGW and create Routing tables that contain a route to the Private NGW and then associate one-to-one relation of the subnet and routing tables without repeating combinations
I apologise in advance for the long post but is difficult to show what I am trying to achieve otherwise.
Code I am using and testing with LocalStack:
# Pass subnets cidrs and az via map
variable "eks_data_cidrs" {
description = "CIDR blocks for the EKS data plane subnets, e.g. nodes and pods"
type = map(any)
default = {
subdat-1 = {
az = "eu-west-2a"
cidr = "198.30.16.0/20"
}
subdat-2 = {
az = "eu-west-2b"
cidr = "198.30.32.0/20"
}
subdat-3 = {
az = "eu-west-2c"
cidr = "198.30.64.0/20"
}
}
}
# Create subnets
resource "aws_subnet" "eks_data" {
for_each = var.eks_data_cidrs
availability_zone = each.value["az"]
cidr_block = each.value["cidr"]
vpc_id = data.aws_vpc.vpc.id
tags = merge(
var.common_tags,
var.eks_data_subnet_tags,
{
Name = "${var.prefix}-${var.env}-eksdat-${each.value["az"]}"
Environment = var.env
}
)
}
# Creation of Routing tables with a route to one of the Private NGW
resource "aws_route_table" "eks_data_rttbl" {
count = length(values(aws_nat_gateway.private_ngws)[*].id)
vpc_id = data.aws_vpc.vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = values(aws_nat_gateway.private_ngws)[count.index].id
}
tags = merge(
var.common_tags,
{
Name = "${var.prefix}-${var.env}-eksdata-rttbl-${count.index}"
Component = "routing-table"
Environment = var.env
}
)
}
# Attemp to do the associations
# Neeed to generate the one-to-one list so let's say I have the following list of subnets and routing tables:
values(aws_subnet.eks_data)[*].id
[
"subnet-16b9f7f5",
"subnet-a83cc7fa",
"subnet-3886cdeb",
]
aws_route_table.eks_data_rttbl[*].id
[
"rtb-71353640",
"rtb-043e1770",
"rtb-fe69173c",
]
# used zipmap function to generate the list
locals {
eksdata_assc_map = zipmap(values(aws_subnet.eks_data)[*].id, aws_route_table.eks_data_rttbl[*].id)
}
#Which gives me this:
local.eksdata_assc_map
{
"subnet-16b9f7f5" = "rtb-71353640"
"subnet-3886cdeb" = "rtb-fe69173c"
"subnet-a83cc7fa" = "rtb-043e1770"
}
# I then tried to do the association
# for_each:
resource "aws_route_table_association" "eks_data_rttbl_association" {
for_each = local.eksdata_assc_map
subnet_id = each.key
route_table_id = each.value
}
# count:
#resource "aws_route_table_association" "eks_data_rttbl_association" {
# count = length(flatten(keys(local.eksdata_assc_map)))
# subnet_id = element(keys(local.eksdata_assc_map), count.index)
# route_table_id = element(values(local.eksdata_assc_map), count.index)
#
#}
So this works fine if the subnets and routing tables have been already created but if I am running this from scratch I get the following errors:
with for_each:
local.eksdata_assc_map will be known only after apply
│
│ The “for_each” map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource
with count:
The “count” value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the
I can’t figure out how to create a key based map, but even with that not sure I will be able to make it work.
I am really trying to avoid either running this in 2 stages or splitting the code into two modules and using something like Terragrunt to wrap the terraform execution and pass dependencies from one module to the other one more easily.