Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #117 - Add one_nat_gateway_per_az functionality #129

Merged
merged 5 commits into from
May 24, 2018
Merged
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
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -78,6 +78,49 @@ Note that in the example we allocate 3 IPs because we will be provisioning 3 NAT
If, on the other hand, `single_nat_gateway = true`, then `aws_eip.nat` would only need to allocate 1 IP.
Passing the IPs into the module is done by setting two variables `reuse_nat_ips = true` and `external_nat_ip_ids = ["${aws_eip.nat.*.id}"]`.

## NAT Gateway Scenarios

This module supports three scenarios for creating NAT gateways. Each will be explained in further detail in the corresponding sections.

* One NAT Gateway per subnet (default behavior)
* `enable_nat_gateway = true`
* `single_nat_gateway = false`
* `one_nat_gateway_per_az = false`
* Single NAT Gateway
* `enable_nat_gateway = true`
* `single_nat_gateway = true`
* `one_nat_gateway_per_az = false`
* One NAT Gateway per availability zone
* `enable_nat_gateway = true`
* `single_nat_gateway = false`
* `one_nat_gateway_per_az = true`

If both `single_nat_gateway` and `one_nat_gateway_per_az` are set to `true`, then `single_nat_gateway` takes precedence.

### One NAT Gateway per subnet (default)

By default, the module will determine the number of NAT Gateways to create based on the the `max()` of the private subnet lists (`database_subnets`, `elasticache_subnets`, `private_subnets`, and `redshift_subnets`). For example, if your configuration looks like the following:

```hcl
database_subnets = ["10.0.21.0/24", "10.0.22.0/24"]
elasticache_subnets = ["10.0.31.0/24", "10.0.32.0/24"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
redshift_subnets = ["10.0.41.0/24", "10.0.42.0/24"]
```

Then `5` NAT Gateways will be created since `5` private subnet CIDR blocks were specified.

### Single NAT Gateway

If `single_nat_gateway = true`, then all private subnets will route their Internet traffic through this single NAT gateway. The NAT gateway will be placed in the first public subnet in your `public_subnets` block.

### One NAT Gateway per availability zone

If `one_nat_gateway_per_az = true` and `single_nat_gateway = false`, then the module will place one NAT gateway in each availability zone you specify in `var.azs`. There are some requirements around using this feature flag:

* The variable `var.azs` **must** be specified.
* The number of public subnet CIDR blocks specified in `public_subnets` **must** be greater than or equal to the number of availability zones specified in `var.azs`. This is to ensure that each NAT Gateway has a dedicated public subnet to deploy to.

## Conditional creation

Sometimes you need to have a way to create VPC resources conditionally but Terraform does not allow to use `count` inside `module` block, so the solution is to specify argument `create_vpc`.
@@ -141,6 +184,7 @@ Terraform version 0.10.3 or newer is required for this module to work.
| manage_default_vpc | Should be true to adopt and manage Default VPC | string | `false` | no |
| map_public_ip_on_launch | Should be false if you do not want to auto-assign public IP on launch | string | `true` | no |
| name | Name to be used on all the resources as identifier | string | `` | no |
| one_nat_gateway_per_az | Should be true if you want only one NAT Gateway per availability zone. Requires the input `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 `azs`. | string | `false` | no |
| private_route_table_tags | Additional tags for the private route tables | string | `<map>` | no |
| private_subnet_tags | Additional tags for the private subnets | string | `<map>` | no |
| private_subnets | A list of private subnets inside the VPC | string | `<list>` | no |
@@ -227,3 +271,4 @@ Module managed by [Anton Babenko](https://github.com/antonbabenko).
## License

Apache 2 Licensed. See LICENSE for full details.

4 changes: 2 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ terraform {

locals {
max_subnet_length = "${max(length(var.private_subnets), length(var.elasticache_subnets), length(var.database_subnets), length(var.redshift_subnets))}"
nat_gateway_count = "${var.single_nat_gateway ? 1 : local.max_subnet_length}"
nat_gateway_count = "${var.single_nat_gateway ? 1 : (var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length)}"
}

######
@@ -102,7 +102,7 @@ resource "aws_route_table" "private" {
# Public subnet
################
resource "aws_subnet" "public" {
count = "${var.create_vpc && length(var.public_subnets) > 0 ? length(var.public_subnets) : 0}"
count = "${var.create_vpc && length(var.public_subnets) > 0 && (!var.one_nat_gateway_per_az || length(var.public_subnets) >= length(var.azs)) ? length(var.public_subnets) : 0}"

vpc_id = "${aws_vpc.this.id}"
cidr_block = "${var.public_subnets[count.index]}"
5 changes: 5 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -76,6 +76,11 @@ variable "single_nat_gateway" {
default = false
}

variable "one_nat_gateway_per_az" {
description = "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`."
default = false
}

variable "reuse_nat_ips" {
description = "Should be true if you don't want EIPs to be created for your NAT Gateways and will instead pass them in via the 'external_nat_ip_ids' variable"
default = false