Last active
December 3, 2022 15:49
-
-
Save dahjohnson/05a5d4c9b63c559c8f6e8e90456f836c to your computer and use it in GitHub Desktop.
Deploy an Auto Scaling Group behind an Application Load Balancer and NAT Gateway using AWS CloudFormation
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
Description: This template deploys the following | |
- VPC with three separate private and public subnets spread across three Availability Zones | |
- Internet gateway with a default route on the public subnets | |
- NAT gateway in the public subnet of the first availability zone with a default route on the private subnets | |
- Security Group allowing HTTP inbound only from 0.0.0.0/0 | |
- EC2 Launch Template | |
- Auto Scaling Group using Launch Template | |
- Application Load Balancer | |
Parameters: | |
EnvironmentName: | |
Description: An environment name that is prefixed to resource names | |
Type: String | |
VpcCIDR: | |
Description: Please enter the IP range (CIDR notation) for this VPC | |
Type: String | |
Default: 10.10.0.0/16 | |
PrivateSubnet1CIDR: | |
Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone | |
Type: String | |
Default: 10.10.1.0/24 | |
PrivateSubnet2CIDR: | |
Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone | |
Type: String | |
Default: 10.10.2.0/24 | |
PrivateSubnet3CIDR: | |
Description: Please enter the IP range (CIDR notation) for the private subnet in the third Availability Zone | |
Type: String | |
Default: 10.10.3.0/24 | |
PublicSubnet1CIDR: | |
Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone | |
Type: String | |
Default: 10.10.10.0/24 | |
PublicSubnet2CIDR: | |
Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone | |
Type: String | |
Default: 10.10.20.0/24 | |
PublicSubnet3CIDR: | |
Description: Please enter the IP range (CIDR notation) for the public subnet in the third Availability Zone | |
Type: String | |
Default: 10.10.30.0/24 | |
Resources: | |
VPC: | |
Type: AWS::EC2::VPC | |
Properties: | |
CidrBlock: !Ref VpcCIDR | |
EnableDnsSupport: true | |
EnableDnsHostnames: true | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName}-VPC | |
InternetGateway: | |
Type: AWS::EC2::InternetGateway | |
DependsOn: VPC | |
Properties: | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName}-InternetGateway | |
InternetGatewayAttachment: | |
Type: AWS::EC2::VPCGatewayAttachment | |
DependsOn: InternetGateway | |
Properties: | |
InternetGatewayId: !Ref InternetGateway | |
VpcId: !Ref VPC | |
PrivateSubnet1: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 0, !GetAZs '' ] | |
CidrBlock: !Ref PrivateSubnet1CIDR | |
MapPublicIpOnLaunch: false | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Private Subnet (AZ1) | |
PrivateSubnet2: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 1, !GetAZs '' ] | |
CidrBlock: !Ref PrivateSubnet2CIDR | |
MapPublicIpOnLaunch: false | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Private Subnet (AZ2) | |
PrivateSubnet3: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 2, !GetAZs '' ] | |
CidrBlock: !Ref PrivateSubnet3CIDR | |
MapPublicIpOnLaunch: false | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Private Subnet (AZ3) | |
PublicSubnet1: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 0, !GetAZs '' ] | |
CidrBlock: !Ref PublicSubnet1CIDR | |
MapPublicIpOnLaunch: true | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Public Subnet (AZ1) | |
PublicSubnet2: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 1, !GetAZs '' ] | |
CidrBlock: !Ref PublicSubnet2CIDR | |
MapPublicIpOnLaunch: true | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Public Subnet (AZ2) | |
PublicSubnet3: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 2, !GetAZs '' ] | |
CidrBlock: !Ref PublicSubnet3CIDR | |
MapPublicIpOnLaunch: true | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName} Public Subnet (AZ3) | |
ElasticIP: | |
Type: AWS::EC2::EIP | |
Properties: | |
Domain: vpc | |
NatGateway: | |
Type: AWS::EC2::NatGateway | |
DependsOn: PublicSubnet1 | |
Properties: | |
ConnectivityType: public | |
AllocationId: !GetAtt ElasticIP.AllocationId | |
SubnetId: !GetAtt PublicSubnet1.SubnetId | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName}-NatGateway | |
PublicRouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref VPC | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName}-PublicRouteTable | |
PrivateRouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref VPC | |
Tags: | |
- Key: Name | |
Value: !Sub ${EnvironmentName}-PrivateRouteTable | |
DefaultPublicRoute: | |
Type: AWS::EC2::Route | |
DependsOn: InternetGatewayAttachment | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
DestinationCidrBlock: 0.0.0.0/0 | |
GatewayId: !Ref InternetGateway | |
PublicSubnet1RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPublicRoute | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
SubnetId: !Ref PublicSubnet1 | |
PublicSubnet2RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPublicRoute | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
SubnetId: !Ref PublicSubnet2 | |
PublicSubnet3RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPublicRoute | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
SubnetId: !Ref PublicSubnet3 | |
DefaultPrivateRoute: | |
Type: AWS::EC2::Route | |
DependsOn: NatGateway | |
Properties: | |
RouteTableId: !Ref PrivateRouteTable | |
DestinationCidrBlock: 0.0.0.0/0 | |
NatGatewayId: !Ref NatGateway | |
PrivateSubnet1RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPrivateRoute | |
Properties: | |
RouteTableId: !Ref PrivateRouteTable | |
SubnetId: !Ref PrivateSubnet1 | |
PrivateSubnet2RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPrivateRoute | |
Properties: | |
RouteTableId: !Ref PrivateRouteTable | |
SubnetId: !Ref PrivateSubnet2 | |
PrivateSubnet3RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
DependsOn: DefaultPrivateRoute | |
Properties: | |
RouteTableId: !Ref PrivateRouteTable | |
SubnetId: !Ref PrivateSubnet3 | |
HTTPIngressSecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
DependsOn: VPC | |
Properties: | |
GroupName: !Sub ${EnvironmentName}-SecurityGroup | |
GroupDescription: "Security group with HTTP ingress rule" | |
VpcId: !Ref VPC | |
HTTPIngressSecurityGroupRule: | |
Type: AWS::EC2::SecurityGroupIngress | |
DependsOn: HTTPIngressSecurityGroup | |
Properties: | |
CidrIp: 0.0.0.0/0 | |
Description: "Allow HTTP" | |
GroupId: !Ref HTTPIngressSecurityGroup | |
IpProtocol: tcp | |
FromPort: 80 | |
ToPort: 80 | |
myLaunchTemplate: | |
Type: AWS::EC2::LaunchTemplate | |
DependsOn: HTTPIngressSecurityGroup | |
Properties: | |
LaunchTemplateName: !Sub ${EnvironmentName}-LaunchTemplate | |
LaunchTemplateData: | |
ImageId: ami-0b0dcb5067f052a63 | |
InstanceType: t2.micro | |
NetworkInterfaces: | |
- DeviceIndex: 0 | |
AssociatePublicIpAddress: false | |
Groups: | |
- !Ref HTTPIngressSecurityGroup | |
UserData: | |
Fn::Base64: | |
!Sub | | |
#!/bin/bash | |
yum update -y | |
yum install -y httpd | |
systemctl start httpd | |
systemctl enable httpd | |
EC2AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone) | |
echo '<center><h1>This Amazon EC2 instance is located in Availability Zone: AZID </h1></center>' > /var/www/html/index.txt | |
sed "s/AZID/$EC2AZ/" /var/www/html/index.txt > /var/www/html/index.html | |
ApplicationLoadBalancer: | |
Type: AWS::ElasticLoadBalancingV2::LoadBalancer | |
DependsOn: InternetGatewayAttachment | |
Properties: | |
Name: !Sub ${EnvironmentName}-LoadBalancer | |
Type: application | |
IpAddressType: ipv4 | |
Scheme: internet-facing | |
SecurityGroups: | |
- !GetAtt HTTPIngressSecurityGroup.GroupId | |
Subnets: | |
- !Ref PublicSubnet1 | |
- !Ref PublicSubnet2 | |
- !Ref PublicSubnet3 | |
Tags: | |
- Key: Name | |
Value: !Ref EnvironmentName | |
TargetGroup: | |
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |
Properties: | |
Name: !Sub ${EnvironmentName}-TargetGroup | |
HealthCheckIntervalSeconds: 30 | |
HealthCheckPath: / | |
Port: 80 | |
Protocol: HTTP | |
HealthyThresholdCount: 5 | |
UnhealthyThresholdCount: 2 | |
TargetType: instance | |
Matcher: | |
HttpCode: "200" | |
VpcId: !Ref VPC | |
HTTPListener: | |
Type: AWS::ElasticLoadBalancingV2::Listener | |
DependsOn: TargetGroup | |
Properties: | |
LoadBalancerArn: !Ref ApplicationLoadBalancer | |
Port: 80 | |
Protocol: HTTP | |
DefaultActions: | |
- Type: forward | |
TargetGroupArn: !Ref TargetGroup | |
myAutoScalingGroup: | |
Type: AWS::AutoScaling::AutoScalingGroup | |
DependsOn: myLaunchTemplate | |
Properties: | |
AutoScalingGroupName: !Sub ${EnvironmentName}-AutoScaleGroup | |
DesiredCapacity: 2 | |
MinSize: 2 | |
MaxSize: 5 | |
LaunchTemplate: | |
LaunchTemplateId: !Ref myLaunchTemplate | |
Version: !GetAtt myLaunchTemplate.LatestVersionNumber | |
TargetGroupARNs: | |
- !Ref TargetGroup | |
VPCZoneIdentifier: | |
- !Ref PrivateSubnet1 | |
- !Ref PrivateSubnet2 | |
- !Ref PrivateSubnet3 | |
Outputs: | |
VPC: | |
Description: A reference to the created VPC | |
Value: !Ref VPC | |
PrivateSubnet1: | |
Description: A reference to the private subnet in the 1st Availability Zone | |
Value: !Ref PrivateSubnet1 | |
PrivateSubnet2: | |
Description: A reference to the private subnet in the 2nd Availability Zone | |
Value: !Ref PrivateSubnet2 | |
PrivateSubnet3: | |
Description: A reference to the private subnet in the 3rd Availability Zone | |
Value: !Ref PrivateSubnet3 | |
PublicSubnet1: | |
Description: A reference to the public subnet in the 1st Availability Zone | |
Value: !Ref PublicSubnet1 | |
PublicSubnet2: | |
Description: A reference to the public subnet in the 2nd Availability Zone | |
Value: !Ref PublicSubnet2 | |
PublicSubnet3: | |
Description: A reference to the public subnet in the 3rd Availability Zone | |
Value: !Ref PublicSubnet1 | |
HTTPIngressSecurityGroup: | |
Description: A reference to the Security Group allowing HTTP only inbound | |
Value: !Ref HTTPIngressSecurityGroup | |
myLaunchTemplate: | |
Description: A reference to the Launch Template | |
Value: !Ref myLaunchTemplate | |
myAutoScalingGroup: | |
Description: A reference to the Auto Scaling Group | |
Value: !Ref myAutoScalingGroup | |
ApplicationLoadBalancer: | |
Description: A reference to the Application Load Balancer | |
Value: !Ref ApplicationLoadBalancer | |
LoadBalancerURL: | |
Description: The URL of the Application Load Balancer | |
Value: !GetAtt ApplicationLoadBalancer.DNSName |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment