Last active
April 20, 2017 18:58
-
-
Save igorlg/af4d3ef48705c1919242 to your computer and use it in GitHub Desktop.
AWS CloudFormation VPC Templates
This file contains 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
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "Template for a VPC with High Availability NAT for ECS", | |
"Parameters": { | |
"NATInstanceType": { | |
"Description": "NAT instance type", | |
"Type": "String", | |
"Default": "t2.micro", | |
"AllowedValues": [ | |
"t2.micro", | |
"t2.small", | |
"m3.medium", | |
"m3.large", | |
"c3.large" | |
], | |
"ConstraintDescription": "must be a valid EC2 instance type." | |
}, | |
"NATInstanceKeyName": { | |
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the NAT instance", | |
"Type": "AWS::EC2::KeyPair::KeyName", | |
"ConstraintDescription": "must be the name of an existing EC2 KeyPair." | |
} | |
}, | |
"Mappings": { | |
"SubnetAZs": { | |
"us-east-1": { | |
"Net1": "us-east-1a", | |
"Net2": "us-east-1c", | |
"Net3": "us-east-1d" | |
}, | |
"us-west-2": { | |
"Net1": "us-west-2a", | |
"Net2": "us-west-2b", | |
"Net3": "us-west-2c" | |
}, | |
"eu-west-1": { | |
"Net1": "eu-west-1a", | |
"Net2": "eu-west-1b", | |
"Net3": "eu-west-1c" | |
}, | |
"sa-east-1": { | |
"Net1": "sa-east-1a", | |
"Net2": "sa-east-1b", | |
"Net3": "sa-east-1c" | |
} | |
}, | |
"CIDRs": { | |
"VPC": { "Value": "10.1.0.0/16" }, | |
"PubNet1": { "Value": "10.1.10.0/24" }, | |
"PubNet2": { "Value": "10.1.11.0/24" }, | |
"PubNet3": { "Value": "10.1.12.0/24" }, | |
"PrivNet1": { "Value": "10.1.20.0/24" }, | |
"PrivNet2": { "Value": "10.1.21.0/24" }, | |
"PrivNet3": { "Value": "10.1.22.0/24" } | |
}, | |
"NATInstanceAMI": { | |
"us-east-1": { | |
"AMI": "ami-184dc970" | |
}, | |
"us-west-2": { | |
"AMI": "ami-69ae8259" | |
}, | |
"eu-west-1": { | |
"AMI": "ami-6975eb1e" | |
}, | |
"sa-east-1": { | |
"AMI": "ami-fbfa41e6" | |
} | |
}, | |
"NATInstanceTimeouts": { | |
"NumberOfPings": { "Value": "3" }, | |
"PingTimeout": { "Value": "1" }, | |
"WaitBetweenPings": { "Value": "2" }, | |
"WaitForInstanceStop": { "Value": "60" }, | |
"WaitForInstanceStart": { "Value": "300" } | |
} | |
}, | |
"Resources": { | |
"VPC": { | |
"Type": "AWS::EC2::VPC", | |
"Properties": { | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "VPC", "Value" ] }, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"InternetGateway": { | |
"Type": "AWS::EC2::InternetGateway", | |
"Properties": { | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"IGW" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"AttachGateway": { | |
"Type": "AWS::EC2::VPCGatewayAttachment", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"InternetGatewayId": { | |
"Ref": "InternetGateway" | |
} | |
} | |
}, | |
"SubnetPublic1": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet1", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net1" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"1" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPublic2": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet2", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net2" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"2" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPublic3": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet3", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net3" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"3" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate1": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet1", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net1" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"1" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate2": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet2", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net2" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"2" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate3": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet3", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net3" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"3" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RouteTabPublic": { | |
"Type": "AWS::EC2::RouteTable", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"RouteTable", | |
"Public" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RouteTabPrivate1": { | |
"Type": "AWS::EC2::RouteTable", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"RouteTable", | |
"Private", | |
"1" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RouteTabPrivate2": { | |
"Type": "AWS::EC2::RouteTable", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"RouteTable", | |
"Private", | |
"2" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RoutePublic": { | |
"Type": "AWS::EC2::Route", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"GatewayId": { | |
"Ref": "InternetGateway" | |
}, | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
} | |
} | |
}, | |
"RoutePrivate1": { | |
"Type": "AWS::EC2::Route", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"InstanceId": { | |
"Ref": "NATInstance1" | |
}, | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate1" | |
} | |
} | |
}, | |
"RoutePrivate2": { | |
"Type": "AWS::EC2::Route", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"InstanceId": { | |
"Ref": "NATInstance2" | |
}, | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate2" | |
} | |
} | |
}, | |
"SubnetPublic1RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic1" | |
} | |
} | |
}, | |
"SubnetPublic2RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic2" | |
} | |
} | |
}, | |
"SubnetPublic3RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic3" | |
} | |
} | |
}, | |
"SubnetPrivate1RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate1" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate1" | |
} | |
} | |
}, | |
"SubnetPrivate2RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate2" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate2" | |
} | |
} | |
}, | |
"SubnetPrivate3RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate1" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate3" | |
} | |
} | |
}, | |
"NATSecurityGroup": { | |
"Type": "AWS::EC2::SecurityGroup", | |
"Properties": { | |
"GroupDescription": "Security Group for the NAT Instance", | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"SecurityGroupIngress": [ | |
{ | |
"CidrIp": { "Fn::FindInMap": [ "CIDRs", "VPC", "Value" ] }, | |
"IpProtocol": "-1", | |
"FromPort": "-1", | |
"ToPort": "-1" | |
} | |
], | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { "Fn::Join": [ "-", [ { "Ref": "AWS::StackName" }, "NAT", "SG" ] ] } | |
}, | |
{ | |
"Key": "Role", | |
"Value": "NAT" | |
} | |
] | |
} | |
}, | |
"IAMRoleNAT": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ { | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ "ec2.amazonaws.com" ] | |
}, | |
"Action": [ "sts:AssumeRole" ] | |
} ] | |
}, | |
"Path": "/", | |
"Policies": [ | |
{ | |
"PolicyName": {"Fn::Join": ["-", [ { "Ref": "AWS::StackName" }, "nat", "role" ] ] }, | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"ec2:DescribeInstances", | |
"ec2:DescribeRouteTables", | |
"ec2:CreateRoute", | |
"ec2:ReplaceRoute", | |
"ec2:StartInstances", | |
"ec2:StopInstances" | |
], | |
"Resource": "*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"IAMInstanceProfileNAT": { | |
"Type": "AWS::IAM::InstanceProfile", | |
"Properties": { | |
"Path": "/", | |
"Roles": [ { "Ref": "IAMRoleNAT" } ] | |
} | |
}, | |
"NATInstance1": { | |
"Type": "AWS::EC2::Instance", | |
"Properties": { | |
"InstanceType": { "Ref": "NATInstanceType" }, | |
"SourceDestCheck": "false", | |
"Monitoring": "true", | |
"KeyName": { "Ref": "NATInstanceKeyName" }, | |
"IamInstanceProfile" : { "Ref" : "IAMInstanceProfileNAT" }, | |
"ImageId": { "Fn::FindInMap": [ "NATInstanceAMI", { "Ref": "AWS::Region" }, "AMI" ] }, | |
"SecurityGroupIds": [ | |
{ | |
"Ref": "NATSecurityGroup" | |
} | |
], | |
"SubnetId": { | |
"Ref": "SubnetPublic1" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"NAT", | |
"1" | |
] | |
] | |
} | |
} | |
], | |
"UserData": { | |
"Fn::Base64": { | |
"Fn::Join": [ | |
"", | |
[ | |
"#!/bin/bash -v\n", | |
"yum update -y aws*\n", | |
". /etc/profile.d/aws-apitools-common.sh\n", | |
"/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE\n", | |
"/sbin/iptables-save > /etc/sysconfig/iptables\n", | |
"echo 1 > /proc/sys/net/ipv4/ip_forward && echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects\n", | |
"mkdir -p /etc/sysctl.d/\n", | |
"cat <<EOF > /etc/sysctl.d/nat.conf\n", | |
"net.ipv4.ip_forward = 1\n", | |
"net.ipv4.conf.eth0.send_redirects = 0\n", | |
"EOF\n", | |
"cd /root\n", | |
"wget http://media.amazonwebservices.com/articles/nat_monitor_files/nat_monitor.sh\n", | |
"NAT_ID=\n", | |
"while [ \"$NAT_ID\" == \"\" ]; do\n", | |
" sleep 60\n", | |
" NAT_ID=`/opt/aws/bin/ec2-describe-route-tables ", | |
{ "Ref": "RouteTabPrivate2" }, | |
" -U https://ec2.", | |
{ "Ref": "AWS::Region" }, | |
".amazonaws.com | grep 0.0.0.0/0 | awk '{print $2;}'`\n", | |
" #echo `date` \"-- NAT_ID=$NAT_ID\" >> /tmp/test.log\n", | |
"done\n", | |
"sed \"s/NAT_ID=/NAT_ID=$NAT_ID/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/NAT_RT_ID=/NAT_RT_ID=", | |
{ "Ref": "RouteTabPrivate2" }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/My_RT_ID=/My_RT_ID=", | |
{ "Ref": "RouteTabPrivate1" }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/EC2_URL=/EC2_URL=https:\\/\\/ec2.", | |
{ "Ref": "AWS::Region" }, | |
".amazonaws.com", | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Num_Pings=3/Num_Pings=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "NumberOfPings", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/Ping_Timeout=1/Ping_Timeout=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "PingTimeout", "Value" ] }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Wait_Between_Pings=2/Wait_Between_Pings=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitBetweenPings", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/Wait_for_Instance_Stop=60/Wait_for_Instance_Stop=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitForInstanceStop", "Value" ] }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Wait_for_Instance_Start=300/Wait_for_Instance_Start=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitForInstanceStart", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"mv /root/nat_monitor.tmp /root/nat_monitor.sh\n", | |
"chmod a+x /root/nat_monitor.sh\n", | |
"echo '@reboot /root/nat_monitor.sh > /tmp/nat_monitor.log' | crontab\n", | |
"/root/nat_monitor.sh > /tmp/nat_monitor.log &\n" | |
] | |
] | |
} | |
} | |
} | |
}, | |
"NATInstance2": { | |
"Type": "AWS::EC2::Instance", | |
"Properties": { | |
"InstanceType": { "Ref": "NATInstanceType" }, | |
"SourceDestCheck": "false", | |
"Monitoring": "true", | |
"KeyName": { "Ref": "NATInstanceKeyName" }, | |
"IamInstanceProfile" : { "Ref" : "IAMInstanceProfileNAT" }, | |
"ImageId": { | |
"Fn::FindInMap": [ | |
"NATInstanceAMI", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"AMI" | |
] | |
}, | |
"SecurityGroupIds": [ | |
{ | |
"Ref": "NATSecurityGroup" | |
} | |
], | |
"SubnetId": { | |
"Ref": "SubnetPublic2" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"NAT", | |
"2" | |
] | |
] | |
} | |
} | |
], | |
"UserData": { | |
"Fn::Base64": { | |
"Fn::Join": [ | |
"", | |
[ | |
"#!/bin/bash -v\n", | |
"yum update -y aws*\n", | |
"# Configure iptables\n", | |
"/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE\n", | |
"/sbin/iptables-save > /etc/sysconfig/iptables\n", | |
"# Configure ip forwarding and redirects\n", | |
"echo 1 > /proc/sys/net/ipv4/ip_forward && echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects\n", | |
"mkdir -p /etc/sysctl.d/\n", | |
"cat <<EOF > /etc/sysctl.d/nat.conf\n", | |
"net.ipv4.ip_forward = 1\n", | |
"net.ipv4.conf.eth0.send_redirects = 0\n", | |
"EOF\n", | |
"# Download nat_monitor.sh and configure\n", | |
"cd /root\n", | |
"wget http://media.amazonwebservices.com/articles/nat_monitor_files/nat_monitor.sh\n", | |
"# Update NAT_ID, NAT_RT_ID, and My_RT_ID\n", | |
"sed \"s/NAT_ID=/NAT_ID=", | |
{ "Ref": "NATInstance1" }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/NAT_RT_ID=/NAT_RT_ID=", | |
{ "Ref": "RouteTabPrivate1" }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/My_RT_ID=/My_RT_ID=", | |
{ "Ref": "RouteTabPrivate2" }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/EC2_URL=/EC2_URL=https:\\/\\/ec2.", | |
{ "Ref": "AWS::Region" }, | |
".amazonaws.com", | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Num_Pings=3/Num_Pings=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "NumberOfPings", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/Ping_Timeout=1/Ping_Timeout=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "PingTimeout", "Value" ] }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Wait_Between_Pings=2/Wait_Between_Pings=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitBetweenPings", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/Wait_for_Instance_Stop=60/Wait_for_Instance_Stop=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitForInstanceStop", "Value" ] }, | |
"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/Wait_for_Instance_Start=300/Wait_for_Instance_Start=", | |
{ "Fn::FindInMap": [ "NATInstanceTimeouts", "WaitForInstanceStart", "Value" ] }, | |
"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"mv /root/nat_monitor.tmp /root/nat_monitor.sh\n", | |
"chmod a+x /root/nat_monitor.sh\n", | |
"echo '@reboot /root/nat_monitor.sh > /tmp/nat_monitor.log' | crontab\n", | |
"/root/nat_monitor.sh >> /tmp/nat_monitor.log &\n" | |
] | |
] | |
} | |
} | |
} | |
}, | |
"NATInstance1EIP": { | |
"Type": "AWS::EC2::EIP", | |
"Properties" : { | |
"InstanceId" : { "Ref": "NATInstance1" }, | |
"Domain" : "vpc" | |
} | |
}, | |
"NATInstance2EIP": { | |
"Type": "AWS::EC2::EIP", | |
"Properties" : { | |
"InstanceId" : { "Ref": "NATInstance2" }, | |
"Domain" : "vpc" | |
} | |
} | |
}, | |
"Outputs": { | |
"VPC": { | |
"Description": "The VPC Id", | |
"Value": { | |
"Ref": "VPC" | |
} | |
}, | |
"NATInstances1IP": { | |
"Description": "The Elastic IP of NAT Instance #1", | |
"Value": { "Ref": "NATInstance1EIP" } | |
}, | |
"NATInstances2IP": { | |
"Description": "The Elastic IP of NAT Instance #2", | |
"Value": { "Ref": "NATInstance2EIP" } | |
} | |
} | |
} |
This file contains 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
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "Template for a VPC with 3 Public and 3 Private subnets and a NAT Instance", | |
"Parameters": { | |
"NATInstanceType": { | |
"Description": "NAT instance type", | |
"Type": "String", | |
"Default": "t2.micro", | |
"AllowedValues": [ | |
"t2.micro", | |
"t2.small", | |
"m3.medium", | |
"m3.large", | |
"c3.large" | |
], | |
"ConstraintDescription": "must be a valid EC2 instance type." | |
}, | |
"NATInstanceKeyName": { | |
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the NAT instance", | |
"Type": "AWS::EC2::KeyPair::KeyName", | |
"ConstraintDescription": "must be the name of an existing EC2 KeyPair." | |
} | |
}, | |
"Mappings": { | |
"SubnetAZs": { | |
"us-east-1": { | |
"Net1": "us-east-1a", | |
"Net2": "us-east-1c", | |
"Net3": "us-east-1d" | |
}, | |
"us-west-2": { | |
"Net1": "us-west-2a", | |
"Net2": "us-west-2b", | |
"Net3": "us-west-2c" | |
}, | |
"eu-west-1": { | |
"Net1": "eu-west-1a", | |
"Net2": "eu-west-1b", | |
"Net3": "eu-west-1c" | |
}, | |
"sa-east-1": { | |
"Net1": "sa-east-1a", | |
"Net2": "sa-east-1b", | |
"Net3": "sa-east-1c" | |
} | |
}, | |
"CIDRs": { | |
"VPC": { "Value": "10.1.0.0/16" }, | |
"PubNet1": { "Value": "10.1.10.0/24" }, | |
"PubNet2": { "Value": "10.1.11.0/24" }, | |
"PubNet3": { "Value": "10.1.12.0/24" }, | |
"PrivNet1": { "Value": "10.1.20.0/24" }, | |
"PrivNet2": { "Value": "10.1.21.0/24" }, | |
"PrivNet3": { "Value": "10.1.22.0/24" } | |
}, | |
"NATInstanceAMI": { | |
"us-east-1": { | |
"AMI": "ami-184dc970" | |
}, | |
"us-west-2": { | |
"AMI": "ami-69ae8259" | |
}, | |
"eu-west-1": { | |
"AMI": "ami-6975eb1e" | |
}, | |
"sa-east-1": { | |
"AMI": "ami-fbfa41e6" | |
} | |
} | |
}, | |
"Resources": { | |
"VPC": { | |
"Type": "AWS::EC2::VPC", | |
"Properties": { | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "VPC", "Value" ] }, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"InternetGateway": { | |
"Type": "AWS::EC2::InternetGateway", | |
"Properties": { | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"IGW" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"AttachGateway": { | |
"Type": "AWS::EC2::VPCGatewayAttachment", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"InternetGatewayId": { | |
"Ref": "InternetGateway" | |
} | |
} | |
}, | |
"SubnetPublic1": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet1", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net1" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"1" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPublic2": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet2", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net2" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"2" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPublic3": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PubNet3", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net3" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PublicNet", | |
"3" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate1": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet1", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net1" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"1" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate2": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet2", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net2" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"2" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"SubnetPrivate3": { | |
"Type": "AWS::EC2::Subnet", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"CidrBlock": { "Fn::FindInMap": [ "CIDRs", "PrivNet3", "Value" ] }, | |
"AvailabilityZone": { | |
"Fn::FindInMap": [ | |
"SubnetAZs", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Net3" | |
] | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"PrivateNet", | |
"3" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RouteTabPublic": { | |
"Type": "AWS::EC2::RouteTable", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"RouteTable", | |
"Public" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RouteTabPrivate": { | |
"Type": "AWS::EC2::RouteTable", | |
"Properties": { | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"RouteTable", | |
"Private" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RoutePublic": { | |
"Type": "AWS::EC2::Route", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"GatewayId": { | |
"Ref": "InternetGateway" | |
}, | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
} | |
} | |
}, | |
"RoutePrivate": { | |
"Type": "AWS::EC2::Route", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"InstanceId": { | |
"Ref": "NATInstance" | |
}, | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate" | |
} | |
} | |
}, | |
"SubnetPublic1RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic1" | |
} | |
} | |
}, | |
"SubnetPublic2RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic2" | |
} | |
} | |
}, | |
"SubnetPublic3RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPublic" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPublic3" | |
} | |
} | |
}, | |
"SubnetPrivate1RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate1" | |
} | |
} | |
}, | |
"SubnetPrivate2RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate2" | |
} | |
} | |
}, | |
"SubnetPrivate3RouteTable": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties": { | |
"RouteTableId": { | |
"Ref": "RouteTabPrivate" | |
}, | |
"SubnetId": { | |
"Ref": "SubnetPrivate3" | |
} | |
} | |
}, | |
"NATSecurityGroup": { | |
"Type": "AWS::EC2::SecurityGroup", | |
"Properties": { | |
"GroupDescription": "Security Group for the NAT Instance", | |
"VpcId": { | |
"Ref": "VPC" | |
}, | |
"SecurityGroupIngress": [ | |
{ | |
"CidrIp": { "Fn::FindInMap": [ "CIDRs", "VPC", "Value" ] }, | |
"IpProtocol": "-1", | |
"FromPort": "-1", | |
"ToPort": "-1" | |
} | |
], | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"NAT", | |
"SG" | |
] | |
] | |
} | |
}, | |
{ | |
"Key": "Role", | |
"Value": "NAT" | |
} | |
] | |
} | |
}, | |
"IAMRoleNAT": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ | |
"ec2.amazonaws.com" | |
] | |
}, | |
"Action": [ | |
"sts:AssumeRole" | |
] | |
} | |
] | |
}, | |
"Path": "/", | |
"Policies": [ | |
{ | |
"PolicyName": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"nat", | |
"role" | |
] | |
] | |
}, | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"ec2:DescribeInstances", | |
"ec2:DescribeRouteTables", | |
"ec2:CreateRoute", | |
"ec2:ReplaceRoute", | |
"ec2:StartInstances", | |
"ec2:StopInstances" | |
], | |
"Resource": "*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"IAMInstanceProfileNAT": { | |
"Type": "AWS::IAM::InstanceProfile", | |
"Properties": { | |
"Path": "/", | |
"Roles": [ | |
{ | |
"Ref": "IAMRoleNAT" | |
} | |
] | |
} | |
}, | |
"NATInstance": { | |
"Type": "AWS::EC2::Instance", | |
"Properties": { | |
"InstanceType": { | |
"Ref": "NATInstanceType" | |
}, | |
"SourceDestCheck": "false", | |
"Monitoring": "true", | |
"KeyName": { | |
"Ref": "NATInstanceKeyName" | |
}, | |
"IamInstanceProfile": { | |
"Ref": "IAMInstanceProfileNAT" | |
}, | |
"ImageId": { | |
"Fn::FindInMap": [ | |
"NATInstanceAMI", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"AMI" | |
] | |
}, | |
"SecurityGroupIds": [ | |
{ | |
"Ref": "NATSecurityGroup" | |
} | |
], | |
"SubnetId": { | |
"Ref": "SubnetPublic1" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"NAT" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
"NATInstanceEIP": { | |
"Type": "AWS::EC2::EIP", | |
"Properties": { | |
"InstanceId": { | |
"Ref": "NATInstance" | |
}, | |
"Domain": "vpc" | |
} | |
} | |
}, | |
"Outputs": { | |
"VPC": { | |
"Description": "The VPC Id", | |
"Value": { | |
"Ref": "VPC" | |
} | |
}, | |
"NATInstanceIP": { | |
"Description": "The NAT Instance EIP", | |
"Value": { | |
"Ref": "NATInstanceEIP" | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
PLEASE FEEL FREE TO SUGGEST CHANGES OR IMPROVEMENTS
Or, if you need any help, you can reach me on Twitter at @igorlgentil.
I've seen this before, more of the same?
Pretty much, yeah. The difference being I have a little bit of OCD and like things with organized names, tags, etc...
Please explain...
I've created these templates for a VPC with Public and Private Subnets and a NAT instance(s).
The first template assumes a single NAT instance, whereas the second assumes two with Failover capability.
These templates have been tested on the following AWS regions:
NAT Instance AMI
I used the latest (as of June 10th 2015) official NAT AMI provided by AWS: amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2. It uses EBS GP2 as the root volume (size ~8Gb).
The AMI ID on each region is:
Why is my region not supported?
Basically, I wanted a minimum of 3 AZs on the VPC. If you want to use these templates on a region with less than 3 AZs, feel free to edit it. It's pretty self-explanatory.
Further read
If you got this far, you probably don't need to read this, but anyways... http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html