Completed DynamoDB + DAX Benchmarker with a nice TUI to boot

This commit is contained in:
hamilcarBarca17
2023-08-02 18:11:41 -06:00
parent 09862c1b43
commit e42070eefa
55 changed files with 3574 additions and 1 deletions
+50
View File
@@ -0,0 +1,50 @@
import { Tags } from "aws-cdk-lib";
import { Construct } from "constructs";
import { EnvironmentProps } from "./types";
import { Instance, InstanceClass, InstanceSize, InstanceType, MachineImage, Peer, Port, SecurityGroup, SubnetType, Vpc } from "aws-cdk-lib/aws-ec2";
import { IRole, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
export class DaxBastionHost extends Construct {
public readonly instanceRole: IRole;
public readonly instance: Instance;
constructor(scope: Construct, id: string, environmentProps: EnvironmentProps, daxSecurityGroup: SecurityGroup) {
super(scope, id);
Tags.of(this).add('Application', 'dynamodb-dax-benchmarker');
const { removalPolicy, user, vpcId, localIp, sshKeyName } = environmentProps;
const localIpCidr = `${localIp}/32`;
const vpc = Vpc.fromLookup(this, 'Vpc', { vpcId });
const bastionHostSecurityGroup = new SecurityGroup(this, `${user}-dax-sg`, {
vpc,
description: `Allow SSH, Elasticsearch, and DAX access for ${user}`,
securityGroupName: `${user}-dax-bastion-host-sg`
});
bastionHostSecurityGroup.applyRemovalPolicy(removalPolicy);
bastionHostSecurityGroup.addIngressRule(Peer.ipv4(localIpCidr), Port.tcp(22), "Allow SSH access to this instance from the users public IP");
bastionHostSecurityGroup.addIngressRule(Peer.ipv4(localIpCidr), Port.tcp(9200), "Allow the host to communicate with the users locally running Elasticsearch cluster");
bastionHostSecurityGroup.addIngressRule(daxSecurityGroup, Port.allTraffic());
daxSecurityGroup.addIngressRule(bastionHostSecurityGroup, Port.allTraffic());
this.instanceRole = new Role(this, `${user}-bastion-role`, {
roleName: `${user}-bastion-role`,
assumedBy: new ServicePrincipal('ec2.amazonaws.com'),
});
this.instanceRole.applyRemovalPolicy(removalPolicy);
this.instance = new Instance(this, `${user}-dax-bastion-host`, {
vpc,
instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.SMALL),
machineImage: MachineImage.latestAmazonLinux2023(),
instanceName: `${user}-dax-bastion-host`,
keyName: sshKeyName,
vpcSubnets: vpc.selectSubnets({ subnetType: SubnetType.PUBLIC }),
securityGroup: bastionHostSecurityGroup,
role: this.instanceRole
});
this.instance.applyRemovalPolicy(removalPolicy);
}
}
+89
View File
@@ -0,0 +1,89 @@
import { Construct } from "constructs";
import { EnvironmentProps } from "./types";
import { CfnOutput, Stack, Tags } from "aws-cdk-lib";
import { CfnCluster, CfnSubnetGroup } from "aws-cdk-lib/aws-dax";
import { Effect, PolicyDocument, PolicyStatement, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
import { SecurityGroup, SubnetType, Vpc } from "aws-cdk-lib/aws-ec2";
import { DynamoDbBenchmarkTable } from "./dynamodb";
import { DaxBastionHost } from "./bastion-host";
export class DaxBenchmarkingStack extends Stack {
constructor(scope: Construct, id: string, environmentProps: EnvironmentProps) {
super(scope, id, environmentProps);
Tags.of(this).add('Application', 'dynamodb-dax-benchmarker');
const { user, removalPolicy, vpcId } = environmentProps;
const { table } = new DynamoDbBenchmarkTable(this, `${user}-dynamodb-benchmark-table`, environmentProps);
const vpc = Vpc.fromLookup(this, 'Vpc', { vpcId });
const daxSecurityGroup = new SecurityGroup(this, `${user}-dax-sg`, {
vpc,
securityGroupName: `${user}-dax-sg`
});
daxSecurityGroup.applyRemovalPolicy(removalPolicy);
const { instanceRole, instance } = new DaxBastionHost(this, `${user}-dax-bastion-host`, environmentProps, daxSecurityGroup);
const daxClusterName = `${user}-high-velocity`;
const daxFullAccessPolicy = new PolicyStatement({
effect: Effect.ALLOW,
actions: [
"dynamodb:BatchGetItem",
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchWriteItem",
"dynamodb:DeleteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DescribeLimits",
"dynamodb:DescribeTimeToLive",
"dynamodb:DescribeTable",
"dynamodb:ListTables"
],
resources: [table.tableArn]
});
const daxServiceRole = new Role(this, `${daxClusterName}-role`, {
assumedBy: new ServicePrincipal("dax.amazonaws.com"),
inlinePolicies: {
DAXFullAccess: new PolicyDocument({
statements: [daxFullAccessPolicy]
})
}
});
daxServiceRole.applyRemovalPolicy(removalPolicy);
instanceRole.addToPrincipalPolicy(daxFullAccessPolicy);
const subnetGroup = new CfnSubnetGroup(this, `${user}-dax-subnet-group`, {
subnetIds: vpc.selectSubnets({
subnetType: SubnetType.PRIVATE_ISOLATED
}).subnetIds,
subnetGroupName: `${user}-dax-subnet-group`,
});
subnetGroup.applyRemovalPolicy(removalPolicy);
const daxCluster = new CfnCluster(this, daxClusterName, {
iamRoleArn: daxServiceRole.roleArn,
nodeType: 'dax.r5.large',
replicationFactor: 3,
securityGroupIds: [daxSecurityGroup.securityGroupId],
subnetGroupName: subnetGroup.subnetGroupName,
availabilityZones: vpc.availabilityZones,
clusterEndpointEncryptionType: 'TLS',
clusterName: daxClusterName,
sseSpecification: {
sseEnabled: true,
}
});
daxCluster.applyRemovalPolicy(removalPolicy);
daxCluster.addDependency(subnetGroup);
new CfnOutput(this, 'DaxEndpoint', { value: daxCluster.attrClusterDiscoveryEndpointUrl });
new CfnOutput(this, 'InstanceId', { value: instance.instanceId });
new CfnOutput(this, 'InstancePublicIp', { value: instance.instancePublicIp });
}
}
+27
View File
@@ -0,0 +1,27 @@
import {Tags} from "aws-cdk-lib";
import {Construct} from "constructs";
import {EnvironmentProps} from "./types";
import {AttributeType, BillingMode, Table} from "aws-cdk-lib/aws-dynamodb";
export class DynamoDbBenchmarkTable extends Construct {
public readonly table: Table;
constructor(scope: Construct, id: string, environmentProps: EnvironmentProps) {
super(scope, id);
Tags.of(this).add('Application', 'dynamodb-dax-benchmarker');
const { baseTableName, removalPolicy, user } = environmentProps;
const tableName = `${user}-${baseTableName}`;
this.table = new Table(this, tableName, {
partitionKey: {
name: 'id',
type: AttributeType.STRING
},
tableName,
removalPolicy,
billingMode: BillingMode.PAY_PER_REQUEST
});
}
}
+10
View File
@@ -0,0 +1,10 @@
import {RemovalPolicy, StackProps} from "aws-cdk-lib";
export interface EnvironmentProps extends StackProps {
readonly baseTableName: string
readonly removalPolicy: RemovalPolicy
readonly user: string
readonly vpcId: string
readonly localIp: string
readonly sshKeyName: string
}