Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,13 @@ Full contributing [guidelines are covered here](.github/contributing.md).
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.24.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.24.0 |

## Modules

Expand All @@ -272,6 +272,7 @@ No modules.
| [aws_iam_role.vpc_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.vpc_flow_log_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_internet_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | resource |
| [aws_nat_gateway.regional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource |
| [aws_nat_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource |
| [aws_network_acl.database](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource |
| [aws_network_acl.elasticache](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource |
Expand Down Expand Up @@ -487,6 +488,7 @@ No modules.
| <a name="input_map_public_ip_on_launch"></a> [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default is `false` | `bool` | `false` | no |
| <a name="input_name"></a> [name](#input\_name) | Name to be used on all the resources as identifier | `string` | `""` | no |
| <a name="input_nat_eip_tags"></a> [nat\_eip\_tags](#input\_nat\_eip\_tags) | Additional tags for the NAT EIP | `map(string)` | `{}` | no |
| <a name="input_nat_gateway_connectivity_type"></a> [nat\_gateway\_connectivity\_type](#input\_nat\_gateway\_connectivity\_type) | Connectivity type for the NAT Gateway. Valid values are:<br/>- 'zonal' (default): Traditional AZ-specific NAT gateways that require public subnets<br/>- 'regional': A single NAT Gateway that automatically scales across all AZs (does not require public subnets)<br/><br/>Regional NAT Gateway support requires Terraform AWS provider >= 6.24.0.<br/>When using 'regional' mode, only one NAT Gateway is created for the entire VPC. | `string` | `"zonal"` | no |
| <a name="input_nat_gateway_destination_cidr_block"></a> [nat\_gateway\_destination\_cidr\_block](#input\_nat\_gateway\_destination\_cidr\_block) | Used to pass a custom destination route for private NAT Gateway. If not specified, the default 0.0.0.0/0 is used as a destination route | `string` | `"0.0.0.0/0"` | no |
| <a name="input_nat_gateway_tags"></a> [nat\_gateway\_tags](#input\_nat\_gateway\_tags) | Additional tags for the NAT gateways | `map(string)` | `{}` | no |
| <a name="input_one_nat_gateway_per_az"></a> [one\_nat\_gateway\_per\_az](#input\_one\_nat\_gateway\_per\_az) | Should be true if you want only one NAT Gateway per availability zone. Requires `var.azs` to be set, and the number of `public_subnets` created to be greater than or equal to the number of availability zones specified in `var.azs` | `bool` | `false` | no |
Expand Down
86 changes: 86 additions & 0 deletions examples/regional-nat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Regional NAT Gateway Example

This example demonstrates how to use the **Regional NAT Gateway** feature in the Terraform AWS VPC module. Regional NAT Gateways provide a highly available NAT solution that automatically scales across multiple Availability Zones within your VPC.

## Key Features of Regional NAT Gateway

- **Single NAT Gateway**: One NAT Gateway serves all Availability Zones in your VPC
- **Automatic High Availability**: Automatically expands and contracts across AZs based on workload distribution
- **No Public Subnets Required**: Regional NAT Gateways operate without requiring public subnets (though we include them here for demonstration)
- **Simplified Management**: Single NAT Gateway ID for consistent route entries across all subnets
- **Increased Capacity**: Supports up to 32 Elastic IP addresses per AZ (compared to 8 for zonal NAT Gateways)

## Architecture

This example creates:

- **VPC**: Single VPC with CIDR block `10.0.0.0/16`
- **Private Subnets**: 3 private subnets (one per Availability Zone)
- **Public Subnets**: 3 public subnets (one per Availability Zone)
- **Database Subnets**: 3 database subnets (one per Availability Zone)
- **Regional NAT Gateway**: Single NAT Gateway that automatically scales across all AZs
- **Internet Gateway**: For outbound internet connectivity

## Usage

To run this example you need to execute:

```bash
$ terraform init
$ terraform plan
$ terraform apply
```

Note that this example may create resources which can cost money (AWS Elastic IP, NAT Gateway, etc.). Run `terraform destroy` when you don't need these resources.

## Configuration

The key configuration for Regional NAT Gateway is:

```hcl
enable_nat_gateway = true
nat_gateway_connectivity_type = "regional"
```

## Comparison: Regional vs Zonal NAT Gateway

### Regional NAT Gateway (This Example)
- **Count**: 1 NAT Gateway for entire VPC
- **Route Tables**: One route table per private subnet (all route to the same NAT Gateway)
- **Subnet Requirement**: No public subnets required
- **Use Case**: Simplified management, automatic scaling, high availability across all AZs

### Zonal NAT Gateway (Traditional)
- **Count**: 1 NAT Gateway per AZ (or per subnet)
- **Route Tables**: Route tables match NAT Gateway count
- **Subnet Requirement**: Requires public subnets
- **Use Case**: Fine-grained control, per-AZ NAT Gateways

## Important Notes

1. **Expansion Timing**: When deploying workloads in a new AZ, the regional NAT Gateway typically takes 15-20 minutes (up to 60 minutes) to expand to that AZ. During this period, traffic may be temporarily routed through existing AZs.

2. **Private Connectivity**: Regional NAT Gateways do not support private connectivity. For workloads requiring private connectivity, continue using zonal NAT Gateways.

3. **Availability**: This feature is available in all commercial AWS Regions, except for AWS GovCloud (US) Regions and China Regions.

4. **Cost Considerations**: Regional NAT Gateways are charged per hour and per GB processed, similar to zonal NAT Gateways, but you only pay for one NAT Gateway instead of multiple.

## Outputs

After applying this configuration, you can see:
- Single NAT Gateway ID in `natgw_ids` output (list with one element)
- All private route tables route to the same NAT Gateway
- One Elastic IP allocated for the regional NAT Gateway

## Requirements

| Name | Version |
|------|---------|
| terraform | >= 1.0 |
| aws | >= 6.24.0 (required for regional NAT gateway support) |

## References

- [AWS Regional NAT Gateway Documentation](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateways-regional.html)
- [AWS Blog: Introducing Amazon VPC Regional NAT Gateway](https://aws.amazon.com/blogs/networking-and-content-delivery/introducing-amazon-vpc-regional-nat-gateway/)
37 changes: 37 additions & 0 deletions examples/regional-nat/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
provider "aws" {
region = local.region
}

data "aws_availability_zones" "available" {}

locals {
region = "ap-south-1"
name = "ex-${basename(path.cwd)}"

vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)

tags = {
Example = local.name
}
}

module "vpc" {
source = "../../"
name = local.name
cidr = local.vpc_cidr

azs = local.azs
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 4)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 8)]

enable_dns_hostnames = true
enable_dns_support = true

# Regional NAT Gateway Configuration
# Requires Terraform AWS provider >= 6.24.0
enable_nat_gateway = true
nat_gateway_connectivity_type = "regional"
tags = local.tags
}
75 changes: 75 additions & 0 deletions examples/regional-nat/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
################################################################################
# VPC Outputs
################################################################################

output "vpc_id" {
description = "The ID of the VPC"
value = module.vpc.vpc_id
}

output "vpc_cidr_block" {
description = "The CIDR block of the VPC"
value = module.vpc.vpc_cidr_block
}

################################################################################
# Subnet Outputs
################################################################################

output "private_subnets" {
description = "List of IDs of private subnets"
value = module.vpc.private_subnets
}

output "private_subnets_cidr_blocks" {
description = "List of cidr_blocks of private subnets"
value = module.vpc.private_subnets_cidr_blocks
}

output "private_route_table_ids" {
description = "List of IDs of private route tables"
value = module.vpc.private_route_table_ids
}

output "public_subnets" {
description = "List of IDs of public subnets"
value = module.vpc.public_subnets
}

output "database_subnets" {
description = "List of IDs of database subnets"
value = module.vpc.database_subnets
}

################################################################################
# NAT Gateway Outputs
################################################################################

output "natgw_ids" {
description = "List of NAT Gateway IDs (will contain a single regional NAT Gateway)"
value = module.vpc.natgw_ids
}

output "nat_public_ips" {
description = "List of public Elastic IPs created for AWS NAT Gateway"
value = module.vpc.nat_public_ips
}

output "nat_ids" {
description = "List of allocation ID of Elastic IPs created for AWS NAT Gateway"
value = module.vpc.nat_ids
}

output "private_nat_gateway_route_ids" {
description = "List of IDs of the private nat gateway route (all route to the same regional NAT Gateway)"
value = module.vpc.private_nat_gateway_route_ids
}

################################################################################
# Internet Gateway Outputs
################################################################################

output "igw_id" {
description = "The ID of the Internet Gateway"
value = module.vpc.igw_id
}
Empty file.
10 changes: 10 additions & 0 deletions examples/regional-nat/version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.24.0"
}
}
}
Loading