13

I'm using terraform v.0.11.7.

I wants to create 4 subnets (2 public subnets, 2 private subnets)

Here's a content of vars.tf

variable "region" { default = "ap-south-1" } variable "ami_id" { type = "map" default = "ami-d783a9b8" } variable "credentials" { default = "/root/.aws/credentials" } variable "vpc_cidr" { default = "10.0.0.0/16" } variable "pub_subnet_aza_cidr" { default = "10.0.10.0/24" } variable "pub_subnet_azc_cidr" { default = "10.0.20.0/24" } variable "pri_subnet_aza_cidr" { default = "10.0.30.0/24" } variable "pri_subnet_azc_cidr" { default = "10.0.40.0/24" } 

Now inside main.tf, i want to associate the first 2 public subnets to public route table, how to do that?

resource "aws_subnet" "pub_subnet_aza" { vpc_cidr = "{aws_vpc.vpc.id}" cidr_block = "${var.pub_subnet_aza_cidr}" tags { Name = "Pub-Sunet-A" } availability_zone = "${data.aws_availability_zone.available.name[0]}" } resource "aws_subnet" "pub_subnet_azc" { vpc_cidr = "{aws_vpc.vpc.id}" cidr_block = "${var.pub_subnet_azc_cidr}" tags { Name = "Pub-Subnet-C" } availability_zone = "${data.aws_availability_zone.available.name[2]}" } resource "aws_route_table_association" "public" { subnet_id = "${aws_subnet.pub_subnet_aza.id}" # How to put pub_subnet_azc.id into here? route_table_id = "${aws_route_table.public.id}" } 
3
  • 1
    Better use lists of subnets to reduce the amount of variables (we started at work in the same way and it's a mess..). Then you can also use count = length(var.subnets) to get 2 instances of the route table association resource and pick the correct one from the subnets list. Commented Aug 8, 2018 at 6:28
  • @StephenKing You should add this as an answer and provide a worked example. Commented Aug 8, 2018 at 7:46
  • Not from mobile ;-) Commented Aug 8, 2018 at 8:02

1 Answer 1

27

Better use lists of subnets to reduce the amount of variables. Then you can also use count = length(var.subnets) to get 2 instances of the route table association resource and pick the correct one from the subnets list.

variable "subnet_cidrs_public" { description = "Subnet CIDRs for public subnets (length must match configured availability_zones)" # this could be further simplified / computed using cidrsubnet() etc. # https://www.terraform.io/docs/configuration/interpolation.html#cidrsubnet-iprange-newbits-netnum- default = ["10.0.10.0/24", "10.0.20.0/24"] type = "list" } resource "aws_subnet" "public" { count = "${length(var.subnet_cidrs_public)}" vpc_id = "${aws_vpc.main.id}" cidr_block = "${var.subnet_cidrs_public[count.index]}" availability_zone = "${var.availability_zones[count.index]}" } resource "aws_route_table_association" "public" { count = "${length(var.subnet_cidrs_public)}" subnet_id = "${element(aws_subnet.public.*.id, count.index)}" route_table_id = "${aws_route_table.public.id}" } 

I see you've been reading availability zones via data, which is fine and you can still do. You just have to somehow set the association between a subnet and the AZ. I leave that up to you.

Certainly more elegant would be to provision a subnet in every AZ of that region. Once we use cidrsubnet() to compute address spaces for the subnets, we could use length(data.availability_zones) as the driver for all the rest. Shouldn't be too complex.

Here is the full code:

provider "aws" { region = "eu-west-1" } variable "availability_zones" { description = "AZs in this region to use" default = ["eu-west-1a", "eu-west-1c"] type = "list" } variable "vpc_cidr" { default = "10.0.0.0/16" } variable "subnet_cidrs_public" { description = "Subnet CIDRs for public subnets (length must match configured availability_zones)" # this could be further simplified / computed using cidrsubnet() etc. # https://www.terraform.io/docs/configuration/interpolation.html#cidrsubnet-iprange-newbits-netnum- default = ["10.0.10.0/24", "10.0.20.0/24"] type = "list" } resource "aws_vpc" "main" { cidr_block = "${var.vpc_cidr}" tags { Name = "stackoverflow-51739482" } } resource "aws_subnet" "public" { count = "${length(var.subnet_cidrs_public)}" vpc_id = "${aws_vpc.main.id}" cidr_block = "${var.subnet_cidrs_public[count.index]}" availability_zone = "${var.availability_zones[count.index]}" } resource "aws_route_table" "public" { vpc_id = "${aws_vpc.main.id}" tags { Name = "public" } } resource "aws_route_table_association" "public" { count = "${length(var.subnet_cidrs_public)}" subnet_id = "${element(aws_subnet.public.*.id, count.index)}" route_table_id = "${aws_route_table.public.id}" } 
Sign up to request clarification or add additional context in comments.

1 Comment

Cool. Thanks bro.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.