Adding an ELB to our stack

We will go through the following changes. In the troposphere import section at the top of the script, we are going to import the subpackage elasticloadbalancing as follows:

from troposphere import ( 
    Base64,
ec2, GetAtt, Join, Output, Parameter, Ref, Template, elasticloadbalancing as elb, )

The creation of an ELB requires specifying the VPC in which to add the load balancer. We can easily select the proper VPC by adding a new parameter to our template. To do so, right after the key pair parameter section, add a new parameter as follows:

t.add_parameter(Parameter( 
    "VpcId", 
    Type="AWS::EC2::VPC::Id", 
    Description="VPC" 
)) 

In addition to selecting which VPC to use to create the ELB, we can also select which subnets to use in order to find instances. Below the VPC parameter selection, add a new block to pick our subnets with the following code:

t.add_parameter(Parameter( 
    "PublicSubnet", 
    Description="PublicSubnet", 
    Type="List<AWS::EC2::Subnet::Id>", 
    ConstraintDescription="PublicSubnet" 
)) 

We now have all the parameters needed to build our ELB instance. We need one more piece of information, the security group. The security groups in ELB work in roughly the same way as in EC2. The main differences with the EC2 security group is that in order to use ELB in a VPC, the security group needs to specify the ID of that VPC and, since it's a managed load balancer service, AWS doesn't provide an SSH access to those instances and therefore we don't need to open up port TCP/22.

After the previous subnet parameter section, we can create our ELB security group resource as follows:

t.add_resource(ec2.SecurityGroup( 
    "LoadBalancerSecurityGroup", 
    GroupDescription="Web load balancer security group.", 
    VpcId=Ref("VpcId"), 
    SecurityGroupIngress=[ 
        ec2.SecurityGroupRule( 
            IpProtocol="tcp", 
            FromPort="3000", 
            ToPort="3000", 
            CidrIp="0.0.0.0/0",
        ), 
    ], 
)) 

We can now create our ELB resource. After the creation of the load balancer security group, we will add a new resource for the load balancer. We are first going to create the resource and initialize it with the load balancer function. We will simply call that resource LoadBalancer:

t.add_resource(elb.LoadBalancer( 
    "LoadBalancer", 

ELBs can be used for internal load balancing or at the edge of your network. In our case, we are trying to use it at our frontend endpoint and therefore we will want an internet-facing scheme. On the next line, add the following:

    Scheme="internet-facing", 

We can now configure our listeners. This means defining which port to redirect to where and which protocol to use for that. In order to keep things simple, we can configure our load balancer to redirect all requests coming in to port 3000 to port 3000 as follows:

    Listeners=[ 
        elb.Listener( 
            LoadBalancerPort="3000", 
            InstancePort="3000", 
            Protocol="HTTP", 
            InstanceProtocol="HTTP" 
        ), 
    ], 

In order to know whether a host is able to take on requests, the load balancer needs to verify that our application is running on the instances that the load balancer points to. This is done through a health check mechanism. Ours will verify that we are able to get the home page of our application, which is running on port 3000. We can do it as follows:

    HealthCheck=elb.HealthCheck( 
        Target="HTTP:3000/", 
        HealthyThreshold="5", 
        UnhealthyThreshold="2", 
        Interval="20", 
        Timeout="15", 
    ), 

Over time, EC2 instances will be added and removed from the load balancer; in order to make a smooth transition when hosts are removed, we want to allow enough time for any ongoing transaction to complete. We can put that in place using a draining policy. Ours will tell the load balancer to stop taking on new requests and wait 10 seconds such that previous connections can complete. Here is how it works:

    ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( 
        Enabled=True, 
        Timeout=10, 
    ), 

We want our load balancer to distribute requests evenly across all instances in the pool regardless of the availability zone that the instances are in; this is done by setting the CrossZone option to True:

    CrossZone=True, 

Finally, we will reference the two resources we previously created to specify which subnets and security groups to use and close the opened parentheses:

    Subnets=Ref("PublicSubnet"), 
    SecurityGroups=[Ref("LoadBalancerSecurityGroup")], 
))  

Our load balancer can now be created. It is going to be used as our endpoint for our application. In order to make it easy to find the new URL for our application, we are going to create a new output to reflect that architecture change. We will create an output similar to what we had in the previous chapter, but instead of pointing to the public IP of the instance that is now gone, we are going to expose the DNS name of our ELB as follows:

t.add_output(Output( 
    "WebUrl", 
    Description="Application endpoint", 
    Value=Join("", [ 
        "http://", GetAtt("LoadBalancer", "DNSName"), 
        ":", ApplicationPort 
    ]), 
)) 

We can now add our Auto Scaling group.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset