Setting Up a Load Balancer, Target Group, and Auto Scaling Group on AWS
Load balancing, auto-scaling, and fault tolerance are key components for high availability and performance in modern web infrastructures. AWS provides built-in tools for this, mainly through Elastic Load Balancing (ELB) and Auto Scaling Groups (ASG). In this article, we will walk through the process of setting up a load balancer, target group, and an auto-scaling group on AWS.
Elastic Load Balancer (ELB)
What is it?
ELB automatically distributes incoming application traffic across multiple targets, such as EC2 instances, containers, and IP addresses, in one or more Availability Zones.
How does it help?
-
High Availability: By distributing traffic across multiple resources, ELB ensures no single resource is a bottleneck, which can be especially useful during traffic spikes.
-
Fault Tolerance: If one or more instances fail, ELB reroutes traffic to healthy instances until the failed ones are restored.
-
Scalability: Easily handle varying loads of traffic without manual intervention.
Why use it?
-
Security: Integrated with AWS security features, such as VPC and Security Groups.
-
Operational Monitoring: Offers metrics and logs to monitor applications and performance.
-
Global Load Balancing: With Global Accelerator, ELB can reroute user traffic to healthy endpoints in multiple AWS regions.
Target Groups
What is it?
When configuring a load balancer, you direct the traffic to a target group. The target group routes requests to one or more registered targets based on the health of the targets.
How does it help?
-
Efficient Traffic Routing: Routes traffic to the right resources.
-
Health Checks: Constantly monitors the health of resources. If a resource becomes unhealthy, the traffic is routed to other healthy resources.
Why use it?
-
Versatility: Supports instances, IP addresses, or Lambda functions as targets.
-
Flexibility: Multiple target groups can be used with a single load balancer.
-
Granular Health Checks: Allows for customized health check configurations.
Auto Scaling Groups (ASG)
What is it?
Auto Scaling helps maintain application availability and allows you to scale Amazon EC2 capacity up or down automatically according to conditions you define.
How does it help?
-
Dynamic Scaling: Automatically scales resources based on demand. If traffic spikes, ASG provisions more resources, and if it drops, it de-provisions them.
-
Maintain Application Availability: Replaces unhealthy instances with healthy ones ensuring that the set number of instances are always running.
-
Balanced Capacity: Evenly distributes instances across Availability Zones for high availability and fault tolerance.
Why use it?
-
Cost Savings: You only use (and pay for) the resources you need.
-
Optimized Performance: Ensures your application has the right amount of capacity at all times.
-
Flexibility: Supports manual scaling, scheduled scaling, and dynamic scaling.
Step-by-step Guide
1. Set Up an Elastic Load Balancer (ELB)
a. Open the AWS Management Console.
b. Navigate to EC2 > Load Balancers.
c. Click Create Load Balancer.
d. Choose your desired type (Application or Network). For this guide, we'll choose Application Load Balancer.
e. Configure Load Balancer settings:
- Name: A unique name for the ELB.
- Scheme: Choose "internet-facing".
- Listeners: Default is HTTP:80. You can add HTTPS if you have a SSL certificate.
f. Configure Availability Zones by selecting the VPC and the subnets.
g. Click Next.
2. Configure Security Settings
If you added an HTTPS listener, you'd configure SSL certificate details here. Otherwise, proceed to the next step.
3. Configure Security Groups
Select a security group that allows incoming HTTP/HTTPS traffic.
4. Configure Routing (Target Group)
a. Name: Give a unique name to your target group.
b. Target type: Choose "instance".
c. Protocol: HTTP.
d. Port: 80.
e. Health checks: Default is /index.html, but you can adjust as needed.
5. Register Targets
Skip this step for now, as we will register targets via the Auto Scaling Group.
6. Create the Load Balancer.
7. Set Up an Auto Scaling Group (ASG)
a. Navigate to EC2 > Auto Scaling Groups.
b. Click Create Auto Scaling group.
c. Choose Launch Template or Launch Configuration. For this guide, we'll use Launch Configuration.
d. Configure:
- AMI: The Amazon Machine Image for your instances.
- Instance type: e.g., t2.micro.
- Key pair: Select the one you created earlier.
e. Configure details like IAM role, monitoring, and advanced details if needed.
f. Configure storage.
g. Configure security groups.
h. Review and create launch configuration.
i. Now, configure the ASG details:
- Group name: A unique name.
- Group size: Desired number of instances.
- Network: Select your VPC.
- Subnet: Choose the subnets.
j. Configure scaling policies as needed.
k. Configure Notification and Tags if needed.
l. In Advanced settings, you can configure:
- Load balancing.
- Health checks.
- Instance protection.
m. Review and Create Auto Scaling group.
n. Once created, edit the ASG and associate the target group under Load balancing.
8. Review and Test
a. Navigate back to Load Balancers and select the one you created.
b. Under the Monitoring tab, you can see traffic and request metrics.
c. Test the load balancer's DNS to ensure it routes traffic to your instances.
Get cloudformation template here
AWSTemplateFormatVersion: '2010-09-09'
Description: Ec2 with load balancer, tg, and asg.
## Parameters
Parameters:
EC2InstanceSize:
Default: "t3.micro"
Description: Instance size for Web Servers.
Type: String
AllowedValues:
- "t3.micro"
- "t3.small"
- "t3.medium"
AllowedIP:
Description: IPs allowed to connect to load balancer.
AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
Type: String
Default: 0.0.0.0/0
VpcId:
Type: AWS::EC2::VPC::Id
Description: Select a VPC for the instance
Default: vpc-0c130bf7bc1cdfe53
LoadBalancerSubnetId:
Type: List<AWS::EC2::Subnet::Id>
Description: Select a subnet for the load balancer
Default: subnet-0b3f26e7665831ca4,subnet-05c54afa0760dd5bb
EC2SubnetId:
Type: List<AWS::EC2::Subnet::Id>
Description: Select a subnet for the instance
Default: subnet-0b3f26e7665831ca4,subnet-05c54afa0760dd5bb
ImageId:
Type: String
Description: ID of the AMI to use for the instance
Default: ami-01a3d71f30b1cf898
ArtifactsBucket:
Description: S3 bucket with artifact files (Lambda functions, templates, html files, etc.). Leave default.
Type: String
Default: ee-assets-prod-us-east-1
AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
ConstraintDescription: ArtifactsBucket S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-).
It cannot start or end with a hyphen (-).
ArtifactsPrefix:
Description: Path in the S3 bucket containing artifact files. Leave default.
Type: String
Default: modules/5af8175826af40428bb6062dff449ce1/v5
AllowedPattern: ^[0-9a-zA-Z-/]*$
ConstraintDescription: ArtifactsPrefix key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-),
and forward slash (/). Leave default.
Resources:
## Configure ALB: security group, load balancer, route 53 endpoint
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: Load Balancer Security Group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref AllowedIP
Tags:
- Key: Name
Value: !Join ["-" , [!Ref 'AWS::StackName', 'load-balancer']]
AppLoadBlancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
Subnets: !Split [',', !Join [',', !Ref LoadBalancerSubnetId]]
Tags:
- Key: Name
Value: !Join ["-" , [!Ref 'AWS::StackName', 'application-load-balancer']]
AppLoadBlancerTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Port: 80
Protocol: HTTP
UnhealthyThresholdCount: 10
VpcId: !Ref VpcId
Tags:
- Key: Name
Value: !Join ["-" , [!Ref 'AWS::StackName', 'target-group']]
AppLoadBlancerListenerHttp:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn: [ AppLoadBlancerTargetGroup ]
Properties:
LoadBalancerArn: !Ref AppLoadBlancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AppLoadBlancerTargetGroup
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: EC2 Instance Security Group
Tags:
- Key: Name
Value: !Join ["-" , [!Ref 'AWS::StackName', 'ec2']]
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId:
!Ref LoadBalancerSecurityGroup
## Configure the EC2 IAM role along with supporting resources
EC2InstanceRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Join ["-" , [!Ref 'AWS::StackName', EC2Role]]
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "sts:AssumeRole"
Principal:
Service:
- "ec2.amazonaws.com"
- "ssm.amazonaws.com"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
Policies:
- PolicyName: inline-policy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "logs:DescribeLogStreams"
Resource: "arn:aws:logs:*:*:*"
-
Action:
- s3:ListBucket
Effect: Allow
Resource:
- !Join ['', ['arn:aws:s3:::', !Ref 'ArtifactsBucket']]
-
Action:
- s3:GetObject
Effect: Allow
Resource:
- !Join ['', ['arn:aws:s3:::', !Ref 'ArtifactsBucket', /, !Ref 'ArtifactsPrefix', /*]]
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: EC2InstanceRole
LaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref ImageId
SecurityGroups:
- !GetAtt EC2SecurityGroup.GroupId
InstanceType: !Ref EC2InstanceSize
IamInstanceProfile:
Ref: EC2InstanceProfile
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello from CloudFormation" > /var/www/html/index.html
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Join ["-" , [!Ref 'AWS::StackName', LaunchTemplate]]
LaunchTemplateData:
ImageId: !Ref ImageId
SecurityGroupIds:
- !GetAtt EC2SecurityGroup.GroupId
InstanceType: !Ref EC2InstanceSize
IamInstanceProfile:
Arn: !GetAtt EC2InstanceProfile.Arn
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello from CloudFormation" > /var/www/html/index.html
# Fetch metadata
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
REGION=$(echo $AZ | sed 's/[a-z]$//')
# Create web page
cat <<EOF > /var/www/html/index.html
<html>
<head>
<title>EC2 Metadata</title>
<style>
body {
font-family: Arial, sans-serif;
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: #f4f4f4;
}
.content {
text-align: center;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div class="content">
<h1>EC2 Instance Metadata</h1>
<p><strong>Instance ID:</strong> $INSTANCE_ID</p>
<p><strong>Availability Zone:</strong> $AZ</p>
<p><strong>Region:</strong> $REGION</p>
</div>
</body>
</html>
EOF
AutoScalingGroup:
DependsOn: AppLoadBlancer
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier: !Split [',', !Join [',', !Ref EC2SubnetId]]
#LaunchConfigurationName: !Ref LaunchConfiguration
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt [LaunchTemplate, LatestVersionNumber]
MinSize: '2'
MaxSize: '2'
TargetGroupARNs:
- !Ref AppLoadBlancerTargetGroup
DesiredCapacity: '2'
HealthCheckType: ELB
HealthCheckGracePeriod: 240
Tags:
-
Key: Name
Value: !Join ["-" , [!Ref 'AWS::StackName', 'asg']]
PropagateAtLaunch: true
In Conclusion:
All these components together form a resilient and scalable architecture. While each can be used individually, their combined use ensures that web applications and services are always available, even if some components fail, and can scale up or down based on real-time demand.
Remember to monitor your infrastructure and adjust configurations as needed based on your application's demands and performance metrics.
© Waqar Ahmed.RSS