AWS offers load balancing to EC2 instances, containers and serverless functions. This enables you to position a fleet of instances to handle incoming requests from the internet.
In a traditional datacenter operation, load balancers distribute traffic onto your virtual machines. AWS's load balancers do the same exact operation but interacts with resources and services in AWS.

This tutorial will show you how to setup an autoscaling group behind a layer 7 application load balancer (ALB).

Prerequisite


For this tutorial, I'm picking up where I left off in my previous post. For you keen-eyed, viewers you may have noticed that there was no way to access the website with your browser.

Now I'm here to let you know that it was totally done on purpose for this post. ;)

If you have torn down the previous environment, you will need to kick off the pipeline in the previous blog post again to recreate the stack. However before you kick off the build again. Let's make some changes to the code.

Open the application.py file and add host='0.0.0.0', port=80 in application.run().

from flask import Flask, render_template 
 
application = Flask(__name__) 
 
@application.route('/') 
def index(): 
    return render_template('index.html') 
 
@application.route('/status') 
def status(): 
    return "green" 
     
if __name__ == '__main__': 
    application.run(host='0.0.0.0', port=80) 

Next open up the prod.yml and add the following in the launch configuration resource section. This will open port 80 on the instance and install pip and flask package for python.

      iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
      amazon-linux-extras install epel -y 
      yum install python-pip -y  
      pip install Flask 

Example of the prod.yml.

# version 2019.10.04 
AWSTemplateFormatVersion: '2010-09-09' 
 
Mappings: 
  AwsRegionAmi: 
    us-east-1: 
      AMI: ami-0b69ea66ff7391e80 
    us-east-2: 
      AMI: ami-00c03f7f7f2ec15c3 
 
Resources: 
  myInstanceProfile:  
    Type: AWS::IAM::InstanceProfile 
    Properties:  
      Roles:  
        - EC2S3RO 
 
  myLaunchConfig: 
    Type: AWS::AutoScaling::LaunchConfiguration 
    Properties: 
      LaunchConfigurationName: cf-created-standard-prod 
      KeyName: cf 
      SecurityGroups:  
        - sg-04f9c0c282f0bc8de 
      InstanceType: t2.micro 
      ImageId: !FindInMap [AwsRegionAmi, !Ref 'AWS::Region', AMI] 
      BlockDeviceMappings:  
        - DeviceName: "/dev/xvda" 
          Ebs: 
            VolumeSize: 10 
            VolumeType: gp2 
      IamInstanceProfile: !Ref myInstanceProfile 
      UserData: 
        Fn::Base64: | 
          #!/bin/bash 
          DATE=$(date +%Y-%m-%d) 
          ARTIFACT=$(aws s3 ls s3://codepipeline-us-east-2-710251686107/hello-kitty-ASG/BuildArtif/ | grep ${DATE} | awk '{print $4}') 
          yum update -y 
          yum install epel-release vim lynx tcpdump tmux -y 
          iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
          amazon-linux-extras install epel -y 
          yum install python-pip -y  
          pip install Flask 
          echo "hello lol12345" > /tmp/lol.txt 
          mkdir /flask 
          aws s3 cp s3://codepipeline-us-east-2-710251686107/hello-kitty-ASG/BuildArtif/${ARTIFACT} /flask 
          unzip /flask/${ARTIFACT} -d /flask 
          python /flask/application.py &
     
  myASG: 
    Type: AWS::AutoScaling::AutoScalingGroup 
    Properties: 
      AutoScalingGroupName: myCfAsg-prod 
      AvailabilityZones:  
        Fn::GetAZs:  
          Ref: "AWS::Region" 
      LaunchConfigurationName: !Ref myLaunchConfig 
      DesiredCapacity: "2" 
      MinSize: "1" 
      MaxSize: "3" 
      Tags: 
        - Key: Environment  
          Value: Prod 
          PropagateAtLaunch: "true" 
        - Key: Name  
          Value: ProdInstance 
          PropagateAtLaunch: "true" 
   
  myS3bucket: 
    Type: AWS::S3::Bucket 
    Properties: 
      BucketName: prods3bucket0021 

Creating the Target Group


Now that the stack is up and running, create a new target group, mine is named tg-prod.

Select and enter the following options.

Port: 80

VPC: Your VPC

Protocol: HTTP

Path: /

Port: traffic port

Healthy threshold: 2

Unhealthy threshold: 3

Timeout: 5

Interval: 10

Success codes: 200-299

Now go into "Auto Scaling Groups", notice in the details tab under "Target Groups" that it's blank. I'll fix this now and add the newly created target group here.

Click on the edit button and add the tg-prod target group, then click save when you're done.

Navigate back to the "Target Groups" page and you should see in the "Targets" tab for tg-prod the newly created instances from the autoscaling group automatically set as registered targets.

Notice the status is saying "unused", this will change once the ALB is created.

Creating the Load Balancer

On the sidebar to the left, click on "Load Balancers". In the next page click on "Application Load Balancer"

Give it a name, mine is named alb-prod and make sure the scheme is set to "internet-facing". For the listeners select the protocol for HTTP and port 80.

Create a new security group for the load balancer. Allow HTTP to be accessible everywhere.

Select the tg-prod as the target group for the ALB to route traffic to.

As you can see the two instances from the auto-scaling group are already registered.

Once the load balancer is up and running, head back into the security groups.

Edit the security group applied to the launch configuration and only allow HTTP to communicate originating from the load balancer's security group.

This will prevent anyone from directly accessing the the EC2 instances by using their public IP. The website should only be served by using the DNS record of the application load balancer.

Now if you check the target group you will see that the instance status has changed to healthy.

Now go ahead and access the website using the ALB's DNS record. You should be greeted by Hello Kitty!

Now if you ever lose one of the instances the ALB will redirect traffic to a healthy instance while the unhealthy instance is terminated and replaced with a new healthy one.