Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amazon API Gateway GeoLocation REST API Disaster Recovery #2394

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions apigw-geo-location-failover/README.md
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please improve on the testing part and provide an example on how to verify the failover is working.

Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Amazon API Gateway GeoLocation REST API Disaster Recovery
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Amazon API Gateway GeoLocation REST API Disaster Recovery
# Multi-Region Disaster Recovery for Amazon API Gateway and AWS Lambda


Customers often want to access the resources from the same country where user resides and this pattern will help them to achieve the same. This demo also demonstrates an Amazon API Gateway multi-region active-passive public API that proxies two independent multi-region active-passive Lambda function.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Customers often want to access the resources from the same country where user resides and this pattern will help them to achieve the same. This demo also demonstrates an Amazon API Gateway multi-region active-passive public API that proxies two independent multi-region active-passive Lambda function.
This serverless application demonstrates a disaster recovery solution for Amazon API Gateway and AWS Lambda across multiple AWS regions. It showcases an active-passive setup where API Gateway and Lambda functions are deployed in two separate regions. In the event of a regional outage or disruption in the primary region, the application automatically fails over to the secondary region, ensuring continued availability and minimizing downtime.


Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the AWS Pricing page for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.

# Requirements
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add required AWS resources here as well (domain, certificate)


* Create an AWS account if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
* AWS CLI installed and configured
* Git Installed
* AWS Serverless Application Model (AWS SAM) installed


# Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:

```
git clone https://github.com/aws-samples/serverless-patterns
```


2. Change directory to:

```
cd apigw-geo-location-failover
```

3. From the command line, use AWS SAM to deploy the AWS resources for the stack as specified in the template.yml file on the primary region:

```
sam deploy -—guided —config-env primary
```

- During the prompts:

* **Stack Name:** Enter a stack name.
* **AWS Region:** Enter the desired secondary AWS Region. This stack has been tested with both us-east-1 and us-east-2. **Make sure to use a different region from the primary one but within the same country**.
* **PublicHostedZoneId:** You must have a public hosted zone in Route 53 with your domain name (i.e. mydomain.com). Enter the Hosted Zone Id for this hosted zone.
* **DomainName:** Enter your custom domain name (i.e. externalapi.mydomain.com).
* **CertificateArn** You must have an ACM certificate that covers your custom domain namespace (i.e. *.mydomain.com) on the region your are deploying this stack. Enter the ARN for this certificate here. **Make sure you are getting the certificate arn for the right region**.
* **FailoverDomainName:** Enter your failover domain name (i.e. failover.mydomain.com)
* **Priority:** Enter “SECONDARY” here
* **GeoLocationValue:** Enter the country code
* Allow SAM CLI to create IAM roles with the required permissions.
* Allow SAM CLI to create the LambdaRegionalApi Lambda function.
* **SAM configuration environment** Accept the **secondary** default value.

Once you have run `sam deploy --guided --config-env primary` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy --config-env primary` in future to use these defaults.


4. From the command line, use AWS SAM to deploy the AWS resources for the stack as specified in the template.yml file on the secondary region:

```
sam deploy —guided —config-env secondary
```

- During the prompts:

* **Stack Name:** Enter a stack name.
* **AWS Region:** Enter the desired secondary AWS Region. This stack has been tested with both us-east-1 and us-east-2. **Make sure to use a different region from the primary one but within the same country**.
* **PublicHostedZoneId:** You must have a public hosted zone in Route 53 with your domain name (i.e. mydomain.com). Enter the Hosted Zone Id for this hosted zone.
* **DomainName:** Enter your custom domain name (i.e. externalapi.mydomain.com).
* **CertificateArn** You must have an ACM certificate that covers your custom domain namespace (i.e. *.mydomain.com) on the region your are deploying this stack. Enter the ARN for this certificate here. **Make sure you are getting the certificate arn for the right region**.
* **FailoverDomainName:** Enter your failover domain name (i.e. failover.mydomain.com)
* **Priority:** Enter “SECONDARY” here
* **GeoLocationValue:** Enter the country code
* Allow SAM CLI to create IAM roles with the required permissions.
* Allow SAM CLI to create the LambdaRegionalApi Lambda function.
* **SAM configuration environment** Accept the **secondary** default value.

Once you have run `sam deploy --guided --config-env secondary` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy --config-env secondary` in future to use these defaults.

```
Note the output from the SAM deployment process. These contain details which are used for testing.
```

# How it works

1. You will deploy the same template in two separate regions:

- When you deploy template in the Primary region, it will create a custom domain name , Geolocation route of custom domain name mapped to failover route, a Primary Record for failover routing mapped to API gateway domain name and Lambda function integrated with API gateway.
- When you deploy template in the Secondary region, it will create a custom domain name, a Primary Record for failover routing mapped to API Gateway domain name and Lambda function integrated with API gateway.


2. If an issue with the primary region occurs, you can user Amazon Route53 ARC to route traffic to the secondary region.

3. This example demonstrates the failover only and does not encompass authentication and data for the multiple regions.

Testing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Testing
# Testing


Once the stack is deployed, get the custom domain name output parameter.
Paste the URL in a browser, or in Postman, or using the curl command.
Eg:

```
curl https://externalapi.mydomain.com/
```

You should see a response similar to when request made from the same country as GeoLocation:

```
{"message" : "Hello World! This is the regional API"}
```

You should see a response similar to when request made from the same country as GeoLocation:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate or something missing, no different command executed


```
Could not resolve host: https
Closing connection
curl: (6) Could not resolve host: https
```



# Cleanup

1. Delete the stack on the primary region.

```
sam delete --config-env primary
```

2. Delete the stack on the secondary region.

```
sam delete --config-env secondary
```
45 changes: 45 additions & 0 deletions apigw-geo-location-failover/example-pattern.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file is syntactically incorrect, and e.g. introBox property is missing.
See here for a reference: https://github.com/aws-samples/serverless-patterns/tree/main/_pattern-model

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"title": "Amazon API Gateway GeoLocation REST API Disaster Recovery”,
"description": "The SAM template deploys a multi-region active-passive public API that proxies two independent multi-region active-passive Lambda function ”,
"language": "Python",
"level": "200",
"framework": "SAM",
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-geo-location-failover",
"templateURL": "serverless-patterns/apigw-geo-location-failover",
"projectFolder": "apigw-geo-location-failover",
"templateFile": "template.yaml"
}
},
"deploy": {
"text": [
"sam deploy"
]
},
"testing": {
"text": [
"See the GitHub repo for detailed testing instructions."
]
},
"cleanup": {
"text": [
"Delete the stack: <code>sam delete</code>."
]
},
"authors": [
{
"name": "Manasvi Jain",
"image": "https://avatars.githubusercontent.com/u/56217984?v=4",
"bio": "Cloud Engineer at AWS",
"linkedin": "https://www.linkedin.com/in/manasvi-jain-36b9941a3/"
},
{
"name": "Umang Aggarwal",
"image": "https://avatars.githubusercontent.com/Umang071",
"bio": "Cloud Engineer II @ AWS",
"linkedin": "https://www.linkedin.com/in/umangaggarwal"
}
]
}

128 changes: 128 additions & 0 deletions apigw-geo-location-failover/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless patterns - Amazon API Gateway Custom Domain Name (uksb-1tthgi812) (tag:apigw-custom-domain-regional)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Description: Serverless patterns - Amazon API Gateway Custom Domain Name (uksb-1tthgi812) (tag:apigw-custom-domain-regional)
Description: This SAM template deploys an API Gateway with a custom domain name and configures failover and geo-location routing.


Parameters:

DomainName:
Type: String

CertificateArn:
Type: String

PublicHostedZoneId:
Type: String

FailoverDomainName:
Type: String

GeoLocationValue:
Type: String

Priority:
Type: String
Description: PRIMARY or SECONDARY
AllowedValues: ["PRIMARY", "SECONDARY"]

Conditions:
CreatePrimaryResources: !Equals
- !Ref Priority
- PRIMARY

Resources:
#Lambda function
LambdaRegionalApi:
Type: AWS::Serverless::Function
Properties:
Handler: index.lambda_handler
InlineCode: |
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message" : "Hello World! This is the regional API"})
}
Runtime: python3.9
Events:
HelloWorld:
Type: Api
Properties:
Path: /
Method: get
RestApiId:
Ref: ApiRegional

#REST Regional API
ApiRegional:
Type: AWS::Serverless::Api
Properties:
StageName: prod
EndpointConfiguration: REGIONAL

CustomDomainRegional:
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: !Ref DomainName
DomainNameConfigurations:
- SecurityPolicy: TLS_1_2
CertificateArn: !Ref CertificateArn
EndpointType: REGIONAL

MappingRegional:
Type: AWS::ApiGatewayV2::ApiMapping
DependsOn:
- CustomDomainRegional
Properties:
DomainName: !Ref DomainName
ApiId: !Ref ApiRegional
Stage: !Ref ApiRegional.Stage

HealthCheck:
Type: AWS::Route53::HealthCheck
Properties:
HealthCheckConfig:
EnableSNI: true
FullyQualifiedDomainName: !Sub ${ApiRegional}.execute-api.${AWS::Region}.amazonaws.com
Type: HTTPS
FailureThreshold: 3 ## Default is 3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FailureThreshold: 3 ## Default is 3

MeasureLatency: true ## Cannot be changed after creation
ResourcePath: /Prod

FailoverRecord:
Type: AWS::Route53::RecordSet
DependsOn:
- CustomDomainRegional
Properties:
Failover: !Ref Priority
Name: !Ref FailoverDomainName
HostedZoneId: !Ref PublicHostedZoneId
HealthCheckId: !Ref HealthCheck
SetIdentifier: !Sub ${AWS::Region}-failover
AliasTarget:
DNSName: !GetAtt CustomDomainRegional.RegionalDomainName
HostedZoneId: !GetAtt CustomDomainRegional.RegionalHostedZoneId
Type: A

GeoLocationRecord:
Condition: CreatePrimaryResources
Type: AWS::Route53::RecordSet
DependsOn:
- FailoverRecord
Properties:
GeoLocation:
CountryCode: !Ref GeoLocationValue
Name: !Ref DomainName
SetIdentifier: !Sub ${AWS::Region}-geolocation
HostedZoneId: !Ref PublicHostedZoneId
AliasTarget:
DNSName: !Ref FailoverDomainName
HostedZoneId: !Ref PublicHostedZoneId
Type: A

Outputs:

# Custom Domain Name endpoint to be used during tests
CustomDomainNameEndpoint:
Description: Custom Domain Name endpoint
Value: !Sub "https://${DomainName}"/