For the purpose of reducing points of failure, it is a common practice to distribute instances across two or more subnets assigned to different availability zones in an AWS VPC. It would be nice feature to be able to list a pool for subnets to be used by a single instance definition. When increasing or decreasing the count, the instances could automatically be spread across these subnets instead of having to define separate resources for each subnet.
I do that currently, using variable tricks:
"subnet_id": "${lookup(var.subnets, count.index % var.subnets_total)}",
The var.subnets is a mapping, from 0 to subnets_total - 1, with each numerically keyed entry holding one subnet (could repeat subnets to achieve uneven balancing, if you desired that).
Only thing that would be nicer, is a way to get the total elements from a var mapping.
Thanks to @mlrobinson for his solution. I think that's a neat way to do it.
@lmickh
We are using a somewhat different workaround with built in functions because we need to split subnets in the account mappings. This is what I do (works for me):
resource "aws_instance" "my-instances" {
subnet_id = "${element(split(",", lookup(var.instance_subnets, var.aws_account)), count.index)}"
# other params here
}
variable "instance_subnets" {
description = "Instance subnets"
default = {
dev = "subnet-xxxxxxxx,subnet-xxxxxxxx"
qa = "subnet-xxxxxxxx,subnet-xxxxxxxx"
prod = "subnet-xxxxxxxx,subnet-xxxxxxxx"
}
}
variable "aws_account" {
default = "dev"
}
# we pass aws_account as a variable into terraform
Hope that helps.
@mlrobinson 's solution does seem to work. Might be nice to have a built-in (or more intuitive) way to do it, but there is an option if the devs decide not to.
@lmickh Out of interest - is there any reason why you deliberately want to use standalone EC2 instances instead of autoscaling groups? ASGs solve this problem quite well.
There are some services that are fairly small and statically scaled. AWS ASGs could be used to solve the problem, but it is a bit overkill in my opinion.
If your working from a base that already makes good use of ASGs, it isn't as much work. When you already have a lifecycle process that works fine outside of a ASG, the amount of changes and additional resources to spin up the same instance inside an ASG instead is not insignificant.
I can see the case for saying use ASGs instead if this is outside of the intended workflow for Terraform. It is the way we are using it in some cases so I thought it might be a benefit to others as well.
Stumbled across this issue today and came up with a alternate workaround (in 0.8.6) for the case where your subnets are already in terrafrom.
subnet_id = "${element(list("${aws_subnet.sub-a.id}", "${aws_subnet.sub-c.id}"), count.index)}"
@nathanhruby That is clever and works quite well. It is preferable to creating variables like I had before. Thanks for the update!
Instead of needing to define input variables with lists of subnet-ids, it would be really nice to have a data source that supports a multiple subnet return. For example, 'aws_subnets' in addition to 'aws_subnet'. this issue is causing a lot of code bloat for me.
We are using the same technique as mlrobinson is.
mlrobinson's solution is clever. However, a data lookup is preferred. I'm in a situation with multiple VPCs over multiple accounts. maintaining variables with lists of subnet_ids for all my VPCs is manual busywork I'd rather avoid. Also, I like to be able to re-use my configurations across multiple clients; not having the lookup just limits reuse. Still hoping for 'aws_subnets'.
Hi everyone,
Thanks for opening and commenting on this feature request!
While we can see that this sort of thing could make configuration more succinct in certain configurations, it doesn't really fit well with Terraform's architecture and, as others have noted, there are some different ways to achieve the same result within Terraform's current model:
Use an auto-scaling group, possibly configured such that it doesn't actually take any automatic scaling actions to simulate a static set of instances.
Use a lookup table of subnet ids with count.index
to manually distribute instances.
We're trying to prune stale feature requests (that aren't likely to be addressed soon) by closing them. In this case Terraform already offers at least two ways to address this use-case, so I'm going to close this.
Not sure who could anyone solve this, terraform is searching for a single subnet_id, not more than that, you can't pass a list of subnets in here in any form. So what those workarounds are all about?
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
I do that currently, using variable tricks:
The var.subnets is a mapping, from 0 to subnets_total - 1, with each numerically keyed entry holding one subnet (could repeat subnets to achieve uneven balancing, if you desired that).
Only thing that would be nicer, is a way to get the total elements from a var mapping.