AWS unhealthy target group instances
I am working on an AWS project at Udacity and deploying an infrastrucute with elastic load balancer, auto scaling group, listeners, listener rules, security groups and target groups. My problem is that the health check status of the instances in the target group always result in unhealthy instances and therefore I am not able to call the load balancer DNS url nor the ip of the instances. I always have 502 bad gateway. What I doing wrong. Here is my code:
Description: >
xxx / Udacity 2023
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
myLaunchTemplateVersionNumber:
Type: String
Default: 1
Resources:
LBSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to our load balancer
VpcId:
Fn::ImportValue:
!Sub "${EnvironmentName}-VPCID"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress: security group.
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
WebServerSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to our hosts and SSH from local only
VpcId:
Fn::ImportValue:
!Sub "${EnvironmentName}-VPCID"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535 #end port
CidrIp: 0.0.0.0/0
myWebAppLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
UserData:
Fn::Base64: !Sub |
#!/bin/bash
apt-get update -y
apt-get install apache2 -y
systemctl start apache2.service
cd /var/www/html
echo "Udacity Demo Web Server Up and Running!" > index.html
ImageId: ami-0a261c0e5f51090b1
KeyName: mykey
SecurityGroupIds:
- sg-01ad772aba0f98d98 # then note the security group id from AWS console todo: use web server SecurityGroup ID
InstanceType: t3.medium # Amazon nomenclature for a specific machine which is how much RAM and which CPU
# Specifying here that we need 10 GB hard drive for this machine and one drive is enough
BlockDeviceMappings:
- DeviceName: "/dev/sdk" # where do I put the hard drive, mount point where you can create folders
Ebs:
VolumeSize: '10' # how much Hard-drive space this machine going to need
WebAppGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier:
- Fn::ImportValue: !Sub "${EnvironmentName}-PUB-NETS"
LaunchTemplate:
LaunchTemplateId: !Ref myWebAppLaunchTemplate # mandantory
Version: !Ref myLaunchTemplateVersionNumber # mandantory
MinSize: "3"
MaxSize: "5"
TargetGroupARNs:
- Ref: WebAppTargetGroup
WebAppLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Subnets:
- Fn::ImportValue: !Sub "${EnvironmentName}-PUB1-SN"
- Fn::ImportValue: !Sub "${EnvironmentName}-PUB2-SN"
SecurityGroups:
- Ref: LBSecGroup
Listener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn:
Ref: WebAppTargetGroup
LoadBalancerArn:
Ref: WebAppLB
Port: '80'
Protocol: HTTP
ALBListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward # forward requests to the specified target group
TargetGroupArn: !Ref 'WebAppTargetGroup'
Conditions:
- Field: path-pattern
Values: [/]
ListenerArn: !Ref 'Listener'
Priority: 1
WebAppTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 15
HealthyThresholdCount: 2
UnhealthyThresholdCount: 5
Port: 8080
Protocol: HTTP
VpcId: # in which VPC the resource is created
Fn::ImportValue:
Fn::Sub: "${EnvironmentName}-VPCID"
Before creation of above infrastructure I need to create the stack below:
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
VpcCIDR:
Description: Please enter the IP range (CIDR notatio) for this VPC
Type: String
Default: 10.0.0.0/16
PublicSubnet1CIDR:
Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
Type: String
Default: 10.0.0.0/24
PublicSubnet2CIDR:
Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone
Type: String
Default: 10.0.1.0/24
PrivateSubnet1CIDR:
Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
Type: String
Default: 10.0.2.0/24
PrivateSubnet2CIDR:
Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
Type: String
Default: 10.0.3.0/24
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC # referencing to the VPC created earlier
# Create 2 public subnets each in AZ0 and AZ1, except for the changed value in the field MapPublicIpOnLaunch: true.
# Marking this field as True will enable the Auto-assign public IP address field of the public subnet
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC # referencing to the VPC created earlier
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Ref PublicSubnet1CIDR # referencing to PublicSubnet1CIDR parameter
MapPublicIpOnLaunch: true # do the subnet gets automatically an IP address
Tags: # Name your subnets using tags, to keep track when you create many subnets.
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC # referencing to the VPC created earlier
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Ref PublicSubnet2CIDR # referencing to PublicSubnet2CIDR parameter
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet (AZ2)
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC # referencing to the VPC created earlier
AvailabilityZone: !Select [0, !GetAZs ""] # Notice that our private subnets are not sharing availability zones.
# We are keeping them separated as we displayed in our diagrams from the previous lesson.
# To do so, the !GetAZs‘’ function fetches the list of AZs in your region which are indexed 0, 1, etc.
# Then, the !select [0, !GetAZs‘’] returns only the first AZ.
CidrBlock: !Ref PrivateSubnet1CIDR # referencing to PrivateSubnet1CIDR parameter
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet (AZ1)
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC # referencing to the VPC created earlier
AvailabilityZone: !Select [1, !GetAZs ""] # the!Select [ 0, !GetAZs '' ] is returning the first AZ from the list of all AZs in your region.
# Similarly, for PrivateSubnet2, the !Select [ 1, !GetAZs '' ] will return the second AZ.
CidrBlock: !Ref PrivateSubnet2CIDR # referencing to PrivateSubnet2CIDR parameter
MapPublicIpOnLaunch: false
Tags:
- Key: NameAW
Value: !Sub ${EnvironmentName} Private Subnet (AZ2)
# The EIP in AWS::EC2::EIP stands for Elastic IP.
# This will give us a known/constant IP address to use instead of a disposable or ever-changing IP address.
# This is important when you have applications that depend on a particular IP address
NatGateway1EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
# Use the DependsOn attribute to protect your dependencies from being created without the proper requirements.
# In the scenario above the EIP allocation will only happen after the InternetGatewayAttachment has completed
NatGateway2EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
NatGateway1:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway1EIP.AllocationId
SubnetId: !Ref PublicSubnet1
NatGateway2:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway2EIP.AllocationId
SubnetId: !Ref PublicSubnet2
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Routes
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment # not neccessary, depends on an InternetGatewayAttachment properly working.
# only used when InternetGateway is attached to VPC and not in any other time during the creation of these resources
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0 # rule means: if you're routing traffic to any address (0.0.0.0 is wildcard address or all addresses),
# they will be routed to this particular resource in GatewayId InternetGateway
# 0.0.0.0 means just send traffic to InternetGateway
# destination matching and a wildcard address (0.0.0/0) to reference all traffic.
# when we use the wildcard address 0.0.0.0/0, we are saying for any address that is destined for any IP address in the world,
# send it to the referenced GatewayId
GatewayId: !Ref InternetGateway
#VPC have route table with routes but could have multiple subnets. SubnetRouteTableAssociation associates a rules to subnets
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet2
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Routes (AZ1)
# route DefaultPrivateRoute1 is attached to the PrivateRouteTable1 and is routed via NatGateway1
# routing traffic to wildcard address 0.0.0.0/0 then send this traffic to NatGateway1, don't exit to the outside
# keep traffic for private subnets within VPC
DefaultPrivateRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway1
# servers within private subnet don't have IP Address
# even placing them on a public subnet, there is no way to access them if they have no IP address
# associate PrivateSubnet1 with rule DefaultPrivateRoute1 from route table PrivateRouteTable1
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable1
SubnetId: !Ref PrivateSubnet1
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Routes (AZ2)
DefaultPrivateRoute2:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable2
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway2
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable2
SubnetId: !Ref PrivateSubnet2
Outputs:
# use this resources in other scripts or files
# we are returning the id of our VPC as well as our Environment's Name:
VPC:
Description: A reference to the created VPC
Value: !Ref VPC # referencing to the VPC created earlier
Export:
Name: !Sub ${EnvironmentName}-VPCID # Substitution of EnvironmentName from parameter
PublicSubnets:
Description: A list of the public subnets
Value: !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]] # join means put several strings together
Export:
Name: !Sub ${EnvironmentName}-PUB-NETS
# Ref get ID of PublicSubnet1 and PublicSubnet2
PrivateSubnets:
Description: A list of the private subnets
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub ${EnvironmentName}-PRIV-NETS
PublicSubnet1:
Description: A reference to the public subnet in the 1st Availability Zone
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${EnvironmentName}-PUB1-SN
PublicSubnet2:
Description: A reference to the public subnet in the 2nd Availability Zone
Value: !Ref PublicSubnet2
Export:
Name: !Sub ${EnvironmentName}-PUB2-SN
PrivateSubnet1:
Description: A reference to the private subnet in the 1st Availability
- Más nuevo
- Más votos
- Más comentarios
It does not look like you are configuring Apache to listen to port 8080.
#!/bin/bash
yum update -y
yum install -y httpd
sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf
systemctl start httpd
systemctl enable httpd
@Shahad_C do you mean curl host into private instance ? What I tried is to ssh login via a bastion host aka jump box to the private instances but I always get a permission denied. I will try to curl localhost too. The instructor in Udacity also uses the following script which I will use in user data in my next try:
#!/bin/bash
Install docker
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
apt-get update
apt-get install -y docker-ce
usermod -aG docker ubuntu
docker run -p 8080:8080 tomcat:8.0
- Shahad_Chace un año
Yes, if its a private instance you'd need to login to it via a Bastion. The bastion would need to have your SSH KeyPair uploaded to it for you to be able to SSH into the private instance. Once inside the private instance you would be able to check if Apache is running and accessible, as well a what port its listening on
thank you for your reply @kentrad. I have the same behaviour when I use the following script in UserData:
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
sudo systemctl enable httpd
How can I configure Apache3 to listen on port 8080 in my UserrData script ?
Contenido relevante
- OFICIAL DE AWSActualizada hace 10 meses
- OFICIAL DE AWSActualizada hace 2 años
- OFICIAL DE AWSActualizada hace 2 años
- OFICIAL DE AWSActualizada hace 2 años
Break down the troubleshooting into chunks to eliminate possibilities. Start by logging into the instance and seeing if the webserver is running. Can you 'curl localhost' inside the instance and get a reply? If no, its an issue with the userdata script; if yes, its config external to the instance