2

I have code to create VPC, with 2 private subnets, 2xec2 instances in private and bastion in public.

ec2 code uses outputs.tf of VPC module subnet_ids. as there are 2 private subnets there are 2 subnet_ids being generated. when these generated subnet_ids are fed into ec2 instances instead of one subnet_id, it is feeding 2 subnet_ids at once as a single value.

As a result terraform couldn't find that subnet_ids value, creation is being failed.

error: The subnet ID 'subnet-0***********,subnet-0*************' does not exist

editing subnets* vpc.tf

private_subnets     = "10.10.20.#/#,10.10.20.#/#"

instanceec2.tf

subnet_id           = "${module.vpc.private_subnets}"

below are modules:

vpc_main.tf

// Private subnet/s
resource "aws_subnet" "private" {
  vpc_id            = "${aws_vpc.vpc.id}"
  cidr_block        = "${element(split(",", var.private_subnets), count.index)}"
  availability_zone = "${element(split(",", var.azs), count.index)}"
  count             = "${length(split(",", var.private_subnets))}"

  tags {
    Name        = "${var.name}-private-${element(split(",", var.azs), count.index)}"
    Team        = "${var.team}"
    Environment = "${var.environment}"
    Service     = "${var.service}"
    Product     = "${var.product}"
    Owner       = "${var.owner}"
    Description = "${var.description}"
    managed_by  = "terraform"
  }
}

resource "aws_route_table" "private" {
  vpc_id = "${aws_vpc.vpc.id}"
  count  = "${length(split(",", var.private_subnets))}"

  tags {
    Name        = "${var.name}-private-${element(split(",", var.azs), count.index)}"
    Team        = "${var.team}"
    Environment = "${var.environment}"
    Service     = "${var.service}"
    Product     = "${var.product}"
    Owner       = "${var.owner}"
    Description = "${var.description}"
    managed_by  = "terraform"
  }
}

resource "aws_route_table_association" "private" {
  subnet_id      = "${element(aws_subnet.private.*.id, count.index)}"
  route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
  count          = "${length(split(",", var.private_subnets))}"
}
``````


vpc_outputs.tf

```````

output "private_subnets" {
  value = "${join(",", aws_subnet.private.*.id)}"
}

Expected value is only one subnet ID as value:

Error: supply 2 Subnet IDs as one value.

aws_instance.ec2-instance[0]: 1 error(s) occurred:

  • aws_instance.ec2-instance.0: Error launching source instance: InvalidSubnetID.NotFound: The subnet ID 'subnet-0**********,subnet-0***********' does not exist
user11411591
  • 77
  • 2
  • 3
  • 9

2 Answers2

1

Since you have 'join'ed the result, you would have to split again if you require just one subnet value. Something like:

element(split(",", var.private_subnets), 0) 
John Kentucky
  • 876
  • 6
  • 10
  • I want to give multiple subnets but as a single value. I have 2 subnets to be given where ec2 instance must be present. It should also be dynamic without specifying 0, 1 etc.. – user11411591 May 09 '19 at 21:00
  • Each ec2 instance can only reside in one subnet. It cannot span across multiple subnets. – John Kentucky May 10 '19 at 12:23
  • makes sense, so how would there be a sync between instances that are sitting in different AZs? Does both AZ have same VPC_ids,subnet_ids and instance_id and same instances. Does 2AZs mean just clones? with all the properties the same?? Your answer would be very much appreciated. – user11411591 May 10 '19 at 18:04
  • What do you mean by sync between the instances? – John Kentucky May 16 '19 at 04:51
1

you are joining the subnet IDs in your output variable:

output "private_subnets" {
  value = "${join(",", aws_subnet.private.*.id)}"
}

When you access this output value from your instanceec2.tf you will only receive this joined string of IDs. So, you again have to slipt the received value as you've done before and access the respective individual ID with your count index of the ec2 resource:

resource "aws_instance" "default" {
    count     = "${length(split(",", module.vpc.private_subnets))}"
    subnet_id = "${element(split(",", module.vpc.private_subnets), count.index)}"
    ....
}    

That should solve you're issue.

Alternatively, you can also output the subnet IDs directly as a list:

output "private_subnets" {
  description = "The IDs of the private subnets as list"
  value       = ["${aws_subnet.private.*.id}"]
}

and then access them with:

subnet_id = "${element(module.vpc.private_subnets, count.index)}"
rflume
  • 848
  • 5
  • 10
  • count.index isn't working because the outputs.tf is of VPC module and I'm using that output in different module ec2.tf. – user11411591 May 09 '19 at 21:02
  • Sure, but I thought you'd use `count = ...` also within your EC2 instance resource definition. You can also specify a count for the instances larger than the length of the ID array. with a count of 3 for example, Terraform would assign subnet 0 to instance 0, subnet 1 to instance 1 and subnet 0 again to instance 3 and so on. – rflume May 09 '19 at 22:35
  • "Join" and "Split" are working for me, the 'list' and 'element' way is not. Thanks a lot! – zqcolor Aug 13 '20 at 07:25