This post is a part of the “Architecting on AWS” series
Picking up from where we left off, we need eliminate the single point(s) of failure in our architecture. Before we get a chance to do that though, we’re made aware of another issue: Our web server’s hostname (URL) changed too.
Regardless of whether these issues are related, perhaps we can think of a solution that solves both issues? Let’s see what we can find.
After a quick search, we find the reason for our changing hostname: “We release the public IP address from your instance, or assign it a new one.” Ah ha! Perhaps our instance was “stopped, hibernated, or terminated” which caused it to obtain a new public IP address.
Now that we know what the problem is, how do we solve it? Lucky for us, the solution is in that same document. “An Elastic IP address is a public IPv4 address that you can allocate to your account. You can associate it to and disassociate it from instances as you require.“ Perfect! Attaching an Elastic IP to our EC2 instance enables us to ensure it will have a static IP address/hostname.
2 instances, 2 hostnames
But wait a minute… if we deploy our second server and assign it an EIP, we’ll end up with two separate hostnames:
That means that if a server fails (e.g
webserver1.example.com), we’ll need to ask visitors to browse to the remaining hostname (e.g
webserver2.example.com). That won’t do! We want to provide a seamless experience. Therefore, EIPs aren’t the right solution for us. Back to the drawing board we go…
Application Load Balancer (ALB)
The next possible solution we find are called Application Load Balancers. During our research on them, we realise that they can solve both our redundancy issue and our dynamic hostname issue too!
In regards to redundancy, an ALB allows us to seamlessly deploy servers across Availability Zones. This means that our website will stay online even if AWS suffers another Availability Zone outage.
In regards to dynamic hostnames, ALBs actually have static hostnames. That means it doesn’t matter if our web servers come and go. Visitors will only ever need to remember a single web address.
So that settles it! An ALB is the way to go. Let’s get to work on updating our CloudFormation template.
After updating our template, we’re ready to launch the stack:
aws cloudformation create-stack \ --template-body file://ec2_website_alb.yaml \ --stack-name OzNetNerd-demo-environment
update-stack if you didn’t delete the stack after completing the previous task.
Note: The CloudFormation template provides two optional parameters. They can be used to lock down access to the EC2 instance as well as provide SSH access to it. See the README for more information.
Once our deployment completes, it will look like this:
Now that the stack has been updated, it’s time to put our new design to the test. First we retrieve the ALB’s hostname using the following command:
aws cloudformation describe-stacks --stack-name OzNetNerd-demo-environment \ --query "Stacks.Outputs[?OutputKey=='Ec2WebHostB'].OutputValue" --output text
When we browse to the URL, we’re relieved to see that the Flask app is working. Better still, we find that each time we refresh our browser, the page is served by one of the two web servers. Fantastic! Our ALB is working perfectly.
As a final test, we upload a file to the app…
Unfortunately see that our
data.csv isn’t listed under “Uploaded Files”. What is going on here?
Actually… there it is!
In a similar vein to “switch it off and on again”, we refresh our page hoping that it’ll magically fix our issue. And it turns out, it does!
After what feels like forever, we realise what the issue is. Our uploads are being uploaded to one web server. When we refresh our browser, we’re then load balanced to the other server. As this server didn’t receive the file, it shows an empty file list. When we refresh the browser again, we’re then load balanced to the original server which does have the upload.
Looking at the screenshots above, we can see the following happen:
- We browse to the ALB’s hostname. It directs us to Server A (ec2-13-238-184-191) which presents us with the upload form.
- When we click “upload”, the ALB directs us to Server B (ec2-3-24-218-53). This means that the file is stored on Server B.
- When we refresh our browser, the ALB directs us to Server A. Because this server doesn’t have the file, no files are listed under “Uploaded Files”.
- When we refresh our browser again, the ALB directs us to Server B. This time we see the file listed.
Now that we know what the problem is, how do we fix it?
As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at email@example.com, or drop me a message on Reddit (OzNetNerd).
Note: The opinions expressed in this blog are my own and not those of my employer.