Last active
December 25, 2018 11:17
-
-
Save ralph-tice/3d6e5b2076cbc2900aaa to your computer and use it in GitHub Desktop.
terraform for 3 AZ VPC with NAT instance with autorecovery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
########### | |
# Variables | |
########### | |
variable "aws_key_name" { | |
default = "mykeypair" | |
} | |
variable "region" { | |
default = "eu-west-1" | |
} | |
variable "vpc_name" { | |
default = "Development VPC" | |
} | |
# this template will use a /16 for the VPC and /24s for subnets | |
# starting at *.*.0.0/24 for private, counting up | |
# and *.*.255.0/24 for public, counting down | |
variable "cidr_prefix" { | |
default = "10.253" | |
} | |
######### | |
# Outputs | |
######### | |
output availability_zones { | |
value = "eu-west-1a,eu-west-1b,eu-west-1c" | |
} | |
output default_elb_sg { | |
value = "${aws_security_group.default_elb.id}" | |
} | |
output default_host_sg { | |
value = "${aws_security_group.default_host.id}" | |
} | |
output private_subnet_ids { | |
value = "${aws_subnet.a_private.id},${aws_subnet.b_private.id},${aws_subnet.c_private.id}" | |
} | |
output private_subnet_ids_elb { | |
value = "${aws_subnet.a_private.id},${aws_subnet.b_private.id},${aws_subnet.c_private.id}" | |
} | |
output public_subnet_ids { | |
value = "${aws_subnet.a_public.id},${aws_subnet.b_public.id},${aws_subnet.c_public.id}" | |
} | |
output region { | |
value = "${var.region}" | |
} | |
output vpc_id { | |
value = "${aws_vpc.this_vpc.id}" | |
} | |
output vpc_cidr_block { | |
value = "${aws_vpc.this_vpc.cidr_block}" | |
} | |
# Subnets | |
output "production_1a_private_id" { value = "${aws_subnet.a_private.id}" } | |
output "production_1b_private_id" { value = "${aws_subnet.b_private.id}" } | |
output "production_1c_private_id" { value = "${aws_subnet.c_private.id}" } | |
output "production_1a_public_id" { value = "${aws_subnet.a_public.id}" } | |
output "production_1b_public_id" { value = "${aws_subnet.b_public.id}" } | |
output "production_1c_public_id" { value = "${aws_subnet.c_public.id}" } | |
########### | |
# Resources | |
########### | |
provider aws { | |
region = "${var.region}" | |
} | |
# Vpc | |
resource aws_vpc "this_vpc" { | |
cidr_block = "${var.cidr_prefix}.0.0/16" | |
tags { | |
Name = "${var.vpc_name}" | |
} | |
} | |
resource "aws_internet_gateway" "default" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
} | |
# Subnets | |
resource aws_subnet "a_private" { | |
availability_zone = "${var.region}a" | |
cidr_block = "${var.cidr_prefix}.0.0/24" | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_a_private" | |
} | |
} | |
resource aws_subnet "b_private" { | |
availability_zone = "${var.region}b" | |
cidr_block = "${var.cidr_prefix}.1.0/24" | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_b_private" | |
} | |
} | |
resource aws_subnet "c_private" { | |
availability_zone = "${var.region}c" | |
cidr_block = "${var.cidr_prefix}.2.0/24" | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_c_private" | |
} | |
} | |
resource aws_subnet "a_public" { | |
availability_zone = "${var.region}a" | |
cidr_block = "${var.cidr_prefix}.255.0/24" | |
map_public_ip_on_launch = true | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_a_public" | |
} | |
} | |
resource aws_subnet "b_public" { | |
availability_zone = "${var.region}b" | |
cidr_block = "${var.cidr_prefix}.254.0/24" | |
map_public_ip_on_launch = true | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_b_public" | |
} | |
} | |
resource aws_subnet "c_public" { | |
availability_zone = "${var.region}c" | |
cidr_block = "${var.cidr_prefix}.253.0/24" | |
map_public_ip_on_launch = true | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
tags { | |
Name = "${var.vpc_name}_c_public" | |
} | |
} | |
# Security Groups | |
resource aws_security_group "default_elb" { | |
name = "Prod Security Group for internal Service ELBs" | |
description = "Prod Security Group for internal Service ELBs" | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
ingress = { | |
cidr_blocks = ["${var.cidr_prefix}.0.0/16"] | |
from_port = "0" | |
to_port = "0" | |
protocol = "-1" | |
} | |
egress = { | |
cidr_blocks = ["0.0.0.0/0"] | |
from_port = "0" | |
to_port = "0" | |
protocol = "-1" | |
} | |
} | |
resource aws_security_group "default_host" { | |
name = "Prod Security Group for Service Apps" | |
description = "Prod Security Group for Service Apps" | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
# Allow access from the elb security group | |
ingress = { | |
security_groups = [ "${aws_security_group.default_elb.id}" ] | |
from_port = "0" | |
to_port = "0" | |
protocol = "-1" | |
} | |
# Allow SSH on all svc app instances | |
ingress = { | |
cidr_blocks = ["0.0.0.0/0"] | |
from_port = "22" | |
to_port = "22" | |
protocol = "tcp" | |
} | |
# Allow consul gossip | |
ingress = { | |
cidr_blocks = ["${var.cidr_prefix}.0.0/16"] | |
from_port = "8300" | |
to_port = "8302" | |
protocol = "tcp" | |
} | |
ingress = { | |
cidr_blocks = ["${var.cidr_prefix}.0.0/16"] | |
from_port = "8300" | |
to_port = "8302" | |
protocol = "udp" | |
} | |
egress = { | |
cidr_blocks = ["0.0.0.0/0"] | |
from_port = "0" | |
to_port = "0" | |
protocol = "-1" | |
} | |
} | |
resource "aws_security_group" "nat" { | |
name = "nat" | |
description = "Allow services from the private subnet through NAT" | |
ingress { | |
from_port = 0 | |
to_port = 65535 | |
protocol = "tcp" | |
cidr_blocks = ["${aws_subnet.a_private.cidr_block}"] | |
} | |
ingress { | |
from_port = 0 | |
to_port = 65535 | |
protocol = "tcp" | |
cidr_blocks = ["${aws_subnet.b_private.cidr_block}"] | |
} | |
ingress { | |
from_port = 0 | |
to_port = 65535 | |
protocol = "tcp" | |
cidr_blocks = ["${aws_subnet.c_private.cidr_block}"] | |
} | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
} | |
# NAT instances | |
resource "aws_instance" "nat-1a" { | |
ami = "ami-6975eb1e" # amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2 | |
availability_zone = "eu-west-1a" | |
instance_type = "m4.xlarge" | |
key_name = "${var.aws_key_name}" | |
security_groups = ["${aws_security_group.nat.id}"] | |
subnet_id = "${aws_subnet.a_public.id}" | |
associate_public_ip_address = true | |
source_dest_check = false | |
} | |
resource "aws_eip" "nat-1a" { | |
instance = "${aws_instance.nat-1a.id}" | |
vpc = true | |
depends_on = ["aws_instance.nat-1a"] | |
} | |
resource "aws_cloudwatch_metric_alarm" "nat-1a_recover" { | |
alarm_name = "${var.region}-${var.vpc_name}-nat-1a-recover" | |
comparison_operator = "GreaterThanThreshold" | |
evaluation_periods = "1" | |
metric_name = "StatusCheckFailed_System" | |
namespace = "AWS/EC2" | |
period = "60" | |
statistic = "Minimum" | |
threshold = "0" | |
alarm_actions = [ "arn:aws:automate:${var.region}:ec2:recover" ] | |
dimensions = { | |
InstanceId = "${aws_instance.nat-1a.id}" | |
} | |
depends_on = ["aws_instance.nat-1a"] | |
} | |
resource "aws_instance" "nat-1b" { | |
ami = "ami-6975eb1e" # amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2 | |
availability_zone = "eu-west-1b" | |
instance_type = "m4.xlarge" | |
key_name = "${var.aws_key_name}" | |
security_groups = ["${aws_security_group.nat.id}"] | |
subnet_id = "${aws_subnet.b_public.id}" | |
associate_public_ip_address = true | |
source_dest_check = false | |
} | |
resource "aws_eip" "nat-1b" { | |
instance = "${aws_instance.nat-1b.id}" | |
vpc = true | |
depends_on = ["aws_instance.nat-1b"] | |
} | |
resource "aws_cloudwatch_metric_alarm" "nat-1b_recover" { | |
alarm_name = "${var.region}-${var.vpc_name}-nat-1b-recover" | |
comparison_operator = "GreaterThanThreshold" | |
evaluation_periods = "1" | |
metric_name = "StatusCheckFailed_System" | |
namespace = "AWS/EC2" | |
period = "60" | |
statistic = "Minimum" | |
threshold = "0" | |
alarm_actions = [ "arn:aws:automate:${var.region}:ec2:recover" ] | |
dimensions = { | |
InstanceId = "${aws_instance.nat-1b.id}" | |
} | |
depends_on = ["aws_instance.nat-1b"] | |
} | |
resource "aws_instance" "nat-1c" { | |
ami = "ami-6975eb1e" # amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2 | |
availability_zone = "eu-west-1c" | |
instance_type = "m4.xlarge" | |
key_name = "${var.aws_key_name}" | |
security_groups = ["${aws_security_group.nat.id}"] | |
subnet_id = "${aws_subnet.c_public.id}" | |
associate_public_ip_address = true | |
source_dest_check = false | |
} | |
resource "aws_eip" "nat-1c" { | |
instance = "${aws_instance.nat-1a.id}" | |
vpc = true | |
depends_on = ["aws_instance.nat-1c"] | |
} | |
resource "aws_cloudwatch_metric_alarm" "nat-1c_recover" { | |
alarm_name = "${var.region}-${var.vpc_name}-nat-1c-recover" | |
comparison_operator = "GreaterThanThreshold" | |
evaluation_periods = "1" | |
metric_name = "StatusCheckFailed_System" | |
namespace = "AWS/EC2" | |
period = "60" | |
statistic = "Minimum" | |
threshold = "0" | |
alarm_actions = [ "arn:aws:automate:${var.region}:ec2:recover" ] | |
dimensions = { | |
InstanceId = "${aws_instance.nat-1c.id}" | |
} | |
depends_on = ["aws_instance.nat-1c"] | |
} | |
################################### | |
# Routing tables for public subnets | |
################################### | |
resource "aws_route_table" "a_public" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
gateway_id = "${aws_internet_gateway.default.id}" | |
} | |
} | |
resource "aws_route_table" "b_public" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
gateway_id = "${aws_internet_gateway.default.id}" | |
} | |
} | |
resource "aws_route_table" "c_public" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
gateway_id = "${aws_internet_gateway.default.id}" | |
} | |
} | |
resource "aws_route_table_association" "a_public" { | |
subnet_id = "${aws_subnet.a_public.id}" | |
route_table_id = "${aws_route_table.a_public.id}" | |
} | |
resource "aws_route_table_association" "b_public" { | |
subnet_id = "${aws_subnet.b_public.id}" | |
route_table_id = "${aws_route_table.b_public.id}" | |
} | |
resource "aws_route_table_association" "c_public" { | |
subnet_id = "${aws_subnet.c_public.id}" | |
route_table_id = "${aws_route_table.c_public.id}" | |
} | |
#################################### | |
# Routing tables for private subnets | |
#################################### | |
resource "aws_route_table" "a_private" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
network_interface_id = "${aws_eip.nat-1a.network_interface}" | |
} | |
depends_on = ["aws_instance.nat-1a", "aws_eip.nat-1a"] | |
} | |
resource "aws_route_table" "b_private" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
network_interface_id = "${aws_eip.nat-1b.network_interface}" | |
} | |
depends_on = ["aws_instance.nat-1b", "aws_eip.nat-1b"] | |
} | |
resource "aws_route_table" "c_private" { | |
vpc_id = "${aws_vpc.this_vpc.id}" | |
route { | |
cidr_block = "0.0.0.0/0" | |
network_interface_id = "${aws_eip.nat-1c.network_interface}" | |
} | |
depends_on = ["aws_instance.nat-1c", "aws_eip.nat-1c"] | |
} | |
resource "aws_route_table_association" "a_private" { | |
subnet_id = "${aws_subnet.a_private.id}" | |
route_table_id = "${aws_route_table.a_private.id}" | |
} | |
resource "aws_route_table_association" "b_private" { | |
subnet_id = "${aws_subnet.b_private.id}" | |
route_table_id = "${aws_route_table.b_private.id}" | |
} | |
resource "aws_route_table_association" "c_private" { | |
subnet_id = "${aws_subnet.c_private.id}" | |
route_table_id = "${aws_route_table.c_private.id}" | |
} |
pll
commented
Oct 29, 2015
note the update (just now) for the correct Dimension for autorecovery alarms
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment