Trong bài viết trước mình đã refactoring source code, nếu bạn chưa xem thì có thể xem lại ở đây để hiểu hơn.
Trong bài viết này mình xin chia sẽ cách mình dùng CDK để tạo subnets.
Subnets
Mình cần tạo những subnets như sau.
Subnet name | Cidr | AZ |
public-subnet-1a | 10.90.16.0/28 | 0 |
public-subnet-1c | 10.90.16.16/28 | 1 |
vitaldb-subnet-1a | 10.90.16.32/28 | 0 |
vitaldb-subnet-1c | 10.90.16.48/28 | 1 |
mobilecachedb-subnet-1a | 10.90.16.64/28 | 0 |
mobilecachedb-subnet-1c | 10.90.16.80/28 | 1 |
admindb-subnet-1a | 10.90.16.96/28 | 0 |
admindb-subnet-1c | 10.90.16.112/28 | 1 |
register-subnet-1a | 10.90.16.128/28 | 0 |
register-subnet-1c | 10.90.16.144/28 | 1 |
admin-subnet-1a | 10.90.16.160/28 | 0 |
admin-subnet-1c | 10.90.16.176/28 | 1 |
mobile-subnet-1a | 10.90.16.192/28 | 0 |
mobile-subnet-1c | 10.90.16.208/28 | 1 |
vitalwebhook-subnet-1a | 10.90.16.224/28 | 0 |
vitalwebhook-subnet-1c | 10.90.16.240/28 | 1 |
vital-transform-subnet-1a | 10.90.17.0/28 | 0 |
vital-transform-subnet-1c | 10.90.17.16/28 | 1 |
vital-parsing-subnet-1a | 10.90.17.32/28 | 0 |
vital-parsing-subnet-1c | 10.90.17.48/28 | 1 |
vital-raw-subnet-1a | 10.90.17.64/28 | 0 |
vital-raw-subnet-1c | 10.90.17.80/28 | 1 |
vital-job-subnet-1a | 10.90.17.96/28 | 0 |
vital-job-subnet-1c | 10.90.17.112/28 | 1 |
common-services-subnet-1a | 10.90.17.128/28 | 0 |
common-services-subnet-1c | 10.90.17.144/28 | 1 |
mình có ba thông tin về mỗi subnet:
- tên subnet
- cidr subnet
- az của subnet
thông tin này là đủ để mình có thể tạo đc subnets.
Quy tắt đặt tên Logical ID và tag
Mình sẽ sử dụng CfnSubnet trong constructor này mình muốn chỉ định Logical ID là dạng viết hoa chử cái đầu và viết liền của tên subnet.
ví dụ: public-subnet-1a => PublicSubnet1a
còn tên subnet dùng để đánh tag:
từ bài viết này trở về sau mình để sẽ tuân thủ quy tắt này.
Khởi tạo props
Mình sẽ tạo thêm một props trong class Resource (đã được giải thích trong bài trước) dùng cho việc format tên subnet thành tên Logical ID như quy tắt ở trên.
Mình cảm thấy đây là một lợi ích lớn khi mình chuyển qua dùng CDK vì mọi định dạng hay quy tắt mình đều có thể triển khai thông qua code, từ đó nó được đồng bộ trên tất cả thành viên trong dự án.
mình sẽ thêm props Format trong file lib/resources/abstract/index.ts
import { Construct } from 'constructs';
import * as cdk from "aws-cdk-lib";
export abstract class Resource {
constructor() {}
protected createTagName(scope: Construct, ProjectName: string, StageName: string, stackname: string, originalName: string): string {
return [
ProjectName,
StageName,
stackname,
originalName,
].join('-');
}
protected Format(scope: Construct, name: string): string {
return name
.split('-')
.map((name) => name[0].toUpperCase() + name.substring(1))
.join('');
}
// protected FomatId(scope: Construct, id: number): string {
// return ('00' + id).slice(-3);
// }
}
tạo file lib/resources/subnet.ts với nội dung như sau
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { BaseResource } from './abstract';
import { Vpc } from './vpc';
export interface ResourceInfo {
readonly id: string;
readonly cidrBlock: string;
readonly availabilityZone: string;
readonly assign: (subnet: ec2.CfnSubnet) => void;
}
Mình dùng interface ResourceInfo để định nghĩa các thông tin cua subnets
import { Vpc } from ‘./vpc';
export class SN extends BaseResource {
public public1a: ec2.CfnSubnet;
public public1c: ec2.CfnSubnet;
public vitaldb1a: ec2.CfnSubnet;
public vitaldb1c: ec2.CfnSubnet;
public mobilecachedb1a: ec2.CfnSubnet;
public mobilecachedb1c: ec2.CfnSubnet;
public admindb1a: ec2.CfnSubnet;
public admindb1c: ec2.CfnSubnet;
public register1a: ec2.CfnSubnet;
public register1c: ec2.CfnSubnet;
public admin1a: ec2.CfnSubnet;
public admin1c: ec2.CfnSubnet;
public mobile1a: ec2.CfnSubnet;
public mobile1c: ec2.CfnSubnet;
public vitalwebhook1a: ec2.CfnSubnet;
public vitalwebhook1c: ec2.CfnSubnet;
public vitaltransform1a: ec2.CfnSubnet;
public vitaltransform1c: ec2.CfnSubnet;
public vitalparsing1a: ec2.CfnSubnet;
public vitalparsing1c: ec2.CfnSubnet;
public vitalraw1a: ec2.CfnSubnet;
public vitalraw1c: ec2.CfnSubnet;
public vitaljob1a: ec2.CfnSubnet;
public vitaljob1c: ec2.CfnSubnet;
public commonservices1a: ec2.CfnSubnet;
public commonservices1c: ec2.CfnSubnet;
private readonly vpc: Vpc;
private readonly projectName: string;
private readonly stageName: string;
private readonly stackname: string;
public readonly resourcesInfo: ResourceInfo[] = [
{
id: 'public-subnet-1a',
cidrBlock: '10.90.16.0/28',
availabilityZone: '0',
assign: (subnet) => (this.public1a = subnet),
},
{
id: 'public-subnet-1c',
cidrBlock: '10.90.16.16/28',
availabilityZone: '1',
assign: (subnet) => (this.public1c = subnet),
},
...
...
...
];
constructor(
scope: Construct,
projectName: string,
stageName: string,
stackname: string,
vpc: Vpc,
) {
super();
this.projectName = projectName;
this.stageName = stageName;
this.stackname = stackname;
this.vpc = vpc;
for (const resourceInfo of this.resourcesInfo) {
const subnet = this.createSN(scope, resourceInfo);
resourceInfo.assign(subnet);
}
}
private createSN(scope: Construct, resourceInfo: ResourceInfo): ec2.CfnSubnet {
const logigcalId: string = this.Format(scope, resourceInfo.id);
const subnet = new ec2.CfnSubnet(scope, logigcalId, {
availabilityZone:
cdk.Stack.of(scope).availabilityZones[resourceInfo.availabilityZone],
cidrBlock: resourceInfo.cidrBlock,
mapPublicIpOnLaunch: false,
vpcId: this.vpc.vpc.ref,
tags: [
{
key: `Name`,
value: this.createTagName(
scope,
this.projectName,
this.stageName,
this.stackname,
resourceInfo.id,
),
},
],
});
return subnet;
}
}
phần định dạng LogicalID mình làm như sau. Bằng việc kết thừa lại Class Resource
const logigcalId: string = this.Format(scope, resourceInfo.id);
Về phần AZ thì mình sẽ làm như sau.
cdk.Stack.of(scope).availabilityZones[resourceInfo.availabilityZone]
trong file lib/resources/index.ts sửa lại như sau
import { Vpc } from './vpc';
import { SN } from './subnet';
export { Vpc, SN };
Tạo Subnet
import * as cdk from 'aws-cdk-lib';
import { Vpc, SN } from './resources';
import { getConfig } from '../config/build-config';
export class HelloCkdStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const config = getConfig(scope);
// VPC
const vpc = new Vpc(this, config.projectName, config.environment, `network`);
// Subnet
new SN(this, config.projectName, config.environment, `network`, vpc);
}
}
Bonus
mình có thêm phần script để format code typescript, để sử dụng bạn chạy lệnh
npm run prettier
Github
Vì thời lượng có hạn nên một số tinh chỉnh mình không để cập đến, chi tiét hơn về code trong bài viết, các bạn có thể tham khảo ở đây