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}"
}
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}"
}