Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
OAwan committed Jul 8, 2020
1 parent 89d66bb commit 9b2441c
Show file tree
Hide file tree
Showing 13 changed files with 12,255 additions and 0 deletions.
11 changes: 11 additions & 0 deletions 05-oawan/demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.js
!jest.config.js
*.d.ts
node_modules

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

# Parcel default cache directory
.parcel-cache
6 changes: 6 additions & 0 deletions 05-oawan/demo/.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
14 changes: 14 additions & 0 deletions 05-oawan/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Easy CDK deploy ECS Fargate Demo

This is a demo that use CDK to build **ECS Fargate Task Definition**, **ECS Service**, **Log Group**, **Security Group**, **ELB**...etc.

> Note: Base on existion Network Stack or Default.
## Useful commands

* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk synth` emits the synthesized CloudFormation template
19 changes: 19 additions & 0 deletions 05-oawan/demo/bin/cdk-fargate-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env node
import * as readlineSync from 'readline-sync';
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { CdkFargateDemoStack } from '../lib/cdk-fargate-demo-stack';

if (!process.env['ENV_ACCOUNT'] || !process.env['ENV_REGION']) {
process.env['ENV_ACCOUNT'] = readlineSync.question('> 請輸入 aws account id: ');
process.env['ENV_REGION'] = readlineSync.question('> 請輸入 stack 建立之 region (default: ap-northeast-1): ') || 'ap-northeast-1';
process.env['VPC_NAME'] = readlineSync.question('> 請輸入以建立的 VPC name (default: default): ');
}

const app = new cdk.App();
new CdkFargateDemoStack(app, 'CdkFargateDemoStack', {
env: {
account: process.env['ENV_ACCOUNT'],
region: process.env['ENV_REGION']
}
});
64 changes: 64 additions & 0 deletions 05-oawan/demo/cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"vpc-provider:account=084664864843:filter.isDefault=true:region=ap-northeast-1:returnAsymmetricSubnets=true": {
"vpcId": "vpc-fcf4459b",
"vpcCidrBlock": "172.31.0.0/16",
"availabilityZones": [],
"subnetGroups": [
{
"name": "Public",
"type": "Public",
"subnets": [
{
"subnetId": "subnet-a0b5ffe9",
"cidr": "172.31.32.0/20",
"availabilityZone": "ap-northeast-1a",
"routeTableId": "rtb-0b300e6c"
},
{
"subnetId": "subnet-32991f69",
"cidr": "172.31.0.0/20",
"availabilityZone": "ap-northeast-1c",
"routeTableId": "rtb-0b300e6c"
},
{
"subnetId": "subnet-14a8863c",
"cidr": "172.31.16.0/20",
"availabilityZone": "ap-northeast-1d",
"routeTableId": "rtb-0b300e6c"
}
]
}
]
},
"vpc-provider:account=084664864843:filter.tag:Name=alpha:region=ap-northeast-1:returnAsymmetricSubnets=true": {
"vpcId": "vpc-05900fcaa6ee08b33",
"vpcCidrBlock": "172.32.0.0/16",
"availabilityZones": [],
"subnetGroups": [
{
"name": "Private",
"type": "Private",
"subnets": [
{
"subnetId": "subnet-049a09f8c50809857",
"cidr": "172.32.111.0/24",
"availabilityZone": "ap-northeast-1c",
"routeTableId": "rtb-0330d717fdf6f4ca8"
}
]
},
{
"name": "Public",
"type": "Public",
"subnets": [
{
"subnetId": "subnet-01af5aba6cbd72d20",
"cidr": "172.32.11.0/24",
"availabilityZone": "ap-northeast-1a",
"routeTableId": "rtb-0330d717fdf6f4ca8"
}
]
}
]
}
}
7 changes: 7 additions & 0 deletions 05-oawan/demo/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"app": "npx ts-node bin/cdk-fargate-demo.ts",
"context": {
"@aws-cdk/core:enableStackNameDuplicates": "true",
"aws-cdk:enableDiffNoFail": "true"
}
}
7 changes: 7 additions & 0 deletions 05-oawan/demo/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
154 changes: 154 additions & 0 deletions 05-oawan/demo/lib/cdk-fargate-demo-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import * as cdk from '@aws-cdk/core';
import * as iam from '@aws-cdk/aws-iam';
import * as ecs from '@aws-cdk/aws-ecs';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as log from '@aws-cdk/aws-logs';
import * as elb from '@aws-cdk/aws-elasticloadbalancingv2';
import * as ecr from '@aws-cdk/aws-ecr';

const stackPolicy = {
removalPolicy: cdk.RemovalPolicy.DESTROY,
};

export class CdkFargateDemoStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// Env Args
const { PROJ_NAME = 'demo', VPC_NAME } = process.env;

// VPC
const vpc_opts = !!VPC_NAME ? { vpcName: VPC_NAME } : { isDefault: true }; // use specified or default vpc
const vpc = ec2.Vpc.fromLookup(this, `${PROJ_NAME}-vpc`, vpc_opts);

// Subnet (Public Subnet),需綁定為指向 natgateway 之 route table
const public_subnet_1 = ec2.Subnet.fromSubnetAttributes(this, `${PROJ_NAME}-public-subnet-1`, {
availabilityZone: 'ap-northeast-1c',
subnetId:'subnet-049a09f8c50809857',
routeTableId: 'rtb-0330d717fdf6f4ca8'
});
const public_subnet_2 = ec2.Subnet.fromSubnetAttributes(this, `${PROJ_NAME}-public-subnet-2`, {
availabilityZone: 'ap-northeast-1c',
subnetId:'subnet-093901b3ac2a36f85',
routeTableId: 'rtb-0330d717fdf6f4ca8'
});

// Security Group
const securityGroup = new ec2.SecurityGroup(this, `${PROJ_NAME}-security-group`, {
vpc,
allowAllOutbound: true,
securityGroupName: PROJ_NAME,
});
// Add Inbound
securityGroup.addIngressRule(ec2.Peer.ipv4('172.32.0.0/16'), ec2.Port.allTraffic(), 'VPC-Alpha');
securityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/16'), ec2.Port.allTraffic(), 'ALL');
// securityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/32'), ec2.Port.tcp(80), 'Office');
// ... Other Inbound ...

// Log Group
const logGroup = new log.LogGroup(this, `${PROJ_NAME}-log-group`, {
...stackPolicy,
logGroupName: `/ecs/${PROJ_NAME}`,
retention: log.RetentionDays.INFINITE, // The number of days to retain the log events in the specified log group.
});

// ELB - Target Group
const targetGroup = new elb.ApplicationTargetGroup(this, `${PROJ_NAME}-target-group`, {
vpc,
targetGroupName: PROJ_NAME,
targetType: elb.TargetType.IP,
protocol: elb.ApplicationProtocol.HTTP,
port: 80,

// Customize healthCheck with your Service
// healthCheck: {
// path: '/ping',
// healthyThresholdCount: 5,
// unhealthyThresholdCount: 2,
// timeout: cdk.Duration.seconds(5),
// interval: cdk.Duration.seconds(30),
// healthyHttpCodes: '200',
// },
});

// ELB - Load Balancer
const loadBalancer = new elb.ApplicationLoadBalancer(this, `${PROJ_NAME}-load-balancer`, {
vpc,
securityGroup,
internetFacing: true, // for Public facing
ipAddressType: elb.IpAddressType.IPV4,
loadBalancerName: PROJ_NAME,
vpcSubnets: {
subnets: [public_subnet_1, public_subnet_2],
},
});
// Add Listener
loadBalancer.addListener(`${PROJ_NAME}-listener`, {
protocol: elb.ApplicationProtocol.HTTP,
port: 80,
defaultTargetGroups: [targetGroup],
});

// ECR
const ecrRepo = ecr.Repository.fromRepositoryName(this, `${PROJ_NAME}-ecr`, 'amazon-ecs-sample');

// ECS - Fargate Task Definition
const account = props?.env?.account || '';
const taskRole = iam.Role.fromRoleArn(
this,
`${PROJ_NAME}-task-role`,
`arn:aws:iam::${account}:role/ecsTaskExecutionRole`,
{
mutable: false,
},
);
const fargateTaskDefinition = new ecs.FargateTaskDefinition(this, `${PROJ_NAME}-task-definition`, { // or use TaskDefinition and specified compatibility to FARGATE
family: PROJ_NAME,
memoryLimitMiB: 2048,
cpu: 1024,
taskRole,
executionRole: taskRole,
});
// Add Container
fargateTaskDefinition.addContainer(`${PROJ_NAME}-container`, {
// Use an image from ECR repo
image: ecs.ContainerImage.fromEcrRepository(ecrRepo, 'latest'),

// Use an image from DockerHub
// image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),

cpu: 1024,
environment: {
AWS_DEFAULT_REGION: 'ap-northeast-1',
// ... env args ...
},
memoryReservationMiB: 500,
memoryLimitMiB: 2048,

// 指定 logging group
logging: new ecs.AwsLogDriver({
streamPrefix: 'ecs',
logGroup,
}),
})
// Add listen port
.addPortMappings({
containerPort: 80,
hostPort: 80,
});

// ECS - Fargate Service
const cluster = new ecs.Cluster(this, `${PROJ_NAME}-cluster`, { vpc });
const svc = new ecs.FargateService(this, `${PROJ_NAME}-service`, {
cluster,
taskDefinition: fargateTaskDefinition
});

// Let loadbalancer loadbalance to this Service of the TargetGroup
targetGroup.addTarget(svc);

new cdk.CfnOutput(this, `${PROJ_NAME}-url`, {
value: `https://${loadBalancer.loadBalancerDnsName}`
});
}
}
Loading

0 comments on commit 9b2441c

Please sign in to comment.