Terraform AWS VPC with Public and Private subnets with NAT

In this guide, we will explore provisioning an AWS VPC using Terraform. Terraform enables you to create and manage infrastructure with code and codes can be stored in version control. This concept is known as Infrastructure as code, i.e. provisioning infrastructure resources in as code.

We are going to create an AWS VPC, with public and private subnets in multiple availability zones. We are also going to create an internet gateway for the public subnets, a nat gateway for the private subnets and a default vpc security group. We will also create Custom Route Tables and associate them with subnets

We are going to create a VPC terraform module that will allow us to launch as many vpcs as we want. A terraform module is a container for multiple resources that are used together.

Prerequisites

To follow along this guide, you need the following:

  • AWS IAM credentials with permissions to manage VPCs – access key and secret key
  • AWS cli installed in your system. Install it here if you don’t have
  • Terraform installed in your machine, get terraform from (here)[https://www.terraform.io/downloads.html] if you don’t have it

This is the terraform version I am using:

➜ terraform --version
Terraform v1.0.7
on darwin_amd64

Export aws credentials in your terminal

export AWS_ACCESS_KEY_ID=your-key-id-here
export AWS_SECRET_ACCESS_KEY=youe-access-key-here
export AWS_DEFAULT_REGION=aws-region

Creating the module

For our resources, we will create a module to create them. This will enable us to re create the same resources as many times as we want.
The module will contain the following:

  • vars.tf – this is the variables supplied to our module. Variables are things that change each time we use the module. These are things like name that we supply, we want to have different name each time we create a vpc
  • main.tf – this is where the aws resources are definend.
  • outputs.tf – these are values that are exported and can be used to perform other action. e.g. for our vpc, we can export the vpc id.

This is my directory structure:

➜ tree
.
├── Makefile
├── main.tf
├── modules
│   └── vpc
│       ├── main.tf
│       ├── outputs.tf
│       └── vars.tf
2 directories, 8 files```

Code

Let us define some variables. Save this in the file vars.tf in our module directory modules/vpc

variable "region" {
  type    = string
  default = "eu-west-3"
}

variable "vpc_cidr" {
  type = string
}

variable "name" {
  type = string
}

variable "env" {
  type = string
}

variable "public_subnets_cidr" {
  type = list(string)
}

variable "availability_zones" {
  type = list(string)
}

variable "private_subnets_cidr" {
  type = list(string)
}

Next, let us define the resources that we want to create in the file main.tf in modules/vpc:

provider "aws" {
  region = var.region
}

resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr

  tags = {
    Name = var.name
    Env  = var.env
  }
}

# This will be used by the public subnets
resource "aws_internet_gateway" "ig" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${var.name}-igw"
    Env  = var.env
  }
}

# elastic ip for the nat gateway
resource "aws_eip" "nat_eip" {
  vpc        = true
  depends_on = [aws_internet_gateway.ig]
}

# Nat gateway for the private subnets
resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = element(aws_subnet.public.*.id, 0)
  depends_on    = [aws_internet_gateway.ig]
  tags = {
    Name = "${var.name}-nat"
    Env  = var.env
  }
}

# Public subnet
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.vpc.id
  count                   = length(var.public_subnets_cidr)
  cidr_block              = element(var.public_subnets_cidr, count.index)
  availability_zone       = element(var.availability_zones, count.index)
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.env}-${element(var.availability_zones, count.index)}-public"
    Env  = var.env
  }
}

# Private subnets
resource "aws_subnet" "private" {
  vpc_id                  = aws_vpc.vpc.id
  count                   = length(var.private_subnets_cidr)
  cidr_block              = element(var.private_subnets_cidr, count.index)
  availability_zone       = element(var.availability_zones, count.index)
  map_public_ip_on_launch = false

  tags = {
    Name = "${var.env}-${element(var.availability_zones, count.index)}-private"
    Env  = var.env
  }
}

# Private subnets route table
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name        = "${var.name}-private-route-table"
    Environment = var.env
  }
}

# Public subnets route table
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name        = "${var.name}-public-route-table"
    Environment = var.env
  }
}

# Add route for public route table to internet gateway
resource "aws_route" "public_internet_gateway" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.ig.id
}

# Add route for private route table to nat gateway
resource "aws_route" "private_nat_gateway" {
  route_table_id         = aws_route_table.private.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.nat.id
}

# Associate the public route table to public subnets
resource "aws_route_table_association" "public" {
  count          = length(var.public_subnets_cidr)
  subnet_id      = element(aws_subnet.public.*.id, count.index)
  route_table_id = aws_route_table.public.id
}

# Associate the public route table to public subnets
resource "aws_route_table_association" "private" {
  count          = length(var.private_subnets_cidr)
  subnet_id      = element(aws_subnet.private.*.id, count.index)
  route_table_id = aws_route_table.private.id
}

# Create a default security for the vpc
resource "aws_security_group" "default" {
  name        = "${var.name}-default-sg"
  description = "Default security group to allow inbound/outbound from the VPC"
  vpc_id      = aws_vpc.vpc.id
  depends_on  = [aws_vpc.vpc]

  ingress {
    from_port = "0"
    to_port   = "0"
    protocol  = "-1"
    self      = true
  }

  egress {
    from_port = "0"
    to_port   = "0"
    protocol  = "-1"
    self      = "true"
  }
  tags = {
    Env = var.env
  }
}

Then lets create a file outputs.tf to export the created resources values:

output "vpc_id" {
  value = aws_vpc.vpc.id
}

output "vpc_arn" {
  value = aws_vpc.vpc.arn
}

output "public_subnet_id" {
  value = join("", aws_subnet.public[*].id)
}

output "private_subnet_id" {
  value = join("", aws_subnet.private[*].id)
}

Using the module

Now that our module is done, can use it. Let’s create two VPCs – a uat and prod one.

In the current working directory, create a main.tf file with this content:

module "uat-vpc" {
  source = "./modules/vpc"

  region               = "eu-west-3"
  vpc_cidr             = "10.10.0.0/16"
  name                 = "uat-vpc"
  env                  = "uat"
  public_subnets_cidr  = ["10.10.0.0/24", "10.10.1.0/24", "10.10.2.0/24"]
  private_subnets_cidr = ["10.10.3.0/24", "10.10.4.0/24", "10.10.5.0/24"]
  availability_zones   = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
}

module "prod-vpc" {
  source = "./modules/vpc"

  region               = "eu-west-3"
  vpc_cidr             = "10.11.0.0/16"
  name                 = "prod-vpc"
  env                  = "prod"
  public_subnets_cidr  = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"]
  private_subnets_cidr = ["10.11.3.0/24", "10.11.4.0/24", "10.11.5.0/24"]
  availability_zones   = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
}

The above code uses the module we defined (source = "./modules/vpc") and passes the defined variables. Let us create the resources in AWS using this command.

Creating resources

To create resources, we first need to initialize. This will download any dependencies required by terraform:

terraform init

To check that everything is working as expected, use this command:

terraform validate

Then check what resources will be created:

terraform plan

If all is well, then apply the changes with:

terraform apply

I like to simplify the process with a makefile. I have a Makefile with this content that will chain the above terraform commands:

all: clean apply

init:
    terraform init
    terraform get

plan: validate
    terraform plan -out=tf.plan

apply: plan
    terraform apply tf.plan

clean:
    rm -f tf.plan
    rm -rf .terraform
    rm -rf *.tfstate*

validate: init
    terraform validate

destroy:
    terraform destroy

For the code above, this is my output:

➜ make apply
terraform init
Initializing modules...

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v3.59.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
terraform get
terraform validate
Success! The configuration is valid.

terraform plan -out=tf.plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # module.prod-vpc.aws_eip.nat_eip will be created
  + resource "aws_eip" "nat_eip" {
      + allocation_id        = (known after apply)
      + association_id       = (known after apply)
      + carrier_ip           = (known after apply)
      + customer_owned_ip    = (known after apply)
      + domain               = (known after apply)
      + id                   = (known after apply)
      + instance             = (known after apply)
      + network_border_group = (known after apply)
      + network_interface    = (known after apply)
      + private_dns          = (known after apply)
      + private_ip           = (known after apply)
      + public_dns           = (known after apply)
      + public_ip            = (known after apply)
      + public_ipv4_pool     = (known after apply)
      + tags_all             = (known after apply)
      + vpc                  = true
    }

  # module.prod-vpc.aws_internet_gateway.ig will be created
  + resource "aws_internet_gateway" "ig" {
      + arn      = (known after apply)
      + id       = (known after apply)
      + owner_id = (known after apply)
      + tags     = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc-igw"
        }
      + tags_all = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc-igw"
        }
      + vpc_id   = (known after apply)
    }

  # module.prod-vpc.aws_nat_gateway.nat will be created
  + resource "aws_nat_gateway" "nat" {
      + allocation_id        = (known after apply)
      + connectivity_type    = "public"
      + id                   = (known after apply)
      + network_interface_id = (known after apply)
      + private_ip           = (known after apply)
      + public_ip            = (known after apply)
      + subnet_id            = (known after apply)
      + tags                 = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc-nat"
        }
      + tags_all             = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc-nat"
        }
    }

  # module.prod-vpc.aws_route.private_nat_gateway will be created
  + resource "aws_route" "private_nat_gateway" {
      + destination_cidr_block = "0.0.0.0/0"
      + id                     = (known after apply)
      + instance_id            = (known after apply)
      + instance_owner_id      = (known after apply)
      + nat_gateway_id         = (known after apply)
      + network_interface_id   = (known after apply)
      + origin                 = (known after apply)
      + route_table_id         = (known after apply)
      + state                  = (known after apply)
    }

  # module.prod-vpc.aws_route.public_internet_gateway will be created
  + resource "aws_route" "public_internet_gateway" {
      + destination_cidr_block = "0.0.0.0/0"
      + gateway_id             = (known after apply)
      + id                     = (known after apply)
      + instance_id            = (known after apply)
      + instance_owner_id      = (known after apply)
      + network_interface_id   = (known after apply)
      + origin                 = (known after apply)
      + route_table_id         = (known after apply)
      + state                  = (known after apply)
    }

  # module.prod-vpc.aws_route_table.private will be created
  + resource "aws_route_table" "private" {
      + arn              = (known after apply)
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = (known after apply)
      + tags             = {
          + "Environment" = "prod"
          + "Name"        = "prod-vpc-private-route-table"
        }
      + tags_all         = {
          + "Environment" = "prod"
          + "Name"        = "prod-vpc-private-route-table"
        }
      + vpc_id           = (known after apply)
    }

  # module.prod-vpc.aws_route_table.public will be created
  + resource "aws_route_table" "public" {
      + arn              = (known after apply)
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = (known after apply)
      + tags             = {
          + "Environment" = "prod"
          + "Name"        = "prod-vpc-public-route-table"
        }
      + tags_all         = {
          + "Environment" = "prod"
          + "Name"        = "prod-vpc-public-route-table"
        }
      + vpc_id           = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.private[0] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.private[1] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.private[2] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.public[0] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.public[1] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_route_table_association.public[2] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.prod-vpc.aws_security_group.default will be created
  + resource "aws_security_group" "default" {
      + arn                    = (known after apply)
      + description            = "Default security group to allow inbound/outbound from the VPC"
      + egress                 = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = true
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = true
              + to_port          = 0
            },
        ]
      + name                   = "prod-vpc-default-sg"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Env" = "prod"
        }
      + tags_all               = {
          + "Env" = "prod"
        }
      + vpc_id                 = (known after apply)
    }

  # module.prod-vpc.aws_subnet.private[0] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-31"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.3.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-31-private"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-31-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_subnet.private[1] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3b"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.4.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3b-private"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3b-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_subnet.private[2] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3c"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.5.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3c-private"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3c-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_subnet.public[0] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-31"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.0.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-31-public"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-31-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_subnet.public[1] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3b"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.1.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3b-public"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3b-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_subnet.public[2] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3c"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.11.2.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3c-public"
        }
      + tags_all                        = {
          + "Env"  = "prod"
          + "Name" = "prod-eu-west-3c-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.prod-vpc.aws_vpc.vpc will be created
  + resource "aws_vpc" "vpc" {
      + arn                              = (known after apply)
      + assign_generated_ipv6_cidr_block = false
      + cidr_block                       = "10.11.0.0/16"
      + default_network_acl_id           = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_group_id        = (known after apply)
      + dhcp_options_id                  = (known after apply)
      + enable_classiclink               = (known after apply)
      + enable_classiclink_dns_support   = (known after apply)
      + enable_dns_hostnames             = (known after apply)
      + enable_dns_support               = true
      + id                               = (known after apply)
      + instance_tenancy                 = "default"
      + ipv6_association_id              = (known after apply)
      + ipv6_cidr_block                  = (known after apply)
      + main_route_table_id              = (known after apply)
      + owner_id                         = (known after apply)
      + tags                             = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc"
        }
      + tags_all                         = {
          + "Env"  = "prod"
          + "Name" = "prod-vpc"
        }
    }

  # module.uat-vpc.aws_eip.nat_eip will be created
  + resource "aws_eip" "nat_eip" {
      + allocation_id        = (known after apply)
      + association_id       = (known after apply)
      + carrier_ip           = (known after apply)
      + customer_owned_ip    = (known after apply)
      + domain               = (known after apply)
      + id                   = (known after apply)
      + instance             = (known after apply)
      + network_border_group = (known after apply)
      + network_interface    = (known after apply)
      + private_dns          = (known after apply)
      + private_ip           = (known after apply)
      + public_dns           = (known after apply)
      + public_ip            = (known after apply)
      + public_ipv4_pool     = (known after apply)
      + tags_all             = (known after apply)
      + vpc                  = true
    }

  # module.uat-vpc.aws_internet_gateway.ig will be created
  + resource "aws_internet_gateway" "ig" {
      + arn      = (known after apply)
      + id       = (known after apply)
      + owner_id = (known after apply)
      + tags     = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc-igw"
        }
      + tags_all = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc-igw"
        }
      + vpc_id   = (known after apply)
    }

  # module.uat-vpc.aws_nat_gateway.nat will be created
  + resource "aws_nat_gateway" "nat" {
      + allocation_id        = (known after apply)
      + connectivity_type    = "public"
      + id                   = (known after apply)
      + network_interface_id = (known after apply)
      + private_ip           = (known after apply)
      + public_ip            = (known after apply)
      + subnet_id            = (known after apply)
      + tags                 = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc-nat"
        }
      + tags_all             = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc-nat"
        }
    }

  # module.uat-vpc.aws_route.private_nat_gateway will be created
  + resource "aws_route" "private_nat_gateway" {
      + destination_cidr_block = "0.0.0.0/0"
      + id                     = (known after apply)
      + instance_id            = (known after apply)
      + instance_owner_id      = (known after apply)
      + nat_gateway_id         = (known after apply)
      + network_interface_id   = (known after apply)
      + origin                 = (known after apply)
      + route_table_id         = (known after apply)
      + state                  = (known after apply)
    }

  # module.uat-vpc.aws_route.public_internet_gateway will be created
  + resource "aws_route" "public_internet_gateway" {
      + destination_cidr_block = "0.0.0.0/0"
      + gateway_id             = (known after apply)
      + id                     = (known after apply)
      + instance_id            = (known after apply)
      + instance_owner_id      = (known after apply)
      + network_interface_id   = (known after apply)
      + origin                 = (known after apply)
      + route_table_id         = (known after apply)
      + state                  = (known after apply)
    }

  # module.uat-vpc.aws_route_table.private will be created
  + resource "aws_route_table" "private" {
      + arn              = (known after apply)
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = (known after apply)
      + tags             = {
          + "Environment" = "uat"
          + "Name"        = "uat-vpc-private-route-table"
        }
      + tags_all         = {
          + "Environment" = "uat"
          + "Name"        = "uat-vpc-private-route-table"
        }
      + vpc_id           = (known after apply)
    }

  # module.uat-vpc.aws_route_table.public will be created
  + resource "aws_route_table" "public" {
      + arn              = (known after apply)
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = (known after apply)
      + tags             = {
          + "Environment" = "uat"
          + "Name"        = "uat-vpc-public-route-table"
        }
      + tags_all         = {
          + "Environment" = "uat"
          + "Name"        = "uat-vpc-public-route-table"
        }
      + vpc_id           = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.private[0] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.private[1] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.private[2] will be created
  + resource "aws_route_table_association" "private" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.public[0] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.public[1] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_route_table_association.public[2] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.uat-vpc.aws_security_group.default will be created
  + resource "aws_security_group" "default" {
      + arn                    = (known after apply)
      + description            = "Default security group to allow inbound/outbound from the VPC"
      + egress                 = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = true
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = true
              + to_port          = 0
            },
        ]
      + name                   = "uat-vpc-default-sg"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Env" = "uat"
        }
      + tags_all               = {
          + "Env" = "uat"
        }
      + vpc_id                 = (known after apply)
    }

  # module.uat-vpc.aws_subnet.private[0] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-31"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.3.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-31-private"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-31-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_subnet.private[1] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3b"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.4.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3b-private"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3b-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_subnet.private[2] will be created
  + resource "aws_subnet" "private" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3c"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.5.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3c-private"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3c-private"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_subnet.public[0] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-31"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.0.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-31-public"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-31-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_subnet.public[1] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3b"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.1.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3b-public"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3b-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_subnet.public[2] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "eu-west-3c"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.10.2.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3c-public"
        }
      + tags_all                        = {
          + "Env"  = "uat"
          + "Name" = "uat-eu-west-3c-public"
        }
      + vpc_id                          = (known after apply)
    }

  # module.uat-vpc.aws_vpc.vpc will be created
  + resource "aws_vpc" "vpc" {
      + arn                              = (known after apply)
      + assign_generated_ipv6_cidr_block = false
      + cidr_block                       = "10.10.0.0/16"
      + default_network_acl_id           = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_group_id        = (known after apply)
      + dhcp_options_id                  = (known after apply)
      + enable_classiclink               = (known after apply)
      + enable_classiclink_dns_support   = (known after apply)
      + enable_dns_hostnames             = (known after apply)
      + enable_dns_support               = true
      + id                               = (known after apply)
      + instance_tenancy                 = "default"
      + ipv6_association_id              = (known after apply)
      + ipv6_cidr_block                  = (known after apply)
      + main_route_table_id              = (known after apply)
      + owner_id                         = (known after apply)
      + tags                             = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc"
        }
      + tags_all                         = {
          + "Env"  = "uat"
          + "Name" = "uat-vpc"
        }
    }

Plan: 42 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Saved the plan to: tf.plan

To perform exactly these actions, run the following command to apply:
    terraform apply "tf.plan"

Our VPCs are not set up and ready to use. Login to aws console to confirm.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy