Commit cf48c2ce authored by Scott Crooks's avatar Scott Crooks Committed by Anton Babenko

Fix #117 - Add `one_nat_gateway_per_az` functionality (#129)

* Initial commit for issue #117

* Adding documentation for NAT Gateway creation

* Adding `enable_nat_gateway` to the documentation

* Updating README.md with `one_nat_gateway_per_az` to be 'true' by default

* Reverted changes back to `one_nat_gateway_per_az` as 'false'
parent 11f92366
...@@ -78,6 +78,49 @@ Note that in the example we allocate 3 IPs because we will be provisioning 3 NAT ...@@ -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. 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}"]`. 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 ## 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`. 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. ...@@ -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 | | 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 | | 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 | | 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_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_subnet_tags | Additional tags for the private subnets | string | `<map>` | no |
| private_subnets | A list of private subnets inside the VPC | string | `<list>` | 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). ...@@ -227,3 +271,4 @@ Module managed by [Anton Babenko](https://github.com/antonbabenko).
## License ## License
Apache 2 Licensed. See LICENSE for full details. Apache 2 Licensed. See LICENSE for full details.
...@@ -4,7 +4,7 @@ terraform { ...@@ -4,7 +4,7 @@ terraform {
locals { locals {
max_subnet_length = "${max(length(var.private_subnets), length(var.elasticache_subnets), length(var.database_subnets), length(var.redshift_subnets))}" 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" { ...@@ -102,7 +102,7 @@ resource "aws_route_table" "private" {
# Public subnet # Public subnet
################ ################
resource "aws_subnet" "public" { 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}" vpc_id = "${aws_vpc.this.id}"
cidr_block = "${var.public_subnets[count.index]}" cidr_block = "${var.public_subnets[count.index]}"
......
...@@ -76,6 +76,11 @@ variable "single_nat_gateway" { ...@@ -76,6 +76,11 @@ variable "single_nat_gateway" {
default = false 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" { 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" 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 default = false
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment