Skip to content

Commit 5c111ad

Browse files
miguelaferreiraantonbabenko
authored andcommitted
Allow passing in EIPs for the NAT Gateways (terraform-aws-modules#38)
* Allow passing in EIPs for the NAT Gateways * Document how to pass external IPs for NAT Gateways * Update README.md to reduce example code
1 parent 3ddef14 commit 5c111ad

File tree

3 files changed

+69
-7
lines changed

3 files changed

+69
-7
lines changed

README.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ These types of resources are supported:
99
* [Subnet](https://www.terraform.io/docs/providers/aws/r/subnet.html)
1010
* [Route](https://www.terraform.io/docs/providers/aws/r/route.html)
1111
* [Route table](https://www.terraform.io/docs/providers/aws/r/route_table.html)
12-
* [Internet Gateway](https://www.terraform.io/docs/providers/aws/r/internet_gateway.html)
12+
* [Internet Gateway](https://www.terraform.io/docs/providers/aws/r/internet_gateway.html)
1313
* [NAT Gateway](https://www.terraform.io/docs/providers/aws/r/nat_gateway.html)
1414
* [VPN Gateway](https://www.terraform.io/docs/providers/aws/r/vpn_gateway.html)
1515
* [VPC Endpoint](https://www.terraform.io/docs/providers/aws/r/vpc_endpoint.html) (S3 and DynamoDB)
16-
* [RDS DB Subnet Group](https://www.terraform.io/docs/providers/aws/r/db_subnet_group.html)
16+
* [RDS DB Subnet Group](https://www.terraform.io/docs/providers/aws/r/db_subnet_group.html)
1717
* [ElastiCache Subnet Group](https://www.terraform.io/docs/providers/aws/r/elasticache_subnet_group.html)
1818
* [DHCP Options Set](https://www.terraform.io/docs/providers/aws/r/vpc_dhcp_options.html)
1919

@@ -31,7 +31,7 @@ module "vpc" {
3131
3232
name = "my-vpc"
3333
cidr = "10.0.0.0/16"
34-
34+
3535
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
3636
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
3737
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
@@ -46,10 +46,45 @@ module "vpc" {
4646
}
4747
```
4848

49+
External NAT Gateway IPs
50+
------------------------
51+
52+
By default this module will provision new Elastic IPs for the VPC's NAT Gateways.
53+
This means that when creating a new VPC, new IPs are allocated, and when that VPC is destroyed those IPs are released.
54+
Sometimes it is handy to keep the same IPs even after the VPC is destroyed and re-created.
55+
To that end, it is possible to assign existing IPs to the NAT Gateways.
56+
This prevents the destruction of the VPC from releasing those IPs, while making it possible that a re-created VPC uses the same IPs.
57+
58+
To achieve this, allocate the IPs outside the VPC module declaration.
59+
```hcl
60+
resource "aws_eip" "nat" {
61+
count = 3
62+
63+
vpc = true
64+
}
65+
```
66+
67+
Then, pass the allocated IPs as a parameter to this module.
68+
```hcl
69+
module "vpc" {
70+
source = "terraform-aws-modules/vpc/aws"
71+
72+
# The rest of arguments are omitted for brevity
73+
74+
enable_nat_gateway = true
75+
single_nat_gateway = false
76+
external_nat_ip_ids = ["${resource.aws_eip.nat.*.id}"] # <= IPs specified here as input to the module
77+
}
78+
```
79+
80+
Note that in the example we allocate 3 IPs because we will be provisioning 3 NAT Gateways (due to `single_nat_gateway = false` and having 3 subnets).
81+
If, on the other hand, `single_nat_gateway = true`, then `aws_eip.nat` would only need to allocate 1 IP.
82+
Passing the IPs into the module is done by setting variable `external_nat_ip_ids = ["${resource.aws_eip.nat.*.id}"]`.
83+
4984
Terraform version
5085
-----------------
5186

52-
Terraform version 1.0.0 or newer is required for this version to work.
87+
Terraform version 0.10.13 or newer is required for this module to work.
5388

5489
Examples
5590
--------
@@ -66,4 +101,4 @@ Module managed by [Anton Babenko](https://github.com/antonbabenko).
66101
License
67102
-------
68103

69-
Apache 2 Licensed. See LICENSE for full details.
104+
Apache 2 Licensed. See LICENSE for full details.

main.tf

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
terraform {
2+
required_version = ">= 0.10.13" # introduction of Local Values configuration language feature
3+
}
4+
15
######
26
# VPC
37
######
@@ -152,16 +156,28 @@ resource "aws_elasticache_subnet_group" "elasticache" {
152156
##############
153157
# NAT Gateway
154158
##############
159+
# Workaround for interpolation not being able to "short-circuit" the evaluation of the conditional branch that doesn't end up being used
160+
# Source: https://github.com/hashicorp/terraform/issues/11566#issuecomment-289417805
161+
#
162+
# The logical expression would be
163+
#
164+
# nat_gateway_ips = var.reuse_nat_ips ? var.external_nat_ip_ids : aws_eip.nat.*.id
165+
#
166+
# but then when count of aws_eip.nat.*.id is zero, this would throw a resource not found error on aws_eip.nat.*.id.
167+
locals {
168+
nat_gateway_ips = "${split(",", (var.reuse_nat_ips ? join(",", var.external_nat_ip_ids) : join(",", aws_eip.nat.*.id)))}"
169+
}
170+
155171
resource "aws_eip" "nat" {
156-
count = "${var.enable_nat_gateway ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0}"
172+
count = "${(var.enable_nat_gateway && !var.reuse_nat_ips) ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0}"
157173

158174
vpc = true
159175
}
160176

161177
resource "aws_nat_gateway" "this" {
162178
count = "${var.enable_nat_gateway ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0}"
163179

164-
allocation_id = "${element(aws_eip.nat.*.id, (var.single_nat_gateway ? 0 : count.index))}"
180+
allocation_id = "${element(local.nat_gateway_ips, (var.single_nat_gateway ? 0 : count.index))}"
165181
subnet_id = "${element(aws_subnet.public.*.id, (var.single_nat_gateway ? 0 : count.index))}"
166182

167183
tags = "${merge(var.tags, map("Name", format("%s-%s", var.name, element(var.azs, (var.single_nat_gateway ? 0 : count.index)))))}"

variables.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ variable "single_nat_gateway" {
6565
default = false
6666
}
6767

68+
variable "reuse_nat_ips" {
69+
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"
70+
default = false
71+
}
72+
73+
variable "external_nat_ip_ids" {
74+
description = "List of EIP IDs to be assigned to the NAT Gateways (used in combination with reuse_nat_ips)"
75+
type = "list"
76+
default = []
77+
}
78+
6879
variable "enable_dynamodb_endpoint" {
6980
description = "Should be true if you want to provision a DynamoDB endpoint to the VPC"
7081
default = false

0 commit comments

Comments
 (0)