Last active
October 22, 2015 22:43
-
-
Save rafaelfelix/4453f041f5d96ef0ecfd to your computer and use it in GitHub Desktop.
Deploy 2 NAT instances using the nat_monitor.sh created by Steve Morad (AWS) inside an existing VPC. Based on the original version nat_monitor_demo.template - http://stevemorad.s3.amazonaws.com/reInvent/demos/nat_template.htm
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" : "Deploy 2 NAT instances using the nat_monitor.sh created by Steve Morad (AWS) inside an existing VPC. Based on the original version nat_monitor_demo.template - http://stevemorad.s3.amazonaws.com/reInvent/demos/nat_template.htm", | |
"Parameters" : { | |
"KeyName" : { | |
"Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", | |
"Type" : "AWS::EC2::KeyPair::KeyName" | |
}, | |
"VpcId" : { | |
"Description" : "VpcId of the VPC where NAT instances will be deployed.", | |
"Type" : "AWS::EC2::VPC::Id" | |
}, | |
"ActivePublicSubnetId" : { | |
"Description" : "SubnetId of the public subnet where the Active NAT instance will be deployed.", | |
"Type" : "AWS::EC2::Subnet::Id" | |
}, | |
"StandbyPublicSubnetId" : { | |
"Description" : "SubnetId of the public subnet where the Standby NAT instance will be deployed (pick one in a different AZ than the Active).", | |
"Type" : "AWS::EC2::Subnet::Id" | |
}, | |
"ActiveNATInstanceElasticIPAllocationId" : { | |
"Description" : "AllocationId of the existing EIP to attach to the Active NAT instance.", | |
"Type" : "String" | |
}, | |
"StandbyNATInstanceElasticIPAllocationId" : { | |
"Description" : "AllocationId of the existing EIP to attach to the Standby NAT instance.", | |
"Type" : "String" | |
}, | |
"ActivePrivateRouteTableId" : { | |
"Description" : "Id of the private route table with 0.0.0.0/0 route going through the Active NAT Instance.", | |
"Type" : "String" | |
}, | |
"StandbyPrivateRouteTableId" : { | |
"Description" : "Id of the private route table with 0.0.0.0/0 route going through the Standby NAT Instance.", | |
"Type" : "String" | |
}, | |
"NATSecurityGroupId": { | |
"Description": "Security group ID to attach to the NAT Nodes.", | |
"Type": "AWS::EC2::SecurityGroup::Id" | |
}, | |
"NATNodeInstanceType" : { | |
"Description" : "Instance type for NAT nodes.", | |
"Type" : "String", | |
"Default" : "t2.small", | |
"AllowedValues" : [ "t2.micro","t2.small","t2.medium","t2.large","m3.medium","m4.xlarge","c4.xlarge","c3.8xlarge"], | |
"ConstraintDescription" : "must be a valid EC2 instance type." | |
} | |
}, | |
"Mappings" : { | |
"AWSNATAMI" : { | |
"us-east-1" : { "AMI" : "ami-b0210ed8" }, | |
"us-west-2" : { "AMI" : "ami-75ae8245" }, | |
"us-west-1" : { "AMI" : "ami-ada746e9" }, | |
"eu-west-1" : { "AMI" : "ami-ef76e898" }, | |
"eu-central-1" : { "AMI" : "ami-1e073a03" }, | |
"ap-southeast-1" : { "AMI" : "ami-1a9dac48" }, | |
"ap-southeast-2" : { "AMI" : "ami-43ee9e79" }, | |
"ap-northeast-1" : { "AMI" : "ami-11dc2a11" }, | |
"sa-east-1" : { "AMI" : "ami-63fa417e" } | |
} | |
}, | |
"Resources" : { | |
"NATRole": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ { | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ "ec2.amazonaws.com" ] | |
}, | |
"Action": [ "sts:AssumeRole" ] | |
} ] | |
}, | |
"Path": "/", | |
"Policies": [ { | |
"PolicyName": "NAT_Takeover", | |
"PolicyDocument": { | |
"Statement": [ { | |
"Effect": "Allow", | |
"Action": [ | |
"ec2:DescribeInstances", | |
"ec2:DescribeRouteTables", | |
"ec2:CreateRoute", | |
"ec2:ReplaceRoute", | |
"ec2:StartInstances", | |
"ec2:StopInstances" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} ] | |
} | |
} ] | |
} | |
}, | |
"NATRoleProfile": { | |
"Type": "AWS::IAM::InstanceProfile", | |
"Properties": { | |
"Path": "/", | |
"Roles": [ { | |
"Ref": "NATRole" | |
} ] | |
} | |
}, | |
"PrivateRouteActiveNAT" : { | |
"Type" : "AWS::EC2::Route", | |
"Properties" : { | |
"RouteTableId" : { "Ref" : "ActivePrivateRouteTableId" }, | |
"DestinationCidrBlock" : "0.0.0.0/0", | |
"InstanceId" : { "Ref" : "NAT1Instance" } | |
} | |
}, | |
"PrivateRouteStandbyNAT" : { | |
"Type" : "AWS::EC2::Route", | |
"Properties" : { | |
"RouteTableId" : { "Ref" : "StandbyPrivateRouteTableId" }, | |
"DestinationCidrBlock" : "0.0.0.0/0", | |
"InstanceId" : { "Ref" : "NAT2Instance" } | |
} | |
}, | |
"NAT1EIPAssoc" : { | |
"Type" : "AWS::EC2::EIPAssociation", | |
"Properties" : { | |
"InstanceId" : { "Ref" : "NAT1Instance" }, | |
"AllocationId" : { "Ref" : "ActiveNATInstanceElasticIPAllocationId" } | |
} | |
}, | |
"NAT2EIPAssoc" : { | |
"Type" : "AWS::EC2::EIPAssociation", | |
"Properties" : { | |
"InstanceId" : { "Ref" : "NAT2Instance" }, | |
"AllocationId" : { "Ref" : "StandbyNATInstanceElasticIPAllocationId" } | |
} | |
}, | |
"NAT1Instance" : { | |
"Type" : "AWS::EC2::Instance", | |
"Metadata" : { | |
"Comment1" : "Create NAT #1" | |
}, | |
"Properties" : { | |
"InstanceType" : { "Ref" : "NATNodeInstanceType" }, | |
"KeyName" : { "Ref" : "KeyName" }, | |
"IamInstanceProfile" : { "Ref" : "NATRoleProfile" }, | |
"SubnetId" : { "Ref" : "ActivePublicSubnetId" }, | |
"SourceDestCheck" : "false", | |
"ImageId" : { "Fn::FindInMap" : [ "AWSNATAMI", { "Ref" : "AWS::Region" }, "AMI" ]}, | |
"SecurityGroupIds" : [{ "Ref" : "NATSecurityGroupId" }], | |
"Tags" : [ | |
{ "Key" : "Name", "Value" : "NAT-Active" } | |
], | |
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ | |
"#!/bin/bash -v\n", | |
"set -x\n", | |
"yum update -y aws*\n", | |
"yum install -y jq\n", | |
". /etc/profile.d/aws-apitools-common.sh\n", | |
"# Download nat_monitor.sh and configure\n", | |
"cd /root\n", | |
"wget https://gist.githubusercontent.com/rafaelfelix/5e170b3b732d0b595993/raw/7c2b53f7041f58c628fee9a89cf8a089ca77c451/nat_monitor.sh -O nat_monitor.sh\n", | |
"# Wait for NAT-Standby to boot up and update StandbyPrivateRouteTableId\n", | |
"sleep 180\n", | |
"NAT_ID=\n", | |
"# CloudFormation should have updated the StandbyPrivateRouteTableId by now (due to yum update), however loop to make sure\n", | |
"while [ \"$NAT_ID\" == \"\" ]; do\n", | |
" sleep 60\n", | |
" NAT_ID=`/usr/bin/aws ec2 describe-route-tables --route-table-ids ",{ "Ref" : "StandbyPrivateRouteTableId" }," --region ", { "Ref" : "AWS::Region" }, " | jq '.RouteTables[]|.Routes[]|select(.DestinationCidrBlock == \"0.0.0.0/0\").InstanceId' | tr -d '\"'`\n", | |
"done\n", | |
"# Update NAT_ID, NAT_RT_ID, and My_RT_ID\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" : "StandbyPrivateRouteTableId" },"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/My_RT_ID=/My_RT_ID=",{ "Ref" : "ActivePrivateRouteTableId" },"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/REGION=/REGION=",{ "Ref" : "AWS::Region" },"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"rm -f /root/nat_monitor.tmp\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" | |
]]}} | |
} | |
}, | |
"NAT1InstanceAutoRecoverAlarm": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Properties": { | |
"AlarmDescription": "Trigger a recovery when instance status check fails for 2 consecutive minutes.", | |
"Namespace": "AWS/EC2" , | |
"MetricName": "StatusCheckFailed_System", | |
"Statistic": "Minimum", | |
"Period": "60", | |
"EvaluationPeriods": "2", | |
"ComparisonOperator": "GreaterThanThreshold", | |
"Threshold": "0", | |
"AlarmActions": [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ], | |
"Dimensions": [{"Name": "InstanceId","Value": {"Ref": "NAT1Instance"}}] | |
} | |
}, | |
"NAT2Instance" : { | |
"Type" : "AWS::EC2::Instance", | |
"Metadata" : { | |
"Comment1" : "Create NAT #2" | |
}, | |
"Properties" : { | |
"InstanceType" : { "Ref" : "NATNodeInstanceType" } , | |
"KeyName" : { "Ref" : "KeyName" }, | |
"IamInstanceProfile" : { "Ref" : "NATRoleProfile" }, | |
"SubnetId" : { "Ref" : "StandbyPublicSubnetId" }, | |
"SourceDestCheck" : "false", | |
"ImageId" : { "Fn::FindInMap" : [ "AWSNATAMI", { "Ref" : "AWS::Region" }, "AMI" ]}, | |
"SecurityGroupIds" : [{ "Ref" : "NATSecurityGroupId" }], | |
"Tags" : [ | |
{ "Key" : "Name", "Value" : "NAT-Standby" } | |
], | |
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ | |
"#!/bin/bash -v\n", | |
"set -x\n", | |
"yum update -y aws*\n", | |
"yum install -y jq\n", | |
"# Download nat_monitor.sh and configure\n", | |
"cd /root\n", | |
"wget https://gist.githubusercontent.com/rafaelfelix/5e170b3b732d0b595993/raw/7c2b53f7041f58c628fee9a89cf8a089ca77c451/nat_monitor.sh -O nat_monitor.sh\n", | |
"# Update NAT_ID, NAT_RT_ID, and My_RT_ID\n", | |
"sed \"s/NAT_ID=/NAT_ID=",{ "Ref" : "NAT1Instance" },"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/NATT_RT_ID=/NAT_RT_ID=",{ "Ref" : "ActivePrivateRouteTableId" },"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"sed \"s/My_RT_ID=/My_RT_ID=",{ "Ref" : "StandbyPrivateRouteTableId" },"/g\" /root/nat_monitor.sh > /root/nat_monitor.tmp\n", | |
"sed \"s/REGION=/REGION=",{ "Ref" : "AWS::Region" },"/g\" /root/nat_monitor.tmp > /root/nat_monitor.sh\n", | |
"rm -f /root/nat_monitor.tmp\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" | |
]]}} | |
} | |
}, | |
"NAT2InstanceAutoRecoverAlarm": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Properties": { | |
"AlarmDescription": "Trigger a recovery when instance status check fails for 2 consecutive minutes.", | |
"Namespace": "AWS/EC2" , | |
"MetricName": "StatusCheckFailed_System", | |
"Statistic": "Minimum", | |
"Period": "60", | |
"EvaluationPeriods": "2", | |
"ComparisonOperator": "GreaterThanThreshold", | |
"Threshold": "0", | |
"AlarmActions": [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]}, { "Ref" : "logical name of an AWS::SNS::Topic resource" } ], | |
"Dimensions": [{"Name": "InstanceId","Value": {"Ref": "NAT2Instance"}}] | |
} | |
}, | |
"NATAllowICMP" : { | |
"Type" : "AWS::EC2::SecurityGroupIngress", | |
"Properties" : { | |
"GroupId" : { "Ref" : "NATSecurityGroupId" }, | |
"IpProtocol" : "icmp", | |
"FromPort" : "-1", | |
"ToPort" : "-1", | |
"SourceSecurityGroupId" : { "Ref" : "NATSecurityGroupId" } | |
} | |
} | |
}, | |
"Outputs" : { | |
"NAT1" : { | |
"Description" : "NAT #1.", | |
"Value" : { "Ref" : "NAT1Instance" } | |
}, | |
"NAT2" : { | |
"Description" : "NAT #2.", | |
"Value" : { "Ref" : "NAT2Instance" } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment