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

possibility of using nat instance, which can be multi-az or just one nat instance per region. #16

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
64e38dd
Option to not create nat gw
jrpradojr Jan 19, 2021
5e97329
Added option to choose NAT Gateway or Instance
jrpradojr Jan 19, 2021
dd0180d
Update init.sh
jrpradojr Jan 19, 2021
378e1c2
Fix data
jrpradojr Jan 19, 2021
3e71f50
Fix data
jrpradojr Jan 19, 2021
2b5e6a5
Fix subnet private
jrpradojr Jan 19, 2021
75d06d1
TODO correct nat cloudformation_stack
jrpradojr Jan 19, 2021
6ce8200
Fix nat_instance
jrpradojr Jan 19, 2021
d612d10
Fix nat_instance
jrpradojr Jan 19, 2021
2965208
Fixed version
jrpradojr Jan 19, 2021
6d7c51b
Fixed nat policy
jrpradojr Jan 19, 2021
431fe30
Final version
jrpradojr Jan 19, 2021
3a90d51
Disable source dest check
jrpradojr Jan 20, 2021
acf755e
Ajust init.sh
jrpradojr Jan 20, 2021
26e5c47
Update AMI and init.sh
jrpradojr Jan 20, 2021
4430073
Fixed sg when nat_instance=true and multi_az=false
jrpradojr Jan 20, 2021
f715978
Fixed role and profile names
jrpradojr Jan 25, 2021
90ba0d9
Update _data.tf
jrpradojr Apr 12, 2021
4e12915
changed instance type to graviton (arm)
jrpradojr Apr 12, 2021
04484f4
Update _variables.tf
jrpradojr Apr 17, 2021
ba7f3ee
Update init.sh
jrpradojr Apr 22, 2021
f5e3fa6
Update _variables.tf
jrpradojr Apr 22, 2021
767e500
Update _variables.tf
jrpradojr Apr 22, 2021
fbe6bfd
Update _data.tf
jrpradojr Apr 22, 2021
b9c8e1b
Update _variables.tf
jrpradojr Apr 22, 2021
e0d67ff
Added option to enable or disable vpc flow logs
May 4, 2021
2c4a20e
Updated the Readme
May 4, 2021
723befe
Fixed vpc-flow-logs
May 4, 2021
cdd137b
Fixed interpolation
May 4, 2021
537f932
Updated the Readme
jrpradojr May 4, 2021
061a26e
Fixed vpc-flow-logs
jrpradojr May 4, 2021
000eb8f
Merge branch 'master' into nat_gw
jrpradojr May 24, 2021
2c22d51
Merged from master
jrpradojr May 24, 2021
5580200
Removed expressions deprecated from files
jrpradojr Jul 23, 2021
1246ccf
Changed test connection url to http://www.google.com
jrpradojr Aug 24, 2021
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
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The following resources will be created:
- Internet Gateway
- Route tables for the Public, Private, Secure and Transit subnets
- Associate all Route Tables created to the correct subnet
- Nat Gateway
- Option to create Nat Gateway or Nat instance
- Network Access Control List (NACL) for all subnets
- Database Subnet group - Provides an RDS DB subnet group resources
- S3 VPC endpoint
Expand Down Expand Up @@ -51,17 +51,22 @@ module "network" {
| Name | Version |
|------|---------|
| aws | n/a |
| template | n/a |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| cf\_export\_name | Name prefix for the export resources of the cloud formation output | `string` | `""` | no |
| instance\_types | Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy | `list` | <pre>[<br> "t4g.micro",<br> "t4g.small",<br> "t4g.medium"<br>]</pre> | no |
| kubernetes\_clusters | List of kubernetes cluster names to creates tags in public and private subnets of this VPC | `list(string)` | `[]` | no |
| kubernetes\_clusters\_type | Use either 'owned' or 'shared' for kubernetes cluster tags | `string` | `"shared"` | no |
| max\_az | Max number of AZs | `number` | `3` | no |
| multi\_nat | Number of NAT Instances, 'true' will yield one per AZ while 'false' creates one NAT | `bool` | `false` | no |
| multi\_nat | Number of NAT, 'true' will yield one per AZ while 'false' creates one NAT | `bool` | `false` | no |
| name | Name prefix for the resources of this stack | `any` | n/a | yes |
| nat\_architecture | Architecture type of instance | `list` | <pre>[<br> "arm64"<br>]</pre> | no |
| nat\_gw | Create a NAT Gateway (Require: nat\_instance=false) | `bool` | `true` | no |
| nat\_instance | Create a NAT Gateway (Require: nat\_gw=false ) | `bool` | `false` | no |
| newbits | Number of bits to add to the vpc cidr when building subnets | `number` | `5` | no |
| private\_netnum\_offset | Start with this subnet for private ones, plus number of AZs | `number` | `5` | no |
| public\_nacl\_inbound\_tcp\_ports | TCP Ports to allow inbound on public subnet via NACLs (this list cannot be empty) | `list(string)` | <pre>[<br> "80",<br> "443",<br> "22",<br> "1194"<br>]</pre> | no |
Expand All @@ -83,6 +88,7 @@ module "network" {

| Name | Description |
|------|-------------|
| aws\_availability\_zones | aws\_availability\_zones |
| cidr\_block | CIDR for VPC created |
| db\_subnet\_group\_id | n/a |
| internet\_gateway\_id | ID of Internet Gateway created |
Expand Down
35 changes: 34 additions & 1 deletion _data.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
state = "available"
}

output "aws_availability_zones" {
value = data.aws_availability_zones.available.names
description = "aws_availability_zones"
}

data "aws_availability_zone" "az" {
count = length(data.aws_availability_zones.available.names)
name = data.aws_availability_zones.available.names[count.index]
}

data "aws_region" "current" {}

# AMI of the latest Amazon Linux 2
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "architecture"
values = var.nat_architecture
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
}
}
24 changes: 22 additions & 2 deletions _variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,28 @@ variable "vpc_cidr_transit" {

variable "multi_nat" {
default = false
description = "Number of NAT Instances, 'true' will yield one per AZ while 'false' creates one NAT"
description = "Number of NAT, 'true' will yield one per AZ while 'false' creates one NAT"
}

variable "nat_gw" {
default = true
description = "Create a NAT Gateway (Require: nat_instance=false)"
}

variable "nat_instance" {
default = false
description = "Create a NAT Gateway (Require: nat_gw=false )"
}

variable "nat_architecture" {
default = ["arm64"]
description = "Architecture type of instance"
}

variable "instance_types" {
description = "Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy"
type = list(any)
default = ["t4g.micro", "t4g.small", "t4g.medium"]
}

variable "newbits" {
Expand Down Expand Up @@ -114,7 +135,6 @@ variable "kubernetes_clusters_type" {
description = "Use either 'owned' or 'shared' for kubernetes cluster tags"
}


locals {
kubernetes_clusters = zipmap(
formatlist("kubernetes.io/cluster/%s", var.kubernetes_clusters),
Expand Down
4 changes: 2 additions & 2 deletions cf-exports.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ resource "aws_cloudformation_stack" "tf_exports" {
"PrivateSubnetCidrs" = join(",", aws_subnet.private.*.cidr_block),
"SecureSubnetIds" = join(",", aws_subnet.secure.*.id),
"SecureSubnetCidrs" = join(",", aws_subnet.secure.*.cidr_block),
"NatGatewayIds" = join(",", aws_nat_gateway.nat_gw.*.id),
"DbSubnetGroupId" = aws_db_subnet_group.secure.id
#"NatGatewayIds" = join(",", aws_nat_gateway.nat_gw.*.id),
"DbSubnetGroupId" = aws_db_subnet_group.secure.id
}
})
}
95 changes: 95 additions & 0 deletions data/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#! /bin/bash
set -x

echo "### INSTALL PACKAGES"
yum update -y
yum install -y amazon-efs-utils aws-cli

echo "### INSTALL SSM AGENT"
cd /tmp
yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm

echo "### CONFIG NETWORK INTERFACE"
echo "### Determine the region"
export AWS_DEFAULT_REGION="$(/opt/aws/bin/ec2-metadata -z | sed 's/placement: \(.*\).$/\1/')"

echo "### Determine the instance id"
instance_id="$(/opt/aws/bin/ec2-metadata -i | cut -d' ' -f2)"

echo "### Disable source dest check"
aws ec2 modify-instance-attribute --instance-id "$instance_id" --source-dest-check "{\"Value\": false}"

echo "### Determine the count of EIP id"
eip_id="$(aws ec2 describe-addresses --query Addresses[*].AllocationId --filters "Name=tag:Function,Values=NAT-instance" --output text)"

if [ $(echo "$eip_id" |wc -w) -eq 1 ]; then
echo "### Attach the EIP"
aws ec2 associate-address --instance-id "$instance_id" --allocation-id "$eip_id"

echo "### Change the private route tables"
route_tables="$(aws ec2 describe-route-tables --query RouteTables[*].RouteTableId --filters "Name=tag:Scheme,Values=private" --output text)"
for route_id in $(echo "$route_tables")
do
route_internet="$(aws ec2 describe-route-tables --route-table-ids "$route_id" |grep -c "0.0.0.0/0")"
if [ "$route_internet" -eq 0 ]
then
aws ec2 create-route --route-table-id "$route_id" --destination-cidr-block 0.0.0.0/0 --instance-id "$instance_id"
else
aws ec2 replace-route --route-table-id "$route_id" --destination-cidr-block 0.0.0.0/0 --instance-id "$instance_id"
fi
done

echo "### enable IP forwarding and NAT"
sysctl -q -w net.ipv4.ip_forward=1
sysctl -q -w net.ipv4.conf.eth0.send_redirects=0
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

echo "### wait for network connection"
curl --retry 20 http://www.google.com

echo "### reestablish connections"
systemctl restart amazon-ssm-agent

else
echo "### Determine the network id in the zone"
timeout=600
time_count=0
zone_name="$(/opt/aws/bin/ec2-metadata -z | cut -d' ' -f2)"
eni_id=$(aws ec2 describe-network-interfaces --query NetworkInterfaces[*].NetworkInterfaceId --filters "Name=status,Values=available" "Name=tag:Function,Values=NAT-instance" "Name=availability-zone,Values=$zone_name" --output text)

while [ -z $eni_id ]; do
let time_count++
sleep 1
eni_id=$(aws ec2 describe-network-interfaces --query NetworkInterfaces[*].NetworkInterfaceId --filters "Name=status,Values=available" "Name=tag:Function,Values=NAT-instance" "Name=availability-zone,Values=$zone_name" --output text)
if [ $time_count -eq $timeout ]; then
echo "No network interface available to instance"
shutdown -h now
fi
done

echo "### Attach network interface"
aws ec2 attach-network-interface \
--region "$(/opt/aws/bin/ec2-metadata -z | sed 's/placement: \(.*\).$/\1/')" \
--instance-id "$(/opt/aws/bin/ec2-metadata -i | cut -d' ' -f2)" \
--device-index 1 \
--network-interface-id "$eni_id"

while ! ip link show dev eth1; do
sleep 1
done

echo "### enable IP forwarding and NAT"
sysctl -q -w net.ipv4.ip_forward=1
sysctl -q -w net.ipv4.conf.eth1.send_redirects=0
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

echo "### switch the default route to eth1"
ip route del default dev eth0

echo "### wait for network connection"
curl --retry 20 http://www.google.com

echo "### reestablish connections"
systemctl restart amazon-ssm-agent

fi
8 changes: 6 additions & 2 deletions nat.tf
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
resource "aws_eip" "nat_eip" {
count = var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : 1
# count = var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : var.nat_gw ? 1 : 0
count = var.nat_gw ? var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : 1 : 0
vpc = true

tags = merge(
var.tags,
{
"Name" = "${var.name}-EIP-${count.index}"
"EnvName" = var.name
"Az" = upper(data.aws_availability_zone.az[count.index].name_suffix)
},
)
}

resource "aws_nat_gateway" "nat_gw" {
count = var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : 1
# count = var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : var.nat_gw ? 1 : 0
count = var.nat_gw ? var.multi_nat ? length(data.aws_availability_zones.available.names) > var.max_az ? var.max_az : length(data.aws_availability_zones.available.names) : 1 : 0
allocation_id = aws_eip.nat_eip[count.index].id
subnet_id = aws_subnet.public[count.index].id

Expand All @@ -21,6 +24,7 @@ resource "aws_nat_gateway" "nat_gw" {
{
"Name" = "${var.name}-NATGW-${count.index}"
"EnvName" = var.name
"Az" = upper(data.aws_availability_zone.az[count.index].name_suffix)
},
)
}
Loading