Blog

Building a global app with AWS Global Accelerator

03 Jul, 2019
Xebia Background Header Wave

This blog post describes how to use the AWS Global Accelerator with a simple service across two regions, deployed with Terraform. AWS Global Accelerator is a networking service that improves the availability and performance of the applications that you offer to your global users. The source code can be found on GitHub:
https://github.com/binxio/tf-global-accelerator
I used a lot of inspiration from the following blog post by Adrian Hornsby: “Multi-region serverless backend”. It’s a good blog post, but it takes a lot of time because it isn’t “infrastructure as code”. So I decided to build a complete example in Terraform.
https://medium.com/@adhorn/multi-region-serverless-backend-reloaded-1b887bc615c0
My colleague Mark van Holsteijn is currently working on a custom resource to provide support for the AWS Global Accelerator in CloudFormation. Stay tuned on our blog.

Introduction

AWS Global Accelerator is a networking service that improves the availability and performance of the applications that you offer to your global users. (Source: aws.amazon.com)
Before:
Building a global app with AWS Global Accelerator - Before
After:
Building a global app with AWS Global Accelerator - After

Architecture

A picture says more than a thousand words. So here’s the architecture of the solution we are building.
Building a global app with AWS Global Accelerator - Achitecture
The IP addresses of the Global Accelerator are “static anycast IP addresses”. So my ISP here in The Netherlands routes all traffic to this IP address immediately to the AWS optimized network. When I access the same IP and I use a VPN connection from a location near the US, the ISP of this VPN routes the traffic to the us region.
When a region has failures, within 1 minute all traffic is routed to the other region. You could test this in the failure part of this blog post. Spoiler: the fail over only works when you configure the Global Accelerator correctly…

Project setup

I’ve structured my project as follows. The module I created is for the backend. In the main.tf the modules are defined, one for eu-west-1 and one for us-east-1.
The main.tf contains:
* Local Actions; like zipping the python file
* Global Resources; like IAM roles and policies and the DynamoDB Global Table
* The Global Accelerator; the ga itself, and a listener
* An output of the IP addresses of the Global Accelerator
* And both the backend modules, for eu-west-1 and us-east-1.
The project setup:

├── backend
│   ├── alb.tf
│   ├── dynamodb.tf
│   ├── ga_endpoint_group.tf
│   ├── lambda.tf
│   └── variables.tf
├── lambda
│   ├── lambda.py
├── main.tf
├── provider.tf

Use the following commands to initialize, plan and deploy the stack:

terraform init
terraform plan
terraform apply -auto-approve

Important; do not change regions in the provider.tf when your stack is deployed. You will not be able to update or destroy the stack.

Use the service

I created a short url service. For the sake of this demo, I’ve kept the code very simple and not fool proof.
Using your browser you can generate a new shorturl:
http://ip/create/?url=https://binx.io
It will show the short url, which will return a redirect to the url you created.
The only thing left is to buy a short domain name and point it to the IP addresses of the Global Accelerator.

Failover testing

I tested the failover a couple of times. Before I found the blog post of Adrian mentioned in the intro, I created two Fargate containers. It’s hard to test the failover with Fargate, because if the ALB health check fails, AWS will recover the Fargate container. So I changed to a Lambda backend, to avoid this problem.

resource "aws_globalaccelerator_endpoint_group" "ga" {
  listener_arn = var.ga_listener
  health_check_interval_seconds = 10
  health_check_path = "/health"
  health_check_protocol = "HTTP"
  threshold_count = 2

  endpoint_configuration {
    endpoint_id = aws_alb.alb.arn
    weight      = 100
  }
}

Also found out that the endpoint_configuration weight and all health checks on the AWS Global Accelerator are required to provide a failover functionality. Otherwise, failover just doesn’t work.
If you have deployed the stack, the failover can be tested by updating the environment variable status=200 to status=500 for example. You should do this manually and not in Terraform. When you use Terraform, all backends are updated, so there will be no healthy endpoints.

  1. Check the page: /health of your GA to find out which region you’re in
  2. Create a new short url and note the short url it generated
  3. Update the lambda environment variable of the lambda function in this region
  4. Refresh a couple of times until it’s switched to the other region
  5. Test the short url, it should be replicated to the other region
    When you’re done testing:
terraform destroy -auto-approve

Conclusion

When I started this project, I checked the CloudFormation documentation to find out there was no support for the AWS Global Accelerator yet. I had two options; build custom resources, or use Terraform. Because the deployment must be done in multiple regions, I thought Terraform was a good choice. After a couple of hours I found out the aws_globalaccelerator_endpoint_group resource was not yet available. So before I start such a project again, I’ll first check if all resources are available.
A few weeks ago the resource became available, so I was able to finish the project and this blog post. After this blog post, Mark created
a CloudFormation custom provider for Global Accelerator.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts