Skip to content

Commit bad7967

Browse files
authored
Merge pull request #1716 from nihilg/nihilg-feature-aurora-serverless-global-db-cdk
New serverless pattern - Amazon Aurora Serverless V2 Primary to Secondary Global Database
2 parents 097e08a + d99c74a commit bad7967

16 files changed

+771
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
!jest.config.js
2+
*.d.ts
3+
node_modules
4+
.DS_Store
5+
package-lock.json
6+
7+
# CDK asset staging directory
8+
.cdk.staging
9+
cdk.out
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Amazon Aurora Serverless V2 Primary to Secondary Global Database
2+
The pattern creates a serverless global database cluster enabling data replication from the primary to secondary cluster. The regional primary cluster contains a serverless db instance supporting both writes and reads. The regional secondary cluster contains a serverless db instance supporting only reads. In the unlikely event of a regional degradation or outage, the secondary region can be promoted to read and write capabilities in less than 1 minute. Also the pattern adopts the multiple stack capability of CDK to provision the resources across the primary and secondary regions. You can deploy each stack indvidually or deploy all the stacks using --all option.
3+
4+
Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >>
5+
6+
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](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
7+
8+
## Requirements
9+
10+
* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) 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.
11+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
12+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
13+
* [Node and NPM](https://nodejs.org/en/download/) installed.
14+
* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) installed and configured
15+
16+
## Deployment Instructions
17+
18+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
19+
```
20+
git clone https://github.com/aws-samples/serverless-patterns
21+
```
22+
2. Change directory to the pattern directory:
23+
```
24+
cd aurora-serverless-global-db-cdk
25+
```
26+
3. Install dependencies:
27+
```
28+
npm install
29+
```
30+
4. Configure AWS CDK to bootstrap the AWS account, primary region and secondary region :
31+
```
32+
cdk bootstrap 111111111111/eu-west-1
33+
cdk bootstrap 111111111111/eu-west-2
34+
```
35+
5. From the command line, use AWS CDK to deploy the all the stacks synthesized:
36+
```
37+
cdk deploy --all
38+
```
39+
Alternatively you can also deploy each stack individually. From the command line, use AWS CDK to deploy each stack:
40+
```
41+
cdk deploy aurora-global-cluster
42+
cdk deploy primary-cluster
43+
cdk deploy secondary-cluster
44+
cdk deploy primary-test-app
45+
cdk deploy secondary-test-app
46+
```
47+
7. Note the outputs from the CDK deployment process. These contain the primary and secondary URLs which are used for testing.
48+
49+
## How it works
50+
51+
- The template in this pattern synthesizes five stacks for deployment using the multiple stack approach of CDK.
52+
- The first stack named aurora-global-cluster creates the Aurora Global Cluster.
53+
- The second stack named primary-cluster deploys the primary cluster with a serverless v2 instance in the primary region defined.
54+
- The third stack named secondary-cluster deploys the secondary cluster with a serverless v2 instance in the secondary region defined.
55+
- The fourth and fifth stack named primary-test-app and secondary-test-app deploys a fargate container with a nodejs app for testing the global database tables.
56+
- The primary cluster supports both write and read operations. The secondary cluster supports read operation only.
57+
- Once you deploy all the stacks, you have built a global database that automatically replicates data from the primary to the secondary region.
58+
59+
## Testing
60+
61+
Note down the primary-test-app.FargateServiceURL and secondary-test-app.FargateServiceURL values from the CDK output and update them in each of the test commands below.
62+
63+
1. Initialize the Global Database by creating a table
64+
65+
```
66+
curl primary-test-app.FargateServiceURL/init
67+
```
68+
69+
Expected Response :
70+
"Task table created.."
71+
72+
2. Write a task into the Primary Cluster
73+
```
74+
curl -X POST primary-test-app.FargateServiceURL/tasks -H 'Content-Type: application/json' -d '{"name":"Task1","status":"created"}'
75+
```
76+
Expected Response : Task added with ID: 1
77+
3. Read the tasks from the Secondary cluster
78+
```
79+
curl secondary-test-app.FargateServiceURL/tasks
80+
```
81+
Expected Response :
82+
[{"id":1,"name":"Task1","status":"created"}]
83+
84+
4. Attempt to write a task into the Secondary cluster
85+
```
86+
curl -X POST secondary-test-app.FargateServiceURL/tasks -H 'Content-Type: application/json' -d '{"name":"Task1","status":"created"}'
87+
```
88+
Expected Response : error : cannot execute INSERT in a read-only transaction
89+
90+
Note : You can enable Write forwarding feature to continue to use the Secondary cluster endpoint for write transactions as well.
91+
92+
5. You can also try to update and delete the task on the Primary cluster
93+
```
94+
curl -X PUT primary-test-app.FargateServiceURL/tasks/1 -H 'Content-Type: application/json' -d '{"name":"Task1","status":"in-progress"}'
95+
96+
curl -X DELETE primary-test-app.FargateServiceURL/tasks/1
97+
98+
```
99+
6. Check if the task is deleted from the Secondary cluster
100+
```
101+
curl secondary-test-app.FargateServiceURL/tasks
102+
```
103+
Expected Response :
104+
[]
105+
106+
## Cleanup
107+
108+
1. Delete the stack
109+
```
110+
cdk destroy --all
111+
```
112+
----
113+
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
114+
115+
SPDX-License-Identifier: MIT-0
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { App } from 'aws-cdk-lib';
2+
import { AuroraGlobalClusterStack } from '../lib/aurora-global-cluster-stack';
3+
import { AuroraRegionalClusterStack } from '../lib/aurora-regional-cluster-stack';
4+
import { FargateTestAppStack } from '../lib/fargate-test-app-stack';
5+
6+
const app = new App();
7+
8+
const account = app.node.tryGetContext('account') || process.env.CDK_INTEG_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT;
9+
const primaryRegion = { account: account, region: 'eu-west-1' };
10+
const secondaryRegion = { account: account, region: 'eu-west-2' };
11+
12+
const globalCluster = new AuroraGlobalClusterStack(app, "aurora-global-cluster", {
13+
env: primaryRegion
14+
});
15+
16+
const primaryclusterstack = new AuroraRegionalClusterStack(app, `primary-cluster`, {
17+
env: primaryRegion, cfnGlobalCluster: globalCluster.cfnGlobalCluster, isPrimary: true
18+
});
19+
20+
const secondaryclusterstack = new AuroraRegionalClusterStack(app, `secondary-cluster`, {
21+
env: secondaryRegion, cfnGlobalCluster: globalCluster.cfnGlobalCluster, isPrimary: false
22+
});
23+
24+
primaryclusterstack.addDependency(globalCluster);
25+
secondaryclusterstack.addDependency(primaryclusterstack)
26+
27+
const primarytestappstack = new FargateTestAppStack(app, `primary-test-app`, {
28+
env: primaryRegion,
29+
endpoint: primaryclusterstack.endpoint,
30+
port: primaryclusterstack.port,
31+
vpc: primaryclusterstack.vpc,
32+
isPrimary: true,
33+
region: primaryclusterstack.region,
34+
dbSecurityGroupId: primaryclusterstack.dbSecurityGroupId
35+
});
36+
37+
const secondarytestappstack = new FargateTestAppStack(app, `secondary-test-app`, {
38+
env: secondaryRegion,
39+
endpoint: secondaryclusterstack.endpoint,
40+
port: secondaryclusterstack.port,
41+
vpc: secondaryclusterstack.vpc,
42+
isPrimary: false,
43+
region: primaryclusterstack.region,
44+
dbSecurityGroupId: secondaryclusterstack.dbSecurityGroupId
45+
});
46+
47+
primarytestappstack.addDependency(primaryclusterstack);
48+
secondarytestappstack.addDependency(secondaryclusterstack);
49+
50+
app.synth();
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/aurora-global-db-multistack.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
21+
"@aws-cdk/core:checkSecretUsage": true,
22+
"@aws-cdk/core:target-partitions": [
23+
"aws",
24+
"aws-cn"
25+
],
26+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
29+
"@aws-cdk/aws-iam:minimizePolicies": true,
30+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
31+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
32+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
33+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
34+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
35+
"@aws-cdk/core:enablePartitionLiterals": true,
36+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
37+
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
38+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
39+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
40+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
41+
"@aws-cdk/aws-route53-patters:useCertificate": true,
42+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
43+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
44+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
45+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
46+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
47+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
48+
"@aws-cdk/aws-redshift:columnId": true,
49+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
50+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
51+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
52+
"@aws-cdk/aws-kms:aliasNameRef": true,
53+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
54+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
55+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true
56+
}
57+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"title": "Amazon Aurora Serverless Primary to Secondary Global Database",
3+
"description": "Create an Aurora Serverless Global database to replicate across regions",
4+
"language": "TypeScript",
5+
"level": "300",
6+
"framework": "CDK",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"The pattern provisions an Amazon Aurora serverless v2 global database enabling data replication from the primary to secondary region. The regional primary cluster contains a serverless db instance and supports both writes and reads. The regional secondary cluster contains a serverless db instance and supports only reads. In the unlikely event of a regional degradation or outage, the secondary region can be promoted to read and write capabilities in less than 1 minute",
11+
"Also the pattern adopts the multiple stack capability of CDK to provision the resources across the primary and secondary regions."
12+
]
13+
},
14+
"gitHub": {
15+
"template": {
16+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/aurora-serverless-global-db-cdk",
17+
"templateURL": "serverless-patterns/aurora-serverless-global-db-cdk",
18+
"projectFolder": "aurora-serverless-global-db-cdk",
19+
"templateFile": "aurora-serverless-global-db-cdk/lib/aurora-regional-cluster-stack.ts"
20+
}
21+
},
22+
"resources": {
23+
"bullets": [
24+
{
25+
"text": "Using Aurora Serverless V2",
26+
"link": "https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.html"
27+
},
28+
{
29+
"text": "Amazon Aurora Global Database",
30+
"link": "https://aws.amazon.com/rds/aurora/global-database/"
31+
}
32+
]
33+
},
34+
"deploy": {
35+
"text": [
36+
"cdk deploy --all"
37+
]
38+
},
39+
"testing": {
40+
"text": [
41+
"See the GitHub repo for detailed testing instructions."
42+
]
43+
},
44+
"cleanup": {
45+
"text": [
46+
"Delete the stack: <code>cdk destroy --all</code>."
47+
]
48+
},
49+
"authors": [
50+
{
51+
"name": "Nihilson Gnanadason",
52+
"image": "https://drive.google.com/file/d/1m82LvtdoipI9nI_q2G6qoRGpZ36JNzHU/view?usp=sharing",
53+
"bio": "Nihilson is a Sr.Solutions Architect at AWS working with ISVs in the UK to build, run, and scale their software products on AWS.",
54+
"linkedin": "https://www.linkedin.com/in/nihilson/"
55+
}
56+
]
57+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM --platform=linux/amd64 node:16-alpine
2+
WORKDIR /usr
3+
COPY package.json ./
4+
COPY src ./src
5+
RUN npm install
6+
RUN npm install pg
7+
COPY . .
8+
EXPOSE 80
9+
CMD ["npm","start"]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "fargate",
3+
"version": "1.0.0",
4+
"description": "Fargate ECS container to run an express app",
5+
"main": "src/index.js",
6+
"scripts": {
7+
"build": "tsc",
8+
"start": "node src/index.js"
9+
},
10+
"author": "nihilson",
11+
"license": "ISC",
12+
"dependencies": {
13+
"express": "^4.18.2",
14+
"pg": "^8.11.3",
15+
"aws-sdk": "latest"
16+
}
17+
}

0 commit comments

Comments
 (0)