Welcome to Day 89 of the “100 Days of DevOps with PowerShell”! For background on our goals in this series, see Announcing the “100 Days of Devops with PowerShell” Series here at SCC.
Update: 2014-12-30 – the code was updated below to fix a couple of typos.
In previous posts we have looked at configuring network infrastructure in AWS as well as deploying and configuring instances. In today’s post we are going to bring together a lot of we’ve covered before and start a mini-series of posts on how to deploy highly available servers in AWS. In our example we are going to look at using a load balancer to distribute requests between two web servers. A load balancer in AWS can be deployed in EC2 Classic or a VPC and in our example we are going to use a VPC. As a refresher (from Day 74), a VPC is specific to a region, but within a region you may have multiple availability zones which would be physically separate datacenters. Subnets are created within availability zones and you may create a VCP in the us-east-1 region with a CIDR block of 10.0.0.1/16, but create multiple subnets within the VPC across different availability zones. Therefore if an availability zone encounters an outage which affects a web server within one its subnets, another web server in another availability zone would be unaffected. It is the job of the load balancer monitor the health state of its assigned instances, so if a web server experiences an outage traffic will not be directed to it.
Configuring the environment for a load balancer.
A requirement when configuring a load balancer is any subnets assigned to it must reside in separate availability zones and this is shown in our architecture below:
Also notice there are two load balancers shown in the diagram. In our example, we’ll only be deploying one load balancer initially, but if AWS detects the availability zone for that load balancer becomes unavailable or if that load balancer becomes under increasing load, a second load balancer will be deployed. Therefore separate subnets for the load balancer and web server need to be created in different availability zones.
Deploying the environment
Much of the deployment of this setup has already been created in previous posts, but for completeness we’ll show the end-to-end deployment and we’ll continue to use variables in the script as we make further enhancements to the environment. In the script we are looking to do the following:
- Deploy a VPC
- Deploy subnets in different availability zones
- Deploy the web servers
- Create an internet gateway for the load balancer subnets
- Create a security group for the load balancers
- Deploy the load balancer
#Create the subnets and Cidrblock for the VPC
$cidrBlock = '10.0.0.0/16'
$ELBCidr1 = '10.0.1.0/24'
$ELBCidr2 = '10.0.2.0/24'
$webCidr1 = '10.0.3.0/24'
$webCidr2 = '10.0.4.0/24'
$region = 'us-east-1'
$zone1 = 'us-east-1a'
$zone2 = 'us-east-1b'
#Create the VPC
$VPC = New-EC2Vpc -CidrBlock $cidrBlock -Region $region
#Create the web subnets
$webSubnet1 = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $webCidr1 -AvailabilityZone $zone1
$webSubnet2 = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $webCidr2 -AvailabilityZone $zone2
#Create the ELB subnets
$ELBSubnet1 = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $ELBCidr1 -AvailabilityZone $zone1
$ELBSubnet1 = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $ELBCidr2 -AvailabilityZone $zone2
#Encode the user data to deploy the start-up scripts to the servers
$userDataString = @"
Install-WindowsFeature Web-Server -IncludeManagementTools -IncludeAllSubFeatures
$EncodeUserData = [System.Text.Encoding]::UTF8.GetBytes($userDataString)
$userData = [System.Convert]::ToBase64String($EncodeUserData)
$ami = Get-EC2ImageByName -Names 'WINDOWS_2012R2_BASE'
$reservation1 = New-EC2Instance -ImageId $ami.ImageId -KeyName 'SCCDemo-key-pair' -InstanceType 't1.micro' -MinCount 1 -MaxCount 1 -UserData $userData -SubnetId $webSubnet1.SubnetID
$reservation2 = New-EC2Instance -ImageId $ami.ImageId -KeyName 'SCCDemo-key-pair' -InstanceType 't1.micro' -MinCount 1 -MaxCount 1 -UserData $userData -SubnetId $webSubnet2.SubnetID
#Creating the internet gateway
$InternetGateway = New-EC2InternetGateway
Add-EC2InternetGateway -InternetGatewayId $InternetGateway.InternetGatewayID -VpcId $VPC.vpcID
#create a route table and add the ELB subnets
$routeTable = New-EC2RouteTable -VpcId $VPC.vpcID
New-EC2Route -RouteTableId $routeTable.routeTableID -DestinationCidrBlock '0.0.0.0/0' -GatewayId $InternetGateway.InternetGatewayID
Register-EC2RouteTable -RouteTableId $routeTable.routeTableID -SubnetId $ELBSubnet1.subnetId
Register-EC2RouteTable -RouteTableId $routeTable.routeTableID -SubnetId $ELBSubnet2.subnetId
#create the security groups for the ELBs
$secGroupID = New-EC2SecurityGroup -vpcID $VPC.vpcID -GroupName 'HTTP-ELB' -GroupDescription 'HTTP access for ELBs'
$HTTPRule = New-Object Amazon.EC2.Model.IpPermission
$HTTPRule.IpProtocol = 'tcp'
$HTTPRule.FromPort = '80'
$HTTPRule.ToPort = '80'
$HTTPRule.IpRange = '0.0.0.0/0'
Grant-EC2SecurityGroupIngress -GroupId $secGroupID -IpPermissions $HTTPRule
#Get the default security group for the VPC
$VPCFilter = New-Object Amazon.EC2.Model.Filter
$VPCFilter.Name = 'vpc-id'
$VPCFilter.Value = $VPC.VpcId
$NameFilter = New-Object Amazon.EC2.Model.Filter
$NameFilter.Name = 'group-name'
$NameFilter.Value = 'default'
$DefaultGroup = Get-EC2SecurityGroup -Filter $VPCFilter, $NameFilter
The environment is now setup and we’re ready to deploy the load balancers. To deploy the load balancers we are going to do the following:
- Create a listener for the Load balancer – in this case it will be port 80
- Create the load balancer and assign the security groups (default and allowing HTTP traffic from the Internet) and the load balancer subnets
#Deploy the load balancers
$HTTPListener = New-Object ‘Amazon.ElasticLoadBalancing.Model.Listener’
$HTTPListener.Protocol = ‘http’
$HTTPListener.InstancePort = 80
$HTTPListener.LoadBalancerPort = 80
New-ELBLoadBalancer -LoadBalancerName ‘ELB-Web-01’ -Listeners $HTTPListener -SecurityGroups $DefaultGroup.GroupID, $secGroupID -Subnets $ELBSubnet1.subnetID, $ELBSubnet2.subnetID
In this post we’ve looked at how at setting up the ground work for highly available web servers by creating the VPC, subnets, instances and security groups for our environment. Finally we deployed the load balancer, assigning the security groups and its subnets. However, we have not yet configured the load balancer which will require assigning the instances as well as the health checks. We’ll do that in the next post!
To see the previous installments in this series, visit “100 Days of DevOps with PowerShell”.