Skip to content

Commit

Permalink
Blog post 3 review 1 (#8)
Browse files Browse the repository at this point in the history
* blog-post-2-review-3
- Final changes

* Blog post 3 review 1 (#2)

* blog-post-3-review-1
- Initial changes

* blog-post-3-review-1
- Initial changes

* blog-post-3-review-1
- Initial changes

* blog-post-3-review-1
- Initial changes

* blog-post-3-review-1
- Initial changes

* blog-post-3-review-1
- Initial changes
  • Loading branch information
jaimenavarro authored Dec 19, 2023
1 parent 7bc83f1 commit 5f9cc47
Show file tree
Hide file tree
Showing 18 changed files with 6,622 additions and 5 deletions.
4 changes: 2 additions & 2 deletions infrastructure/blog_post_2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ npx cdk synth --debug -vv



## Step 5 - Deploy First CDK Stack
## Step 5 - Deploy First CDK Stage
This command will deploy the basic infrastructure in region us-east-1:
* Creates a VPC that spans a whole region. It will automatically divide the provided VPC CIDR range, and create public and private subnets per Availability Zone. Network routing for the public subnets will be configured to allow outbound access directly via an Internet Gateway. Network routing for the private subnets will be configured to allow outbound access via a set of resilient NAT Gateways (one per AZ).
* Fargate cluster
Expand Down Expand Up @@ -102,7 +102,7 @@ npx cdk context --clear --debug -vv
npx cdk synth --debug -vv
```

## Step 8 - Deploy Second CDK Stack
## Step 8 - Deploy Second CDK Stage
In this step, we will deploy web container tasks (web-server-container) in Fargate Cluster and its related infrastructure in (us-east-1):
* Deploys the web container tasks in Fargate Cluster
* Creates a public certificate in ACM. ( Step 6 needs to be working)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class DeployServiceStack extends Stack {
const hostedZone = this.lookUpForPublicHostedZone();
const certificate = this.createSSLCertificate(hostedZone);
const fargateAlbService = this.createApplicationLoadBalancedFargateService(cluster, certificate, props);
this.createDNSRecordForApplicationALBService(hostedZone, fargateAlbService, props);
this.createDNSRecordTypeSimple(hostedZone, fargateAlbService, props);
}

/**
Expand Down Expand Up @@ -109,13 +109,13 @@ export class DeployServiceStack extends Stack {
* @param fargateAlbService
* @param props
*/
private createDNSRecordForApplicationALBService(
private createDNSRecordTypeSimple(
hostedZone: route53.IHostedZone,
fargateAlbService: ecs_patterns.ApplicationLoadBalancedFargateService,
props: StackProps
) {
// Create DNS A Record to reach our service
new route53.ARecord(this, 'Record', {
new route53.ARecord(this, 'record-simple', {
zone: hostedZone,
recordName: AppConfig.INTERNAL_DNS + '-' + props.env?.region,
target: route53.RecordTarget.fromAlias(new LoadBalancerTarget(fargateAlbService.loadBalancer)),
Expand Down
12 changes: 12 additions & 0 deletions infrastructure/blog_post_3/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out
cdk.context.json

# IntelliJ
.idea/**
6 changes: 6 additions & 0 deletions infrastructure/blog_post_3/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
6 changes: 6 additions & 0 deletions infrastructure/blog_post_3/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"semi": true,
"trailingComma": "none",
"singleQuote": true,
"printWidth": 120
}
145 changes: 145 additions & 0 deletions infrastructure/blog_post_3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Guide to deploy this infrastructure on AWS

## Step 0 - Install dependencies
- AWS account credentials
- Install AWS CLI https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
- Get AWS credentials https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html
- NodeJS installation https://nodejs.org/en/download/

## Step 1 - Confirm AWS credentials
After getting AWS credentials, you will need to make sure that you pick the right ones(if you have more than one):
```bash
aws configure list-profiles
export AWS_DEFAULT_PROFILE=xxxxxxxxxx
export AWS_DEFAULT_REGION=us-east-1
```
Confirm AWS credentials are working by running the following commands:
```bash
aws configure list
aws sts get-caller-identity
```

## Step 2 - Configuration
> **Warning** Update the default public DNS domain (_subdomain-**2**.subdomain-**1**.cloudns.ph_) with your own domain name.
In [ClouDNS](https://www.cloudns.net) set up the following:
* Create a free DNS Hosted Zone (Example case: subdomain-**xx**.cloudns.ph)

In this GitHub repository, update the [configuration file](./config/environment.ts) with your own public domain name.
* DNS_ZONE_NAME: "_subdomain-2.subdomain-**xx**.cloudns.ph_"

```javascript
export const AppConfig = {
VPC_NAME: 'vpc-web-container',
CLUSTER_NAME: 'fargate-cluster-web-container',
APP_NAME: 'app-region-evacuation',
DNS_ZONE_NAME: 'subdomain-2.subdomain-1.cloudns.ph',
INTERNAL_DNS: 'web-container',
DOCKER_IMAGE: 'jaimenavarro/web-container'
};
```

## Step 3 - Build
These are the following steps to build the project:
* Make sure you are in the right folder
```bash
cd infrastructure/blog_post_3
```
* Install javascript dependencies
```bash
npm install -dd
npm run build -dd
```

## Step 4 - Setting up AWS CloudFormation
* It sets up the necessary AWS resources and configurations required to deploy your CDK stacks in CloudFormation.
```bash
npx cdk bootstrap --debug -vv --region us-east-1
npx cdk bootstrap --debug -vv --region us-east-2
```

* AWS CDK Synth the project
```bash
npx cdk context --clear
npx cdk synth --debug -vv
```



## Step 5 - Deploy First CDK Stage
This command will deploy the basic infrastructure in region us-east-1, us-east-2:
* Creates a VPC that spans a whole region. It will automatically divide the provided VPC CIDR range, and create public and private subnets per Availability Zone. Network routing for the public subnets will be configured to allow outbound access directly via an Internet Gateway. Network routing for the private subnets will be configured to allow outbound access via a set of resilient NAT Gateways (one per AZ).
* Fargate cluster
* Route53 DNS public zone

```bash
npx cdk deploy stage-1/* --debug -vv --require-approval never
```
You can review the status of your CDK deployment from AWS console
* [CloudFormation us-east-1](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1)
* [CloudFormation us-east-2](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-2)

## Step 6 - Configure ClouDNS with the NS records from AWS route53
Go to [AWS Route 53](https://us-east-1.console.aws.amazon.com/route53/v2/hostedzones) the hosted zone created in the previous step.
Copy the NS records related to the authoritative DNS servers.
* Example values:
```
ns-231.awsdns-28.com.
ns-1965.awsdns-53.co.uk.
ns-1055.awsdns-03.org.
ns-724.awsdns-26.net.
```

Go to your account in [ClouDNS](https://www.cloudns.net/) and open your free DNS zone (For our example was subdomain-**xx**.cloudns.ph). We will add four NS records, one for each authoritative DNS servers
* Type: NS record
* Host: subdomain-2.subdomain-**xx**.cloudns.ph
* Points to: ns-231.awsdns-28.com

You can confirm that the NS records are working fine by using the following online tool. **Keep in mind to use your own domain name. (For our example was subdomain-**xx**.cloudns.ph)**
* https://dnschecker.org/#NS/subdomain-2.subdomain-1.cloudns.ph

## Step 7 - Update CDK Context with the new resources
After creating basic infrastructure in the previous step we need to recreate the file cdk.context.json, which keeps information of the infrastructure in AWS, for that purpose we will use the following commands:
```bash
npx cdk context --clear --debug -vv
npx cdk synth --debug -vv
```

## Step 8 - Deploy Second CDK Stage
In this step, we will deploy web container tasks (web-server-container) in Fargate Cluster and its related infrastructure in (us-east-1, us-east-2):
* Deploys the web container tasks in Fargate Cluster
* Creates a public certificate in ACM. ( Step 6 needs to be working)
* Creates Application Load Balancer with the previously created certificate
* Creates Route53 DNS records to reach the web container.

```bash
cdk deploy stage-2/* --debug -vv --require-approval never
```
You can review the status of your CDK deployment from AWS console:
* [CloudFormation us-east-1](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1)
* [CloudFormation us-east-2](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-2)

## Validations Steps
You can use the following online resources to confirm that your public endpoint is available and the certificate is valid.
> **Warning** Update the following domains with your own domain name.
* Online DNS validation tool:
* https://dnschecker.org/#A/web-container-us-east-1.subdomain-2.subdomain-1.cloudns.ph
* https://dnschecker.org/#A/web-container-us-east-2.subdomain-2.subdomain-1.cloudns.ph
* https://dnschecker.org/#A/latency-endpoint.subdomain-2.subdomain-1.cloudns.ph
* Online SSL/TLS validation tool:
* https://www.sslshopper.com/ssl-checker.html#hostname=https://web-container-us-east-1.subdomain-2.subdomain-1.cloudns.ph/
* https://www.sslshopper.com/ssl-checker.html#hostname=https://web-container-us-east-2.subdomain-2.subdomain-1.cloudns.ph/
* https://www.sslshopper.com/ssl-checker.html#hostname=https://latency-endpoint.subdomain-2.subdomain-1.cloudns.ph/
```bash
curl -v https://web-container-us-east-1.subdomain-2.subdomain-1.cloudns.ph
curl -v https://web-container-us-east-2.subdomain-2.subdomain-1.cloudns.ph
curl -v https://latency-endpoint.subdomain-2.subdomain-1.cloudns.ph
```

## Remove all resources from your AWS account
In order to remove all the resources go to your [cloudformation console](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1) and delete the stacks in the inverse order:
1. stage-2/app-region-evacuation-service-us-east-1 (*app-region-evacuation-service*)
2. Remove the DNS records with type CNAME in [Route 53](https://us-east-1.console.aws.amazon.com/route53/v2/hostedzones?region=us-east-1#) created by Certificates Manager
3. stage-1/app-region-evacuation-basic-infrastructure-us-east-1 (*app-region-evacuation-basic-infrastructure*)


20 changes: 20 additions & 0 deletions infrastructure/blog_post_3/bin/app-region-evacuation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { DeployServiceStage } from '../lib/stage-2/stages/deploy-service-stage';
import { DeployBasicInfrastructureStage } from '../lib/stage-1/stages/deploy-basic-infrastructure-stage';

const app = new cdk.App();

new DeployBasicInfrastructureStage(app, 'stage-1', {
env: {
account: process.env.CDK_DEPLOY_ACCOUNT ?? process.env.CDK_DEFAULT_ACCOUNT
},
stage: 'stage-1'
});

new DeployServiceStage(app, 'stage-2', {
env: {
account: process.env.CDK_DEPLOY_ACCOUNT ?? process.env.CDK_DEFAULT_ACCOUNT
},
stage: 'stage-2'
});
43 changes: 43 additions & 0 deletions infrastructure/blog_post_3/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"app": "npx ts-node --prefer-ts-exts bin/app-region-evacuation.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false
}
}
15 changes: 15 additions & 0 deletions infrastructure/blog_post_3/config/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Shared values that are the same across all environments
export const AppConfig = {
VPC_NAME: 'vpc-web-container',
CLUSTER_NAME: 'fargate-cluster-web-container',
APP_NAME: 'app-region-evacuation',
DNS_ZONE_NAME: 'subdomain-2.subdomain-1.cloudns.ph',
INTERNAL_DNS: 'web-container',
DOCKER_IMAGE: 'jaimenavarro/web-container',
LATENCY_DNS_RECORD: 'latency-endpoint'
};

// Regions where the app will be deployed (stage-1 and stage-2)
export const TargetRegions = ['us-east-1', 'us-east-2'];

export const PRIMARY_REGION = 'us-east-1';
8 changes: 8 additions & 0 deletions infrastructure/blog_post_3/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import route53 = require('aws-cdk-lib/aws-route53');
import ec2 = require('aws-cdk-lib/aws-ec2');
import ecs = require('aws-cdk-lib/aws-ecs');
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { AppConfig, PRIMARY_REGION } from '../../../config/environment';

/**
* Stack for deploying the basic infrastructure in one region
* 1. Create Route53 Public Hosted Zone
* 2. Create VPC and ECS Cluster
*/
export class DeployBasicInfrastructureStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
// It's a global resource, so we only need to create once
if (props?.env?.region === PRIMARY_REGION) {
this.createRoute53PublicHostedZone();
}
// Create VPC in each region
const vpc = new ec2.Vpc(this, 'MyVpc', { vpcName: AppConfig.VPC_NAME, maxAzs: 2 });
// Create ECS Cluster in each region
new ecs.Cluster(this, 'Cluster', { clusterName: AppConfig.CLUSTER_NAME, vpc });
}

/**
* Create Route53 Public Hosted Zone
*/
private createRoute53PublicHostedZone() {
new route53.PublicHostedZone(this, 'create-dns-zone.cloudns.ph', {
zoneName: AppConfig.DNS_ZONE_NAME,
comment: 'Web container public hosted zone'
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Stage, StageProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { AppConfig, TargetRegions } from '../../../config/environment';
import { DeployBasicInfrastructureStack } from '../stacks/deploy-basic-infrastructure-stack';

interface DeployBasicInfrastructureStageProps extends StageProps {
stage: string;
}

/**
* Stage for deploying the basic infrastructure in all the regions
* 1. Create Route53 Public Hosted Zone
* 2. Create VPC and ECS Cluster in each region
*/
export class DeployBasicInfrastructureStage extends Stage {
constructor(scope: Construct, id: string, props: DeployBasicInfrastructureStageProps) {
super(scope, id, props);
for (let region of TargetRegions) {
new DeployBasicInfrastructureStack(this, `${AppConfig.APP_NAME}-basic-infrastructure-${region}`, {
terminationProtection: false,
env: {
region: region,
account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT
},
stackName: `${AppConfig.APP_NAME}-basic-infrastructure`
});
}
}
}
Loading

0 comments on commit 5f9cc47

Please sign in to comment.