Skip to content

Commit b622cfc

Browse files
authored
Add nat-instance (#51)
* Add `nat-instance` * Pin terraform `required_version` * Update README * Pin aws provider * Update `aws_security_group_rule`
1 parent 44cf26d commit b622cfc

File tree

8 files changed

+151
-23
lines changed

8 files changed

+151
-23
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright 2017-2018 Cloud Posse, LLC
189+
Copyright 2017-2019 Cloud Posse, LLC
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are
4545

4646
## Usage
4747

48+
49+
**IMPORTANT:** The `master` branch is used in `source` just as an example. In your code, do not pin to `master` because there may be breaking changes between releases.
50+
Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest releases](https://github.com/cloudposse/terraform-aws-dynamic-subnets/releases).
51+
52+
4853
```hcl
4954
module "subnets" {
5055
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master"
@@ -156,10 +161,12 @@ Available targets:
156161
| delimiter | Delimiter to be used between `namespace`, `stage`, `name`, and `attributes` | string | `-` | no |
157162
| igw_id | Internet Gateway ID the public route table will point to (e.g. `igw-9c26a123`) | string | - | yes |
158163
| map_public_ip_on_launch | Instances launched into a public subnet should be assigned a public IP address | string | `true` | no |
159-
| max_subnet_count | Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every availablility zone within the region | string | `0` | no |
164+
| max_subnet_count | Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every provided availablility zone (in `availability_zones` variable) within the region | string | `0` | no |
160165
| name | Name (e.g. `app`) | string | - | yes |
161166
| namespace | Namespace (e.g. `cp` or `cloudposse`) | string | - | yes |
162-
| nat_gateway_enabled | Flag to enable/disable NAT gateways for private subnets | string | `true` | no |
167+
| nat_gateway_enabled | Flag to enable/disable NAT Gateways to allow servers in the private subnets to access the Internet | string | `true` | no |
168+
| nat_instance_enabled | Flag to enable/disable NAT Instances to allow servers in the private subnets to access the Internet | string | `false` | no |
169+
| nat_instance_type | NAT Instance type | string | `t3.micro` | no |
163170
| private_network_acl_id | Network ACL ID that will be added to private subnets. If empty, a new ACL will be created | string | `` | no |
164171
| public_network_acl_id | Network ACL ID that will be added to public subnets. If empty, a new ACL will be created | string | `` | no |
165172
| region | AWS Region (e.g. `us-east-1`) | string | - | yes |
@@ -174,13 +181,14 @@ Available targets:
174181
| Name | Description |
175182
|------|-------------|
176183
| availability_zones | List of Availability Zones where subnets were created |
177-
| nat_gateway_ids | AWS IDs of the NAT gateways created |
178-
| private_route_table_ids | AWS IDs of the created private route tables |
184+
| nat_gateway_ids | IDs of the NAT Gateways created |
185+
| nat_instance_ids | IDs of the NAT Instances created |
186+
| private_route_table_ids | IDs of the created private route tables |
179187
| private_subnet_cidrs | CIDR blocks of the created private subnets |
180-
| private_subnet_ids | AWS IDs of the created private subnets |
181-
| public_route_table_ids | AWS IDs of the created public route tables |
188+
| private_subnet_ids | IDs of the created private subnets |
189+
| public_route_table_ids | IDs of the created public route tables |
182190
| public_subnet_cidrs | CIDR blocks of the created public subnets |
183-
| public_subnet_ids | AWS IDs of the created public subnets |
191+
| public_subnet_ids | IDs of the created public subnets |
184192

185193

186194

docs/terraform.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
| delimiter | Delimiter to be used between `namespace`, `stage`, `name`, and `attributes` | string | `-` | no |
99
| igw_id | Internet Gateway ID the public route table will point to (e.g. `igw-9c26a123`) | string | - | yes |
1010
| map_public_ip_on_launch | Instances launched into a public subnet should be assigned a public IP address | string | `true` | no |
11-
| max_subnet_count | Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every availablility zone within the region | string | `0` | no |
11+
| max_subnet_count | Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every provided availablility zone (in `availability_zones` variable) within the region | string | `0` | no |
1212
| name | Name (e.g. `app`) | string | - | yes |
1313
| namespace | Namespace (e.g. `cp` or `cloudposse`) | string | - | yes |
14-
| nat_gateway_enabled | Flag to enable/disable NAT gateways for private subnets | string | `true` | no |
14+
| nat_gateway_enabled | Flag to enable/disable NAT Gateways to allow servers in the private subnets to access the Internet | string | `true` | no |
15+
| nat_instance_enabled | Flag to enable/disable NAT Instances to allow servers in the private subnets to access the Internet | string | `false` | no |
16+
| nat_instance_type | NAT Instance type | string | `t3.micro` | no |
1517
| private_network_acl_id | Network ACL ID that will be added to private subnets. If empty, a new ACL will be created | string | `` | no |
1618
| public_network_acl_id | Network ACL ID that will be added to public subnets. If empty, a new ACL will be created | string | `` | no |
1719
| region | AWS Region (e.g. `us-east-1`) | string | - | yes |
@@ -26,11 +28,12 @@
2628
| Name | Description |
2729
|------|-------------|
2830
| availability_zones | List of Availability Zones where subnets were created |
29-
| nat_gateway_ids | AWS IDs of the NAT gateways created |
30-
| private_route_table_ids | AWS IDs of the created private route tables |
31+
| nat_gateway_ids | IDs of the NAT Gateways created |
32+
| nat_instance_ids | IDs of the NAT Instances created |
33+
| private_route_table_ids | IDs of the created private route tables |
3134
| private_subnet_cidrs | CIDR blocks of the created private subnets |
32-
| private_subnet_ids | AWS IDs of the created private subnets |
33-
| public_route_table_ids | AWS IDs of the created public route tables |
35+
| private_subnet_ids | IDs of the created private subnets |
36+
| public_route_table_ids | IDs of the created public route tables |
3437
| public_subnet_cidrs | CIDR blocks of the created public subnets |
35-
| public_subnet_ids | AWS IDs of the created public subnets |
38+
| public_subnet_ids | IDs of the created public subnets |
3639

main.tf

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
# Pin the `aws` provider
2+
# https://www.terraform.io/docs/configuration/providers.html
3+
# Any non-beta version >= 2.12.0 and < 2.13.0, e.g. 2.12.X
4+
provider "aws" {
5+
version = "~> 2.12.0"
6+
}
7+
8+
# Terraform
9+
#--------------------------------------------------------------
110
terraform {
2-
required_version = ">= 0.10.2"
11+
required_version = "~> 0.11.0"
312
}
413

514
# Get object aws_vpc by vpc_id
File renamed without changes.

nat-instance.tf

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
module "nat_instance_label" {
2+
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.3"
3+
namespace = "${var.namespace}"
4+
stage = "${var.stage}"
5+
name = "${var.name}"
6+
delimiter = "${var.delimiter}"
7+
attributes = "${compact(concat(var.attributes,list("nat", "instance")))}"
8+
tags = "${var.tags}"
9+
}
10+
11+
locals {
12+
nat_instance_enabled = "${var.nat_instance_enabled == "true" ? true : false}"
13+
nat_instance_count = "${local.nat_instance_enabled ? length(var.availability_zones) : 0}"
14+
cidr_block = "${var.cidr_block != "" ? var.cidr_block : data.aws_vpc.default.cidr_block}"
15+
}
16+
17+
resource "aws_security_group" "nat_instance" {
18+
count = "${local.nat_instance_enabled ? 1 : 0}"
19+
name = "${module.nat_instance_label.id}"
20+
description = "Security Group for NAT Instance"
21+
vpc_id = "${var.vpc_id}"
22+
tags = "${module.nat_instance_label.tags}"
23+
}
24+
25+
resource "aws_security_group_rule" "nat_instance_egress" {
26+
count = "${local.nat_instance_enabled ? 1 : 0}"
27+
description = "Allow all egress traffic"
28+
from_port = 0
29+
to_port = 0
30+
protocol = "-1"
31+
cidr_blocks = ["0.0.0.0/0"]
32+
security_group_id = "${join("", aws_security_group.nat_instance.*.id)}"
33+
type = "egress"
34+
}
35+
36+
resource "aws_security_group_rule" "nat_instance_ingress" {
37+
count = "${local.nat_instance_enabled ? 1 : 0}"
38+
description = "Allow ingress traffic from the VPC CIDR block"
39+
from_port = 0
40+
to_port = 0
41+
protocol = "-1"
42+
cidr_blocks = ["${local.cidr_block}"]
43+
security_group_id = "${join("", aws_security_group.nat_instance.*.id)}"
44+
type = "ingress"
45+
}
46+
47+
// aws --region us-west-2 ec2 describe-images --owners amazon --filters Name="name",Values="amzn-ami-vpc-nat*" Name="virtualization-type",Values="hvm"
48+
data "aws_ami" "nat_instance" {
49+
count = "${local.nat_instance_enabled ? 1 : 0}"
50+
most_recent = true
51+
52+
filter {
53+
name = "name"
54+
values = ["amzn-ami-vpc-nat*"]
55+
}
56+
57+
filter {
58+
name = "virtualization-type"
59+
values = ["hvm"]
60+
}
61+
62+
owners = ["amazon"]
63+
}
64+
65+
// https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-comparison.html
66+
// https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html
67+
// https://dzone.com/articles/nat-instance-vs-nat-gateway
68+
resource "aws_instance" "nat_instance" {
69+
count = "${local.nat_instance_count}"
70+
ami = "${join("", data.aws_ami.nat_instance.*.id)}"
71+
instance_type = "${var.nat_instance_type}"
72+
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
73+
vpc_security_group_ids = ["${aws_security_group.nat_instance.id}"]
74+
tags = "${merge(module.nat_instance_label.tags, map("Name",format("%s%s%s", module.nat_label.id, var.delimiter, replace(element(var.availability_zones, count.index),"-",var.delimiter))))}"
75+
76+
# Required by NAT
77+
# https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html#EIP_Disable_SrcDestCheck
78+
source_dest_check = false
79+
80+
associate_public_ip_address = true
81+
82+
lifecycle {
83+
create_before_destroy = true
84+
}
85+
}
86+
87+
resource "aws_route" "nat_instance" {
88+
count = "${local.nat_instance_count}"
89+
route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
90+
instance_id = "${element(aws_instance.nat_instance.*.id, count.index)}"
91+
destination_cidr_block = "0.0.0.0/0"
92+
depends_on = ["aws_route_table.private"]
93+
}

outputs.tf

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
output "public_subnet_ids" {
2-
description = "AWS IDs of the created public subnets"
2+
description = "IDs of the created public subnets"
33
value = ["${aws_subnet.public.*.id}"]
44
}
55

66
output "private_subnet_ids" {
7-
description = "AWS IDs of the created private subnets"
7+
description = "IDs of the created private subnets"
88
value = ["${aws_subnet.private.*.id}"]
99
}
1010

@@ -19,20 +19,25 @@ output "private_subnet_cidrs" {
1919
}
2020

2121
output "public_route_table_ids" {
22-
description = "AWS IDs of the created public route tables"
22+
description = "IDs of the created public route tables"
2323
value = ["${aws_route_table.public.*.id}"]
2424
}
2525

2626
output "private_route_table_ids" {
27-
description = "AWS IDs of the created private route tables"
27+
description = "IDs of the created private route tables"
2828
value = ["${aws_route_table.private.*.id}"]
2929
}
3030

3131
output "nat_gateway_ids" {
32-
description = "AWS IDs of the NAT gateways created"
32+
description = "IDs of the NAT Gateways created"
3333
value = ["${aws_nat_gateway.default.*.id}"]
3434
}
3535

36+
output "nat_instance_ids" {
37+
description = "IDs of the NAT Instances created"
38+
value = ["${aws_instance.nat_instance.*.id}"]
39+
}
40+
3641
output "availability_zones" {
3742
description = "List of Availability Zones where subnets were created"
3843
value = "${var.availability_zones}"

variables.tf

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ variable "region" {
4343

4444
variable "max_subnet_count" {
4545
default = 0
46-
description = "Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every availablility zone within the region"
46+
description = "Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every provided availablility zone (in `availability_zones` variable) within the region"
4747
}
4848

4949
variable "vpc_id" {
@@ -82,10 +82,20 @@ variable "private_network_acl_id" {
8282
}
8383

8484
variable "nat_gateway_enabled" {
85-
description = "Flag to enable/disable NAT gateways for private subnets"
85+
description = "Flag to enable/disable NAT Gateways to allow servers in the private subnets to access the Internet"
8686
default = "true"
8787
}
8888

89+
variable "nat_instance_enabled" {
90+
description = "Flag to enable/disable NAT Instances to allow servers in the private subnets to access the Internet"
91+
default = "false"
92+
}
93+
94+
variable "nat_instance_type" {
95+
description = "NAT Instance type"
96+
default = "t3.micro"
97+
}
98+
8999
variable "map_public_ip_on_launch" {
90100
default = "true"
91101
description = "Instances launched into a public subnet should be assigned a public IP address"

0 commit comments

Comments
 (0)