Hi all,
I’m trying to solve a subnet assignment problem in Terraform and want to double-check if there’s a way to meet all my requirements using only Terraform (no external scripts or manual mapping).
In short:
I want to solve the challenge of dynamic, stateful assignment of subnets to resources over time —specifically, to achieve both sticky assignment (so each resource keeps its subnet) and gap-filling (so freed subnets are reused for new resources).
Requirements:
- Each VM must get a unique subnet from a pool of available subnets (no two VMs share the same subnet).
- The assignment must be sticky: if I remove a VM, the other VMs must keep their assigned subnets (no shifting/reassignment).
- The assignment should be gap-filling/non-fragmenting: if a VM is removed, its subnet should become available for the next new VM (i.e., the assignment should fill gaps and not leave unused subnets indefinitely).
- No shifting: Removing one VM should not cause other VMs to be reassigned to different subnets.
- No external allocation: Preferably, this should be achieved using only Terraform (no external scripts, files, or manual mapping).
What I’ve tried:
The only way I’ve found to guarantee unique assignments is to use a sequential/index-based approach, like this:
locals {
subnets = ["subnet-1", "subnet-2", "subnet-3"]
vms = ["vm-1", "vm-2", "vm-3"]
# Assign subnets by index
vm_subnet_map = {
for idx, vm in local.vms :
vm => local.subnets[idx]
}
}
(This code is a simplified example of what I’m actually doing in my real setup.)
This works for uniqueness, but if I remove (for example) vm-2
, then vm-3
will be reassigned from subnet-3
to subnet-2
on the next apply. This is not acceptable for my use case, as I need the assignments to be sticky and not change for existing VMs.
I’ve also tried various approaches to make the assignments sticky, such as:
- Using hash/modulo logic (e.g., assigning subnets based on a hash of the VM name or resource key), but this can lead to collisions and isn’t gap-filling.
- Trying to use Terraform outputs or resource attributes to track assignments, but outputs are only available after apply and can’t be used to influence resource creation in the same plan/apply run.
- Attempting to filter or dynamically select the “first available” subnet, but Terraform’s declarative model and lack of state introspection make this impossible within a single run.
Am I overlooking something very simple or straightforward here?
If there’s not a way in pure Terraform only, what is the recommended best practice way of achieving this?
Thanks for any advice or patterns!