I’m doing tests with terraform and I didn’t found a solution on internet for this situation.
I have 4 environments (default, testing, prod, high). Each environment has AZ requirements… default has 1 AZ, testing 1 AZ, prod 2 AZ and high use all AZ in the region
and for each environment I have to create X instances per AZ. for default and testing 1 instance, for prod 2 instances, for high 3 instances.
I setup local vars:
data "aws_availability_zones" "available" {}
locals {
env="${terraform.workspace}"
#number of instances per AZ
counts = {
"default" = 1
"testing" = 1
"production" = 1
#high demand
"high" = 3
}
#number of subnets
subnet_public = {
"default" = 1
"testing" = 1
"production" = 2
#use all AZ disponible to create subnets
"high" = length(data.aws_availability_zones.available.names)
}
instance_count = lookup(local.counts,local.env)
instance_type = "t2.micro"
}
Now I’m trying create X instances per AZ
#create X instances per public subnet
for(i = 0; i < local.instance_count; i++) {
resource "aws_instance" "public_rproxy" {
for_each = aws_subnet.public
ami = data.aws_ami.amazon-linux-2.id
associate_public_ip_address = true
instance_type = local.instance_type
key_name = "wordpress-environment-key"
vpc_security_group_ids = [ aws_security_group.SG-FrontEnd ]
subnet_id = each.value.id
user_data = file("deploy_nginx_rproxy.sh")
tags = {
Name = "Public-Proxy-Server-${local.env}"
Environment = "${local.env}"
Application = "FrontEnd-NGINX-RProxy"
}
}
}
but terraform shows error in the for statement
49: for(i = 0; i < local.instance_count; i++) {
The ";" character is not valid. Use newlines to separate arguments and blocks,
and commas to separate items in collection values.
How I can create X instances in each AZ?
thanks
Terraform is not C/C++. You can’t write for-loops that way. Please consult the docs at
In your case you probably don’t even need a for-loop, you can just use count = local.instance_count
in the resource block.
I found the example using this for on the internet.
But if I use local.instance_count how to create X instances in Y AZ?
I need create a number of instances per AZ… and the number of AZ is based on the environment.
for example if I use count how to define the subnets? the local.instance_count is the number of instances inside one AZ, but if I use the example below I will create a number of instances but I can’t find a logic way to determine the AZ
resource "aws_instance" "public_rproxy" {
count = local.instance_count
ami = data.aws_ami.amazon-linux-2.id
associate_public_ip_address = true
instance_type = local.instance_type
key_name = "wordpress-environment-key"
vpc_security_group_ids = [ aws_security_group.SG-FrontEnd ]
subnet_id = ????
user_data = file("deploy_nginx_rproxy.sh")
tags = {
Name = "Public-Proxy-Server-${local.env}"
Environment = "${local.env}"
Application = "FrontEnd-NGINX-RProxy"
}
}
and to use for_each I will create only 1 instance per subnet
resource “aws_instance” “public_rproxy” {
for_each = aws_subnet.public
ami = data.aws_ami.amazon-linux-2.id
associate_public_ip_address = true
instance_type = local.instance_type
key_name = “wordpress-environment-key”
vpc_security_group_ids = [ aws_security_group.SG-FrontEnd ]
subnet_id = each.value.id
user_data = file(“deploy_nginx_rproxy.sh”)
tags = {
Name = "Public-Proxy-Server-${local.env}"
Environment = "${local.env}"
Application = "FrontEnd-NGINX-RProxy"
}
}
And the idea is create a number of instances for each AZ
Are you using subnet_id as a proxy for the AZ? Your resource declarations are specifying the AZ at all.
Yes, I forgot… I create one subnet per AZ and after I get the subnets:
data "aws_subnet_ids" "public_ids" {
vpc_id = aws_vpc.principal.id
tags = {
Type = "Public"
Environment = local.env
}
}
and in the resource instance
resource "aws_instance" "public_web_server" {
for_each = data.aws_subnet_ids.public_ids.ids
ami = data.aws_ami.amazon-linux-2.id
associate_public_ip_address = true
instance_type = local.instance_type
key_name = "wordpress-environment-key"
subnet_id = each.value
#vpc_security_group_ids = [ aws_security_group.SG-FrontEnd ]
#user_data = file("deploy_nginx_proxy.sh")
tags = {
Name = "Public-Proxy-Server-${local.env}"
Environment = "${local.env}"
Application = "Wordpress"
}
}
Of course, I don’t know if it’s a good way to deploy… I’m testing the options and trying mix options and possibilities to understand what is possible to do.
You are basically trying to do nested loops… I’m not familiar with how to do that, but hopefully someone else will be able to assist.
Thank you @kpfleming for your help. With your tip "nested loop"I found a solution.
I created a total_instance variable (multiplication of number of instances with subnets/AZ and the total of subnets/az)
total_instances = local.num_subnet_public * local.instance_count
I use count as total_instances and use the operator % to get the division remainder count.index by the total of subnets/AZ and works.
resource "aws_instance" "public_web_server" {
count = local.total_instances
ami = data.aws_ami.amazon-linux-2.id
associate_public_ip_address = true
instance_type = local.instance_type
key_name = "wordpress-environment-key"
subnet_id = aws_subnet.public[count.index % local.num_subnet_public].id
#vpc_security_group_ids = [ aws_security_group.SG-FrontEnd ]
#user_data = file("deploy_nginx_proxy.sh")
tags = {
Name = "Public-Proxy-Server-${local.env}"
Environment = "${local.env}"
Application = "Wordpress"
}
}
Now I will make some tests to confirm all workspaces will work with this solution.
Thank you 
1 Like