Please consider this scenario:
I want to deploy a CloudFormation stack with the basic required resources for an Elastic Load Balancer to route traffic to the EC2.
I have stripped bellow template from a template that has a VPC, InternetGateway, VPCGatewayAttachment, RouteTable, Route, SubnetRouteTableAssociation, attached to it.
I did so because I thought AWS will provision a default VPC for me.
Mappings:
NetworkToSubnet:
"10.0.0.0":
PubSubnetZoneA: "10.0.10.0/24"
PrivSubnetZoneA: "10.0.20.0/24"
PubSubnetZoneB: "10.0.30.0/24"
PrivSubnetZoneB: "10.0.40.0/24"
Resources:
# Internet accessable subnet in the first availability zone
PubSubnetZoneA:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone:
Fn::Select:
- '0'
- Fn::GetAZs:
Ref: 'AWS::Region'
CidrBlock:
Fn::FindInMap:
- NetworkToSubnet
- '10.0.0.0'
- PubSubnetZoneA
MapPublicIpOnLaunch: 'True'
Tags:
- Key: 'Name'
Value:
'Fn::Join': [ ':', [ 'Public', 'Zone A', !Ref 'AWS::StackName' ] ]
# Non-internet accessable subnet in the first availability zone
PrivSubnetZoneA:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone:
Fn::Select:
- '0'
- Fn::GetAZs:
Ref: 'AWS::Region'
CidrBlock:
Fn::FindInMap:
- NetworkToSubnet
- '10.0.0.0'
- PrivSubnetZoneA
MapPublicIpOnLaunch: 'False'
Tags:
- Key: 'Name'
Value:
'Fn::Join': [ ':', [ 'Private', 'Zone A', !Ref 'AWS::StackName' ] ]
# Internet accessable subnet in the second availability zone
PubSubnetZoneB:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone:
Fn::Select:
- '1'
- Fn::GetAZs:
Ref: 'AWS::Region'
CidrBlock:
Fn::FindInMap:
- NetworkToSubnet
- '10.0.0.0'
- PubSubnetZoneB
MapPublicIpOnLaunch: 'True'
Tags:
- Key: 'Name'
Value:
'Fn::Join': [ ':', [ 'Public', 'Zone B', !Ref 'AWS::StackName' ] ]
# Non-internet accessable subnet in the second availability zone
PrivSubnetZoneB:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone:
Fn::Select:
- '1'
- Fn::GetAZs:
Ref: 'AWS::Region'
CidrBlock:
Fn::FindInMap:
- NetworkToSubnet
- '10.0.0.0'
- PrivSubnetZoneB
MapPublicIpOnLaunch: 'False'
Tags:
- Key: 'Name'
Value:
'Fn::Join': [ ':', [ 'Private', 'Zone B', !Ref 'AWS::StackName' ] ]
# EC2 Security Group Allowing Port 22 and 80 from anywhere
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'SSH and Port 80'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Ref: ELBSecurityGroup
# ELB Security Group allowing Port 80 from anywhere
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'SSH and Port 80'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
# Linux Instance with Apache running on Port 80
AmazonLinuxInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0ffd774e02309201f
InstanceInitiatedShutdownBehavior: stop
InstanceType: t2.nano
Monitoring: 'true'
NetworkInterfaces:
- AssociatePublicIpAddress: 'true'
DeviceIndex: '0'
GroupSet:
- !Ref EC2SecurityGroup
Tenancy: default
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
cd /tmp
yum update -y
yum install -y httpd24
echo "Healthy" > /var/www/html/index.html
service httpd start
/opt/aws/bin/cfn-signal \
-e $? \
--stack ${AWS::StackName} \
--resource AmazonLinuxInstance \
--region ${AWS::Region}
# Target Group
EC2TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 15
HealthyThresholdCount: 5
Matcher:
HttpCode: '200'
Name: EC2TargetGroup
Port: 80
Protocol: HTTP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: '20'
Targets:
- Id:
Ref: AmazonLinuxInstance
Port: 80
UnhealthyThresholdCount: 3
Tags:
- Key: Name
Value: EC2TargetGroup
- Key: Port
Value: 80
#ELB (ALB)
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn:
Ref: EC2TargetGroup
LoadBalancerArn:
Ref: ApplicationLoadBalancer
Port: 80
Protocol: HTTP
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing # or internal
Outputs:
ALBHostName:
Description: 'Application Load Balancer Hostname'
Value:
!GetAtt ApplicationLoadBalancer.DNSName
EC2Instance:
Description: 'EC2 Instance'
Value:
Ref: AmazonLinuxInstance
EC2TargetGroup:
Description: 'EC2 Target Group'
Value:
Ref: EC2TargetGroup
ApplicationLoadBalancer:
Description: 'Application Load Balancer'
Value:
Ref: ApplicationLoadBalancer
When provisioning the stack provided I get the following errors:
The following resource(s) failed to create: [PubSubnetZoneB, PrivSubnetZoneA,
PrivSubnetZoneB, ApplicationLoadBalancer, ELBSecurityGroup, PubSubnetZoneA]. Rollback
requested by user.
At least two subnets in two different Availability Zones must be specified (Service:
AmazonElasticLoadBalancing; Status Code: 400; Error Code: ValidationError; Request ID: 000-
0000-0000-0000-0000; Proxy: null)
What are the minimum required resources for an ELB to have, so it can direct traffic to an EC2?
The error is saying At least two subnets in two different Availability Zones must be specified.
From AWS::ElasticLoadBalancingV2::LoadBalancer - AWS CloudFormation:
Subnets
The IDs of the subnets. You can specify only one subnet per Availability Zone. You must specify either subnets or subnet mappings.
[Application Load Balancers] You must specify subnets from at least two Availability Zones. When you specify subnets for an existing Application Load Balancer, they replace the previously enabled subnets.
Thus, you need to add Subnets to your Load Balancer definition. It must be at least two subnets, each in different Availability Zones.
Related
i am pretty new to CloudFormation templates. I have already created a VPC with 2 public and 4 private subnets. Now, i want to create an EC2 instance in 2 of the private subnets, which is then load balanced using ELB created on a public subnet. Below is the CFT template for the same.
Parameters:
SecurityGroupDescription:
Description: Security Group Description
Type: String
KeyName:
Description: Key Pair for EC2
Type: 'AWS::EC2::KeyPair::KeyName'
VPC:
Description: Select VPC.
Type: AWS::EC2::VPC::Id
Subnet1:
Description: Private Subnet to Deploy Docker MFA.
Type: AWS::EC2::Subnet::Id
Subnet2:
Description: Private Subnet to Deploy Docker MFA.
Type: AWS::EC2::Subnet::Id
Mappings:
RegionMap:
us-west-2:
AMI: ami-0c54e4ec017b92f04
Resources:
EC2InstanceMule1:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId:
Fn::FindInMap:
- RegionMap
- Ref: AWS::Region
- AMI
SubnetId:
Ref: Subnet1
SecurityGroups:
- !GetAtt EC2SecurityGroup.GroupId
KeyName: !Ref KeyName
EC2InstanceMule2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId:
Fn::FindInMap:
- RegionMap
- Ref: AWS::Region
- AMI
SubnetId:
Ref: Subnet2
SecurityGroups:
- !GetAtt EC2SecurityGroup.GroupId
KeyName: !Ref KeyName
# security group
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ELB Security Group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Ref SecurityGroupDescription
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Fn::GetAtt:
- ELBSecurityGroup
- GroupId
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
# Load Balancer for EC2
LoadBalancerforEC2:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Instances:
- !Ref EC2InstanceMule1
- !Ref EC2InstanceMule2
Listeners:
- LoadBalancerPort: '80'
InstancePort: '80'
Protocol: HTTP
HealthCheck:
Target: HTTP:80/
HealthyThreshold: '3'
UnhealthyThreshold: '5'
Interval: '30'
Timeout: '5'
SecurityGroups:
- !GetAtt ELBSecurityGroup.GroupId
I am getting the following error :
The parameter groupName cannot be used with the parameter subnet (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterCombination
I have gone through the previous question of the same error and used the security group ID that is being created. Still the error persists. Also, any other modifications required would be appreciated.
You should be using SecurityGroupIds, rather then SecurityGroups.
I have 2 EC2 instances in 2 public subnets. The EC2 instances are fronted my an Application Load Balancer in the same public subnet as the EC2 instances. The Security groups for the EC2's is set to only accept tcp traffic from the security group the load balancer is in.
I am getting a 502 when I hit the Application Load Balancers endpoint.
I am deploying using CloudFormation. Here is the relevant bit of code.
AWSTemplateFormatVersion: "2010-09-09"
Description: Deploy a 3-tier wordpress system. (Plublic and Private subnets and DB on RDS)
Parameters:
VpcId:
Description: VPC id
Type: String
Default: vpc-0b6a616f830dd7d5a
PublicSubnetA:
Description: Subnet Id where instance will create
Type: String
Default: subnet-0616a6183bee2b276
PrivateSubnetA:
Description: Subnet Id where instance will create
Type: String
Default: subnet-06784a19612a64444
PublicSubnetB:
Description: Subnet Id where instance will create
Type: String
Default: subnet-04f7e39ac1431f22a
PrivateSubnetB:
Description: Subnet Id where instance will create
Type: String
Default: subnet-0fa6aa79eaee582bf
EC2KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
Default: test
ConstraintDescription: must be the name of an existing EC2 KeyPair.
EC2InstanceType:
Description: EC2 instance type
Type: String
Default: t2.micro
ConstraintDescription: must be a valid EC2 instance type.
WebServerInstanceAMI:
Description: EC2 instance type
Type: AWS::EC2::Image::Id
Default: ami-0210560cedcb09f07
ConstraintDescription: must be an existing AMI ID.
SSHLocation:
Description: The IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: 9
MaxLength: 18
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
Application:
Description: Application Name
Type: String
AllowedPattern: "[A-Za-z0-9-]+"
Default: test
Environment:
AllowedValues: [preprod,prod]
Default: preprod
Description: The name of the Environment
Type: String
Resources:
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: ELB Security Group
SecurityGroupIngress:
- FromPort: 80
IpProtocol: tcp
CidrIp: 0.0.0.0/0
ToPort: 80
Description: Allow from internet
Tags:
- Key: Name
Value: !Sub '${Application}-loadbalancer-sg'
- Key: Project
Value: !Ref Application
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'SSH and Port 80'
VpcId:
Ref: VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref 'SSHLocation'
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Ref: LoadBalancerSecurityGroup
Tags:
- Key: Name
Value: !Sub '${Application}-webserver-sg'
- Key: Project
Value: !Ref Application
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: ApplicationLoadBalancer
Scheme: internet-facing
Subnets:
- !Ref PublicSubnetA
- !Ref PublicSubnetB
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ApplicationTargetGroup
ApplicationTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 15
HealthyThresholdCount: 3
UnhealthyThresholdCount: 3
HealthCheckPath: /index.html
Matcher:
HttpCode: '200'
Name: ApplicationTargetGroup
VpcId: !Ref VpcId
Port: 80
Protocol: HTTP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: '20'
Targets:
- Id: !Ref WebServerInstance1
Port: 80
- Id: !Ref WebServerInstance2
Port: 80
WebServerInstance1:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
SubnetId: !Ref PublicSubnetA
SecurityGroupIds:
- !Ref WebServerSecurityGroup
ImageId: !Ref WebServerInstanceAMI
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
cd /tmp
sudo yum update -y
sudo yum install -y httpd
echo "Welcome from the instance 1" > /var/www/html/index.html
sudo -u root service httpd start
WebServerInstance2:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
SubnetId: !Ref PublicSubnetB
SecurityGroupIds:
- !Ref WebServerSecurityGroup
ImageId: !Ref WebServerInstanceAMI
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
cd /tmp
sudo yum update -y
sudo yum install -y httpd
echo "Welcome from the instance 2" > /var/www/html/index.html
sudo -u root service httpd start
Outputs:
LoadBalancerDnsName:
Description: Load Balancer public facing DNS
Export:
Name: !Sub ${AWS::StackName}-LoadBaancer
Value: !GetAtt LoadBalancer.DNSName
I have a look at the resources deployed in the console UI and I can see the correct security group rules on the EC2 instances. I don't see when the ALB would have trouble sending messages to the EC2 instances.
Question: Why am I getting a 502 error when I hit the ALBs endpoint?
I deployed your template in my VPC. The template is perfectly fine and works without any issues, including your load balancer and the website.
Thus whatever is causing your issues, is outside of this template. Probably VPC definition is incorrect, but it is not showed. You can make new question with details of your VPC setup if you want.
New to learning with AWS, I have an EC2 running an apache web server, serving a simple page. I have a classic load balancer in front of it and a route 53 cname pointing to the dns name of the loadbalancer.
If I enter the IP address of the ec2 in a browser, I get my webpage
If I enter the the dns name of the loadbalancer, I get my webpage
But when I enter the dns name of my route 53, it doesn't work, giving a 'this site can't be reached' error.
The cloudformation for my instance is below, with xxxxs blocking out the parts I can't share.:
AWSTemplateFormatVersion: 2010-09-09
Description: EC2 with Route53 and Load Balancer
Parameters:
AWSAccount:
Default: sandbox
Description: Which AWS Account?
AllowedValues:
- sandbox
Type: String
AMI:
Default: ami-0d712b3e6e1f798ef
Description: what AMI will be deployed in the cluster?
Type: 'AWS::EC2::Image::Id'
Name:
Default: xxxxxxxx-xxxtraining
Description: Instance Name
Type: String
ProjectName:
Default: xxxxxxxx
Description: Use your project tag.
Type: String
ContactEmail:
Default: xxxxxxxxxxx
Description: Your Email
Type: String
CName:
Default: xxxxxxx-xxxtraining
Description: appended with domainame.
Type: String
EC2InstanceType:
Default: t3.small
Description: Instance Type
Type: String
EC2KeyName:
Default: xxxxxxxxxxxxxxx
Description: The EC2 Key Pair to allow SSH access to the instances
Type: 'AWS::EC2::KeyPair::KeyName'
ConstraintDescription: Must be the name of an existing EC2 Key Pair.
Mappings:
sandbox:
eu-west-1:
ServiceDNSZone: sandbox.aws.xxxxxxx.com.
DbDNSZone: sandbox.aws.xxxxxxx.com.
ServiceCNAMESuffix: sandbox.aws.xxxxxx.com.
SSLCert: >-
xxxxxxxxxxx
VpcId: vpc-xxxxxxxxxxx
PrivateSubnetIDs:
- subnet-xxxxxxxx
- subnet-xxxxxxxx
- subnet-xxxxxxxx
PublicSubnetIDs:
- subnet-xxxxxxxx
- subnet-xxxxxxxx
- subnet-xxxxxxxx
VPCSubnetMask: 10.41.0.0/16
prod:
eu-west-1:
VpcId: vpc-xxxxxx
ServiceDNSZone: xxxxxxtools.net.
ServiceCNAMESuffix: xxxxxxtools.net.
DbDNSZone: prod.aws.xxxxxx.com.
SSLCert: >-
xxxxxxxxxx
PrivateSubnetIDs:
- subnet-xxxxxxx
- subnet-xxxxxxx
- subnet-xxxxxxx
PublicSubnetIDs:
- subnet-xxxxxxx
- subnet-xxxxxxx
- subnet-xxxxxxx
VPCSubnetMask: 10.51.0.0/16
Resources:
EC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !Ref AMI
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
SecurityGroupIds:
- !Ref EC2InstanceSecurityGroup
SubnetId: !Select
- '0'
- !FindInMap
- !Ref AWSAccount
- !Ref 'AWS::Region'
- PrivateSubnetIDs
Tags:
- Key: Name
Value: !Ref Name
- Key: Project
Value: !Ref ProjectName
- Key: Contact
Value: !Ref ContactEmail
- Key: StackName
Value: !Ref 'AWS::StackName'
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash
- |
yum -y update
- >
yum -y install wget vim nano curl unzip firewalld bash-completion
httpd yum-cron
- '/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource EC2Instance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- >
hostnamectl set-hostname xxxxxxxxxxx
--static
- |
systemctl enable firewalld
- |
systemctl start firewalld
- |
firewall-cmd --add-port=8080/tcp --permanent
- |
firewall-cmd --add-port=22/tcp --permanent
- |
firewall-cmd --add-port=80/tcp --permanent
- |
firewall-cmd --reload
- |
systemctl enable httpd
- |
systemctl start httpd
- >
sed -i 's/update_cmd = default/update_cmd = security/g'
/etc/yum/yum-cron.conf
- >
sed -i 's/apply_updates = no/apply_updates = yes/g'
/etc/yum/yum-cron.conf
- |
systemctl enable yum-cron
- |
systemctl start yum-cron
- |
echo “Hello World from $(hostname -f)” > /var/www/html/index.html
EC2InstanceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Security Group for EC2Instance
VpcId: !FindInMap
- !Ref AWSAccount
- !Ref 'AWS::Region'
- VpcId
Tags:
- Key: Name
Value: !Join
- '-'
- - !Ref 'AWS::StackName'
- EC2InstanceSecurityGroup
- Key: Project
Value: !Ref ProjectName
- Key: Contact
Value: !Ref ContactEmail
- Key: StackName
Value: !Ref 'AWS::StackName'
SecurityGroupIngress:
- IpProtocol: TCP
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/8
- IpProtocol: TCP
FromPort: 8080
ToPort: 8080
CidrIp: 10.0.0.0/8
- IpProtocol: ICMP
FromPort: -1
ToPort: -1
CidrIp: 10.0.0.0/8
- IpProtocol: TCP
FromPort: 443
ToPort: 443
CidrIp: 10.0.0.0/8
- IpProtocol: TCP
FromPort: 80
ToPort: 80
CidrIp: 10.0.0.0/8
Route53:
Type: 'AWS::Route53::RecordSet'
Properties:
HostedZoneName: !FindInMap
- !Ref AWSAccount
- !Ref 'AWS::Region'
- ServiceDNSZone
Comment: CNAME for ELB
Name: !Join
- .
- - !Ref CName
- !FindInMap
- !Ref AWSAccount
- !Ref 'AWS::Region'
- ServiceCNAMESuffix
Type: CNAME
TTL: '300'
ResourceRecords:
- !GetAtt
- LoadBalancer
- DNSName
LoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Instances:
- !Ref EC2Instance
Listeners:
- LoadBalancerPort: '80'
InstancePort: '80'
Protocol: HTTP
HealthCheck:
Target: HTTP:80/
HealthyThreshold: '3'
UnhealthyThreshold: '5'
Interval: '30'
Timeout: '5'
Subnets:
- !ImportValue PrivateSubnetA
- !ImportValue PrivateSubnetB
- !ImportValue PrivateSubnetC
Scheme: internal
SecurityGroups:
- !Ref EC2InstanceSecurityGroup
Outputs:
URL:
Description: The URL of the webserver
Value: !Ref Route53
EC2InstanceID:
Description: EC2 Instance ID
Value: !Ref EC2Instance
EC2InstanceIPAdress:
Description: Instance Private DNS Name
Value: !GetAtt EC2Instance.PrivateIp
In order for your route53 hosted zone to be available in public internet it must have public domain bind to it set as NS record to your Domain registrar.
I have CF template which is creating EC2 machine.
AWSTemplateFormatVersion: 2010-09-09
Mappings:
InstanceAMI:
# ubuntu 18.04
us-west-2:
ami: 'ami-0bbe6b35405ecebdb'
us-east-1:
ami: 'ami-0ac019f4fcb7cb7e6'
Parameters:
Endpoint:
Type: String
# TODO edit the default value
Description:
Resources:
NodeInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- !Ref NodeInstanceRole
NodeInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
CdpDeplSvcSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access Deployment service
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: 'Access Deployment'
DeploymentMachine:
Type: AWS::EC2::Instance
Properties:
# AvailabilityZone: us-east-1a
ImageId: !FindInMap [InstanceAMI, !Ref "AWS::Region", ami]
InstanceType: 't2.small'
KeyName: 'key'
Tags:
- Key: Name
Value: 'Deployment'
BlockDeviceMappings:
- DeviceName: "/dev/sda1"
Ebs:
# VolumeType: "io1"
# Iops: "200"
DeleteOnTermination: "true"
VolumeSize: "30"
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: 'true'
DeleteOnTermination: 'true'
GroupSet:
- !GetAtt CdpDeplSvcSecurityGroup.GroupId
IamInstanceProfile: !Ref NodeInstanceProfile
It executing correctly. But the problem I am facing is sometimes it creates in default private subnet, sometimes in default public subnet.
I want to deploy this machine in the default public subnet only. I don't want to pass VPC id or subnet id as parameter. For that, what I have change here.
This will just put it into a random subnet - you need to hardcode subnet, or specify subnet through a parameter and then reference the parameter - this can provide you with some flexibility for varying the subnet per customer.
Potentially, during deployment of your stack, you could script the deployment, using the AWS CLI to get all public subnets, and pass one in as a parameter into your cloudformation stack.
I am having a hard time troubleshooting why a static page hosted on an EC2 instance is not served through a load balancer.
I am certain the EC2 instance is configured correctly because:
- I can ping the instance when inbound ICMP is allowed in the associated security group
- I can browse the web page when I add the public name of the instance to the Outputs section (though I do not want to do this directly, as the instance is supposed to sit behind the load balancer).
So I think there is an issue with the security groups and/or the network routes.
Here is a simplified version of the CloudFormation template (supposed to be launched in eu-west-1):
AWSTemplateFormatVersion: 2010-09-09
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
InstanceTenancy: default
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
IGW:
Type: 'AWS::EC2::InternetGateway'
IGWAttachment:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
PublicSubnet:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: 10.0.0.0/24
AvailabilityZone: eu-west-1a
MapPublicIpOnLaunch: 'True'
VpcId: !Ref VPC
App:
Type: 'AWS::EC2::Instance'
Properties:
DisableApiTermination: 'false'
InstanceInitiatedShutdownBehavior: stop
ImageId: ami-70edb016
InstanceType: t2.micro
Monitoring: 'false'
UserData: >-
IyEvYmluL2Jhc2gNCnl1bSB1cGRhdGUgLXkNCnl1bSBpbnN0YWxsIC15IGh0dHBkMjQNCnNlcnZpY2UgaHR0cGQgc3RhcnQNCmNoa2NvbmZpZyBodHRwZCBvbg0KZ3JvdXBhZGQgd3d3DQp1c2VybW9kIC1hIC1HIHd3dyBlYzItdXNlcg0KY2hvd24gLVIgcm9vdDp3d3cgL3Zhci93d3cNCmNobW9kIDI3NzUgL3Zhci93d3cNCmZpbmQgL3Zhci93d3cgLXR5cGUgZCAtZXhlYyBjaG1vZCAyNzc1IHt9ICsNCmZpbmQgL3Zhci93d3cgLXR5cGUgZiAtZXhlYyBjaG1vZCAwNjY0IHt9ICsNCmVjaG8gJzxodG1sPjxoZWFkPjx0aXRsZT5TdWNjZXNzITwvdGl0bGU+PC9oZWFkPjxib2R5PlN1Y2Nlc3MhPC9ib2R5PjwvaHRtbD4nID4gL3Zhci93d3cvaHRtbC9kZW1vLmh0bWw=
NetworkInterfaces:
- AssociatePublicIpAddress: 'true'
DeleteOnTermination: 'true'
Description: Primary network interface
DeviceIndex: 0
SubnetId: !Ref PublicSubnet
GroupSet:
- !Ref SGApp
ELB:
Type: 'AWS::ElasticLoadBalancing::LoadBalancer'
Properties:
Subnets:
- !Ref PublicSubnet
Instances:
- !Ref App
SecurityGroups:
- !Ref SGELB
Listeners:
- LoadBalancerPort: '80'
InstancePort: '80'
Protocol: HTTP
HealthCheck:
Target: 'HTTP:80/'
HealthyThreshold: '3'
UnhealthyThreshold: '5'
Interval: '15'
Timeout: '5'
SGELB:
Type: 'AWS::EC2::SecurityGroup'
Properties:
VpcId: !Ref VPC
AllowInboundHTTPToELB:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref SGELB
IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
SGApp:
Type: 'AWS::EC2::SecurityGroup'
Properties:
VpcId: !Ref VPC
AllowInboundHTTPFromELB:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref SGApp
IpProtocol: tcp
FromPort: '80'
ToPort: '80'
SourceSecurityGroupId: !Ref SGELB
RouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
PublicRoute:
Type: 'AWS::EC2::Route'
Properties:
DestinationCidrBlock: 0.0.0.0/0
RouteTableId: !Ref RouteTable
GatewayId: !Ref IGW
SubnetRouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref PublicSubnet
Outputs:
LoadBalancerDNSName:
Value: !GetAtt ELB.DNSName
Once your CF template has created the resources go and check that the EC2 instance is in a healthy state in the ELB under the loadbalancers console. If it is unhealthy it will not route traffic to it.
I decrypted your UserData and could see you don't have an index.html, HTTP:80/ will look for index.html by default. Since there is no index.html httpd would redirect to a test page with an unhealthy 302 response code, as you mentioned in the comments TCP:80 would work or use HTTP:80/demo.html
#!/bin/bash
yum update -y
yum install -y httpd24
service httpd start
chkconfig httpd on
groupadd www
usermod -a -G www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
echo '<html><head><title>Success!</title></head><body>Success!</body></html>' > /var/www/html/demo.html