内容
下記の構成をCDKで構築します。
-
VPC
VPC、サブネットを作成します。作成した情報を他のスタックからクロススタック参照出来るようにします。 -
Route53
ECSスタックの中で既存ホストゾーンにALBのAレコード(Alias)を追加しています。 -
ALB,ECS
aws-ecs-patternsというモジュールがあります。こちらは一般的な構成パラメータがデフォルト値となっており、少ないパラメータでECSを構築することが可能となります。こちらをベースにコードをカスタマイズしていきます。ALBもこの中で作成されます。nginxのイメージを使用します。
上記の通り、CloudFormationで600行程度のYAMLを数行で書くことが可能です。
- Aurora,Secret Manger
VPCスタックの情報を使用してサブネットグループ、セキュリティグループを作成します。
シングル構成のAuroraを作成します。デフォルトではパスワードはSecret Managerに保存されます。なおFargate、Aurora間の接続確認は未実施です。
準備
mkdir app01
cd app01
cdk init --language typescript
エントリポイント
bin/app01.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { VpcStack } from '../lib/vpc-stack';
import { EcsStack } from '../lib/ecs-stack';
import { RdsStack } from '../lib/rds-stack';
const app = new cdk.App();
const vpcStack = new VpcStack(app, 'VpcStack', {
env: {
account: 'AWS_ACCOUNT',
region: 'ap-northeast-1',
},
});
new EcsStack(app, 'EcsStack', {
//変数を渡す
vpc: vpcStack.vpc,
env: {
account: 'AWS_ACCOUNT',
region: 'ap-northeast-1',
},
});
new RdsStack(app, 'RdsStack', {
//変数を渡す
vpc: vpcStack.vpc,
env: {
account: 'AWS_ACCOUNT',
region: 'ap-northeast-1',
},
});
VPCスタック
lib/vpc-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Vpc } from 'aws-cdk-lib/aws-ec2';
export class VpcStack extends Stack {
//別スタックから参照できるようにする
public readonly vpc: Vpc;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const vpc_name = 'cdk-vpc';
const cidr = '10.1.0.0/16';
this.vpc = new ec2.Vpc(this, 'VPC', {
vpcName: vpc_name,
cidr: cidr,
maxAzs: 2,
subnetConfiguration: [
{
cidrMask: 24,
name: `${vpc_name}-public`,
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: `${vpc_name}-private`,
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
]
})
}
};
ECSスタック
lib/ecs-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Vpc } from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';
import * as route53 from 'aws-cdk-lib/aws-route53';
//VpcStackの変数を扱えるようにする
interface SubStackProps extends StackProps {
vpc: Vpc;
};
export class EcsStack extends Stack {
//SubStackPropsを使用する
constructor(scope: Construct, id: string, props: SubStackProps) {
super(scope, id, props);
//変数設定
const ecs_vpc = props.vpc;
const domain_name = 'DOMAIN_NAME'
//Domain名設定
const domainZone = route53.HostedZone.fromLookup(this, 'Zone', {
domainName: 'DOMAIN_ZONE'
});
//Cluster設定
const cluster = new ecs.Cluster(this, 'Cluster', {
clusterName: 'WebApp01-Cluster',
vpc: ecs_vpc,
})
//ELB+Fargate設定
new ecsp.ApplicationLoadBalancedFargateService(this, 'WebApp01', {
cluster,
domainName: domain_name,
domainZone,
memoryLimitMiB: 512,
desiredCount: 2,
cpu: 256,
assignPublicIp: true,
loadBalancerName: 'WebApp01-lb01',
publicLoadBalancer: true,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('nginx'),
},
});
}
};
RDSスタック
lib/rds-stack.ts
import { RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Peer, Port, SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
//VpcStackの変数を扱えるようにする
interface SubStackProps extends StackProps {
vpc: Vpc;
};
export class RdsStack extends Stack {
constructor(scope: Construct, id: string, props: SubStackProps) {
super(scope, id, props);
//VPC取得
const vpc = props.vpc;
//Subnet取得
const private_subnet = vpc.selectSubnets({
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
}).subnets
const public_subnet = vpc.selectSubnets({
subnetType: ec2.SubnetType.PUBLIC,
}).subnets
//SubnetGroup作成
const subnetGroup = new rds.SubnetGroup(this, 'SubnetGroup', {
description: 'aurora subnet group for WebApp01',
vpc: vpc,
vpcSubnets: {
subnets: private_subnet,
}
});
//SecurityGroup作成
const secgroup01 = new SecurityGroup(this, 'SecGroup', {
vpc: vpc,
});
//SecurityGroupにPublic SubnetからのIngressルール追加
for (const elm of public_subnet) {
secgroup01.addIngressRule(
Peer.ipv4(elm.ipv4CidrBlock),
Port.tcp(3306),
)};
//RDS作成
const cluster = new rds.DatabaseCluster(this, 'AuroraDB', {
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_2_10_2
}),
credentials: rds.Credentials.fromGeneratedSecret('admin'),
defaultDatabaseName: 'database1',
instanceProps: {
vpc,
publiclyAccessible: false,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.BURSTABLE3,
ec2.InstanceSize.SMALL),
securityGroups: [secgroup01],
vpcSubnets: {
subnets: private_subnet,
},
},
deletionProtection: false,
iamAuthentication: true,
instances: 1,
preferredMaintenanceWindow: 'Sat:16:00-Sat:16:30',
removalPolicy: RemovalPolicy.DESTROY,
subnetGroup: subnetGroup,
});
}
}
メモ
CFnテンプレートの情報を出力しない。(console.log()の確認等に使用)
cdk synth --quiet