
The module creates AWS VPC with flexible number of subnets and configures routing for them. It is meant to handle various network combinations based on the common presets following best practices of AWS networking:
simple
- creates a single public subnet in the VPC. With High Availability option, this produces one public subnet per availability zonecanonical
- follows a typical scheme for secure AWS VPC: one private, one public subnet per AZ, with NAT GW for egress traffic from the private subnet. With HA, creates a canonical multi-AZ AWS VPCadvanced
- allows to create a fully custom network configurationSupports converting a single-zone setup to multi-zonal one by toggling High Availability (ha_enabled
variable). Subnet definitions in presets preserve existing networks and only append new CIDRs.
Once you have a Corewide Solutions Portal account, this one-time action will use your browser session to retrieve credentials:
shellterraform login solutions.corewide.com
Initialize mandatory providers:
Copy and paste into your Terraform configuration and insert the variables:
hclmodule "tf_aws_vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1.0"
# specify module inputs here or try one of the examples below
...
}
Initialize the setup:
shellterraform init
Corewide DevOps team strictly follows Semantic Versioning
Specification
to
provide our clients with products that have predictable upgrades between versions. We
recommend
pinning
patch versions of our modules using pessimistic
constraint operator (~>
) to prevent breaking changes during upgrades.
To get new features during the upgrades (without breaking compatibility), use
~> 5.1
and run
terraform init -upgrade
For the safest setup, use strict pinning with version = "5.1.0"
The module creates AWS VPC with flexible number of subnets and configures routing for them. It is meant to handle various network combinations based on the common presets following best practices of AWS networking:
simple
- creates a single public subnet in the VPC. With High Availability option, this produces one public subnet per availability zonecanonical
- follows a typical scheme for secure AWS VPC: one private, one public subnet per AZ, with NAT GW for egress traffic from the private subnet. With HA, creates a canonical multi-AZ AWS VPCadvanced
- allows to create a fully custom network configurationSupports converting a single-zone setup to multi-zonal one by toggling High Availability (ha_enabled
variable). Subnet definitions in presets preserve existing networks and only append new CIDRs.
All notable changes to this project are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
canonical-lite
networking setup, that limits the number of AZ covered, with a network scheme similar to canonical
preset.BREAKING CHANGE: resources naming style was changed to follow Terraform naming conventions, which is incompatible with previous versions. Upgrade from an older version is possible with manual changes, see Upgrade Notes section
moved {}
blocks for the following resources: aws_vpc
, aws_internet_gateway
, aws_route
aws_vpc
, aws_internet_gateway
, aws_route
, aws_eip
, aws_nat_gateway
, aws_route_table
, aws_route_table_association
simple
, canonical
and advanced
. advanced
preset is set as default for compatibility with previous versions. Presets encapsulate configuration for popular network configuration scenarios and automatically calculate CIDRs for subnetsha_enabled
variable to toggle multi-zone feature for a particular preset (ignored for advanced
one)nat_enabled
variable to toggle NAT configuration for canonical
preset (ignored for others)subnets
variable is now optional and is only used with advanced
presetenable_dns_hostnames
variable (deprecation notice expired)BREAKING CHANGE: naming style for resources managed with for_each
was changed. The new subnet management scheme is incompatible with previous versions. Upgrade from an older version is possible with manual changes, see Upgrade Notes section
nat_via
argument for the subnets
variablefor_each
subnets
variable type from list(object)
to map(object)
5.*
and newer(Last version compatible with Terraform AWS v4)
dns_hostnames_enabled
variable that will replace enable_dns_hostnames
after two minor releasesenable_dns_hostnames
variable in favor of dns_hostnames_enabled
BREAKING CHANGE: now all resources managed with for_each
have corresponding names in the state instead of abstract indexed names; new naming scheme is incompatible with previous versions. Upgrade from an older version is possible with manual changes, see Upgrade Notes section
for_each
- aws_subnet
, aws_eip
, aws_nat_gateway
, aws_route_table
, aws_route_table_association
name_prefix
input to allow only alphanumeric characters, dashes, underscores and dots (only between the alphanumeric characters)BREAKING CHANGE: now module inputs and resources management have fundamentally new concept. Upgrade from an older version is possible with manual changes, see Upgrade Notes section
4.*
(Last version compatible with Terraform AWS v3)
enable_auto_assigning_ips
variable (false
by default)enable_dns_hostnames
variable (true
by default)enable_private_network
variable (true
by default)First stable version
The module from v2.0
has changed inputs principles and handling of multiple resource copies from count
meta-argument to for_each
which aren't compatible with an old version. First, update declaration of module according to the requirements and examples in order to match designed VPC configuration, then re-init module and update naming in Terraform state of managed indexed resources.
v1.x
to v2.x
For example, the NAT gateway resource represented in the TF state file as:
module.vpc.aws_nat_gateway.nat_gw[0]
will become:
module.vpc.aws_nat_gateway.nat_gw["0"]
It's necessary to change state file accordingly:
bashterraform state mv module.vpc.aws_nat_gateway.nat_gw[0] module.vpc.aws_nat_gateway.nat_gw[\"0\"]
v1.x
or v2.x
to v3.x
The module v3.0
has changed keys naming design of resources managed with for_each
which aren't compatible with an old version. First, re-init the module, then update naming in Terraform state of managed indexed resources.
As an example, the name_prefix
variable is set to foo
and the NAT gateway resource represented in the TF state file as follows:
module.vpc.aws_nat_gateway.nat_gw[0]
- in v1.x
or
module.vpc.aws_subnet.public["0"]
- in v2.x
the variable value will be added to the resource name in v3.x
:
module.vpc.aws_nat_gateway.nat_gw["foo"]
The state file must be changed accordingly.
If the initial module version is v1.x
:
bashterraform state mv module.vpc.aws_nat_gateway.nat_gw[0] module.vpc.aws_nat_gateway.nat_gw[\"foo\"]
If the initial module version is v2.x
:
bashterraform state mv module.vpc.aws_nat_gateway.nat_gw[\"0\"] module.vpc.aws_nat_gateway.nat_gw[\"foo\"]
v3.x
to v4.x
The module v4.0
has changed the key naming design of resources managed with for_each
. The private/public subnet management way changed as well. It makes the new module version incompatible with the previous one. First, re-init the module and change the subnet definition arguments according to the documentation and examples.
For example, the name_prefix
variable is set to foo
, subnets["name"]
is bar
and the NAT gateway resource represented in the TF state file as follows:
module.vpc.aws_nat_gateway.nat_gw["foo"]
the subnet name value will be added to the resource name:
module.vpc.aws_nat_gateway.nat_gw[\"foo-bar\"]
The state file should then be modified accordingly::
bashterraform state mv module.vpc.aws_nat_gateway.nat_gw[\"foo\"] module.vpc.aws_nat_gateway.nat_gw[\"foo-bar\"]
v4.x
to v5.x
The module v5.0
has changed the key naming pattern of the following resources: aws_vpc
, aws_internet_gateway
, aws_route
, aws_eip
, aws_nat_gateway
, aws_route_table
, aws_route_table_association
.
aws_vpc
, aws_internet_gateway
, aws_route
resources are moved automatically with moved {}
block, but other ones should be migrated manually.
For example, the name_prefix
variable is set to foo
, subnets["name"]
is bar
and the resources represented in the TF state file as follows:
module.vpc.aws_eip.elastic_ip[\"foo-bar\"]
module.vpc.aws_nat_gateway.nat_gw[\"foo-bar\"]
module.vpc.aws_route_table.private[\"foo-bar\"]
module.vpc.aws_route_table_association.private[\"foo-bar\"]
they will be changed to:
module.vpc.aws_eip.nat_gw[\"foo-bar\"]
module.vpc.aws_nat_gateway.main[\"foo-bar\"]
module.vpc.aws_route_table.private_subnet_to_nat_gw[\"foo-bar\"]
module.vpc.aws_route_table_association.private_subnet_to_nat_gw[\"foo-bar\"]
The state file then should be modified accordingly:
bashterraform state mv module.vpc.aws_eip.elastic_ip[\"foo-bar\"] module.vpc.aws_eip.nat_gw[\"foo-bar\"]
terraform state mv module.vpc.aws_nat_gateway.nat_gw[\"foo-bar\"] module.vpc.aws_nat_gateway.main[\"foo-bar\"]
terraform state mv module.vpc.aws_route_table.private[\"foo-bar\"] module.vpc.aws_route_table.private_to_nat_gw[\"foo-bar\"]
terraform state mv module.vpc.aws_route_table_association.private[\"foo-bar\"] module.vpc.aws_route_table_association.private_to_nat_gw[\"foo-bar\"]
Single-zone VPC setup with custom subnet CIDRs in a custom AZ:
hclmodule "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "foo"
cidr_block = "20.20.0.0/16"
preset = "advanced"
subnets = {
private-1 = {
availability_zone = "us-east-1b"
private_subnet_cidr_block = "20.20.6.0/24"
# allow outgoing access to the Internet with NAT gateway
nat_via = "public-1"
tags = {
"foo" = "bar"
}
}
public-1 = {
availability_zone = "us-east-1b"
public_subnet_cidr_block = "20.20.5.0/24"
}
}
tags = {
Project = "bar"
}
}
Non-canonical VPC setup with a single public subnet and an isolated private subnet (no NAT GW gets created - suitable for a web server and database instance):
hclmodule "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "foo"
cidr_block = "20.20.0.0/16"
preset = "advanced"
subnets = {
private-1 = {
availability_zone = "us-east-1b"
private_subnet_cidr_block = "20.20.6.0/24"
}
public-1 = {
availability_zone = "us-east-1b"
public_subnet_cidr_block = "20.20.5.0/24"
}
}
tags = {
Project = "bar"
}
}
VPC with a single-zone public subnet; in this example, a public subnet public-1
(20.20.0.0/24
) will be created in us-east-1a
zone (first available one in the region).
hclprovider "aws" {
region = "us-east-1"
}
module "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "foo"
cidr_block = "20.20.0.0/16"
preset = "simple"
tags = {
Project = "bar"
}
}
A highly available version of this example produces a VPC with three public subnets (20.20.0.0/24
, 20.20.1.0/24
and 20.20.2.0/24
), one per AZ in the region (us-east-1a
, us-east-1b
, us-east-1c
):
hclprovider "aws" {
region = "us-east-1"
}
module "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "web"
cidr_block = "20.20.0.0/16"
preset = "simple"
ha_enabled = true
tags = {
Purpose = "website"
}
}
VPC with a single-zone public and private subnets, with a NAT GW for outgoing connections from the private network. This example implicitly defines a public subnet public-1
(20.20.0.0/24
) and private subnet (20.20.1.0/24
) in the first AZ of the region (us-east-1a
) along with NAT GW with a dedicated IP:
hclprovider "aws" {
region = "us-east-1"
}
module "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "foo"
cidr_block = "20.20.0.0/16"
preset = "canonical"
tags = {
Project = "bar"
}
}
With ha_enabled = true
, the number of subnets is multiplied by the number of AZ (public CIDRs are 20.20.0.0/24
, 20.20.2.0/24
, 20.20.4.0/24
, private ones get 20.20.1.0/24
, 20.20.3.0/24
, 20.20.5.0/24
).
The same example, but simplified, can be used to create a generic networking setup with a single public subnet and a single fully isolated private subnet commonly used for website hosting:
hclprovider "aws" {
region = "us-east-1"
}
module "vpc" {
source = "solutions.corewide.com/aws/tf-aws-vpc/aws"
version = "~> 5.1"
name_prefix = "foo-ha"
cidr_block = "20.20.0.0/16"
preset = "canonical"
ha_enabled = true
tags = {
Project = "bar"
}
}
Variable | Description | Type | Default | Required | Sensitive |
---|---|---|---|---|---|
cidr_block |
The CIDR block for the VPC | string |
yes | no | |
name_prefix |
Naming prefix for all the resources created by the module | string |
yes | no | |
subnets[<key>] |
Subnet name | string |
yes | no | |
tags |
Tags that must be assigned to resources | map(string) |
yes | no | |
dns_hostnames_enabled |
Enable/disable DNS hostnames for VPC | bool |
true |
no | no |
ha_enabled |
Whether networking must be highly available (multi-zonal) | bool |
false |
no | no |
nat_enabled |
Whether NAT resources must be created | bool |
true |
no | no |
preset |
Preconfigured networking setup | string |
advanced |
no | no |
private_subnet_destination_cidr_block |
Allowed destination CIDR block for access from the public VPC segment | string |
0.0.0.0/0 |
no | no |
public_subnet_destination_cidr_block |
Allowed destination CIDR block for access from the public VPC segment | string |
0.0.0.0/0 |
no | no |
subnets |
Specific definitions for the subnets creation. Map keys are used as subnet names and values with further defined elements | map(object) |
{} |
no | no |
subnets[<key>].availability_zone |
Availability zone of the subnet | string |
yes | no | |
subnets[<key>].enable_auto_assigning_ips |
Defines that instances launched into the public subnet should be assigned a public IP address | bool |
true |
no | no |
subnets[<key>].nat_via |
Name of public subnet to create NAT GW in. Private network will use it for outgoing Internet traffic | string |
no | no | |
subnets[<key>].private_subnet_cidr_block |
The IPv4 CIDR block for the private subnet | string |
no | no | |
subnets[<key>].public_subnet_cidr_block |
The IPv4 CIDR block for the public subnet | string |
no | no | |
subnets[<key>].tags |
Map of additional subnet-specific tags | map(string) |
no | no |
Output | Description | Type | Sensitive |
---|---|---|---|
nat_gw_ips |
List of elastic IPs used for outgoing traffic | list(attribute) |
no |
private_subnets |
Contains attributes of private VPC segment | resource |
no |
public_subnets |
Contains attributes of public VPC segment | resource |
no |
vpc |
Contains attributes of aws_vpc resource |
resource |
no |
Dependency | Version | Kind |
---|---|---|
terraform |
>= 1.3 |
CLI |
hashicorp/aws |
~> 5.0 |
provider |