Load Balancing

Elastic Load Balancing

In this project we are going to use Amazon EC2 Auto Scaling that should distribute traffic among instances

  MyAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      AvailabilityZones:
        - "us-east-2a"
        - "us-east-2b"
      MinSize: "1"
      MaxSize: "2"
      DesiredCapacity: "1"
      HealthCheckType: EC2
      LaunchConfigurationName: !Ref MyLaunchConfiguration

Over all the code sets up an Auto Scaling group with a desired capacity of 1, minimum size of 1, and a maximum size of 2. Instances will be launched in two availability zones in the us-east-2 region, and their health will be monitored using EC2 status checks. The specifics of the instance configuration are determined by the referenced Launch Configuration MyLaunchConfiguration --> SHIP YAML --> https://devops.stefanogramm.com/devops/ship

---

We define an AWS CloudFormation resource for an Auto Scaling group

AvailabilityZones: Specifies the availability zones where the instances in the Auto Scaling group will be launched. In this example, it will launch instances in both "us-east-2a" and "us-east-2b".

MinSize: "1": Specifies the minimum number of instances that should be maintained in the Auto Scaling group. In this case, it's set to 1, which means there should always be at least one instance running.

MaxSize: "2": Specifies the maximum number of instances that the Auto Scaling group can scale up to. In this case, it's set to 2, meaning the group can have a maximum of two instances running simultaneously. We can change that depend the scenario

DesiredCapacity: "1": Specifies the desired number of instances in the Auto Scaling group

HealthCheckType: EC2: Specifies the type of health check used for the instances in the Auto Scaling group. In this case, it's set to "EC2," which means that the health of instances will be determined based on EC2 status checks.

LaunchConfigurationName: !Ref MyLaunchConfiguration: References the name of the AWS Launch Configuration resource (MyLaunchConfiguration) that defines the configuration settings for the instances launched by the Auto Scaling group. This Launch Configuration resource will specify details like the AMI, instance type, security groups, and other launch parameters.

---

To Do

Done:

Increased the MinSize to 2 and MaxSize to 4, which means our Auto Scaling group will ensure that at least 2 instances are always running, and can scale up to 4 instances if needed at anytime.

  MyAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      AvailabilityZones:
        - "us-east-2a"
        - "us-east-2b"
      MinSize: "2"
      MaxSize: "4"
      DesiredCapacity: "2"
      HealthCheckType: EC2
      LaunchConfigurationName: !Ref MyLaunchConfiguration
      TargetGroupARNs: 
        - !Ref MyTargetGroup

---HA---

Done:

Created an Application Load Balancer (MyLoadBalancer) in three subnets spanning different availability zones. This setup ensures high availability and fault tolerance.

  MyLoadBalancer:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties: 
      Subnets:
        - "subnet-feced596"
        - "subnet-c7dc8dbd"
        - "subnet-52d9611e"
      SecurityGroups: 
        - "sg-a7f988c5"

Health Checks

External Health checks and Analytics

Taking the server down to test external health checks:

Health Checks
Unhealthy checks
Unhealthy checks details

AWS Health checks

We created a Target Group with an HTTP health check on the default route "/". The health check ensures that traffic is routed only to healthy instances.

HealthCheckPath: "/"

To do

Consistent public IP address - Elasti IPs

( Can add if required, depends the project)

Can be added to the UserData section in the main configuration yaml if needed. ( ELB handles the distribution of incoming traffic to multiple instances without needing Elastic IPs)

  • MyEIP creates an Elastic IP address (EIP) using the AWS CloudFormation

  • MyLambdaExecutionRole resource creating an IAM role which is going to be used by the Lambda function we will create

  • AssumeRolePolicyDocument will define AWS Lambda service

  • MyLambdaFunction resource will create a Lambda function using the latest Node.js

  • MyEIPAssociation resource sends a request to a specified ServiceToken (ARN)

--> https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html

  • Should have the AmazonEC2FullAcces attached

Resources:
  MyEIP:
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  MyLambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AmazonEC2FullAccess

  MyLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.handler
      Role: !GetAtt 'MyLambdaExecutionRole.Arn'
      Code:
        ZipFile: |
          const AWS = require('aws-sdk');
          const ec2 = new AWS.EC2();

          exports.handler = async (event, context) => {
            if (event.RequestType === 'Create') {
              await ec2.associateAddress({
                InstanceId: event.ResourceProperties.InstanceId,
                PublicIp: event.ResourceProperties.PublicIp
              }).promise();

              return {
                PhysicalResourceId: context.logStreamName
              };
            }
          };
      Runtime: nodejs18.x // https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
      Timeout: '15'

  MyEIPAssociation:
    Type: 'Custom::EIPAssociation'
    Properties:
      ServiceToken: !GetAtt 'MyLambdaFunction.Arn'
      InstanceId: !Ref 'MyInstance'
      PublicIp: !GetAtt 'MyEIP.PublicIp'

Tested? =

Last updated

Was this helpful?