in src/proxysql.ts [192:327]
constructor(scope: Construct, id: string, props: ProxysqlFargateProps) {
super(scope, id);
if ((props.rdscluster && props.customBackend) || (!props.rdscluster && !props.customBackend)) {
throw new Error('You have to specify either dbcluster or customBackend. Atleast one, not both.');
}
const vpc = props.vpc ?? props.rdscluster?.vpc ?? getOrCreateVpc(this);
// generate and store MYSQL_USER1_PASSWORD in the secrets manager
const auroraMasterSecret = new secretsmanager.Secret(this, 'AuroraMasterSecret', {
secretName: `${Stack.of(this).stackName}-auroraMasterSecret`,
generateSecretString: {
passwordLength: 12,
excludePunctuation: true,
},
});
// generate and store RADMIN_PASSWORD in the secrets manager
const radminSecret = new secretsmanager.Secret(this, 'RAdminPassword', {
secretName: `${Stack.of(this).stackName}-radmin_pwd`,
generateSecretString: {
passwordLength: 12,
excludePunctuation: true,
},
});
const cluster = new ecs.Cluster(this, 'Cluster', {
vpc,
});
const taskDefinition = new ecs.TaskDefinition(this, 'Task', {
compatibility: ecs.Compatibility.FARGATE,
memoryMiB: '4096',
cpu: '1024',
});
const proxysql = taskDefinition.addContainer('proxysql', {
image: ecs.ContainerImage.fromAsset('./dockerAssets.d/proxysql'),
logging: new ecs.AwsLogDriver({
streamPrefix: 'proxysql-main',
}),
environment: {
DB_WRITER_HOSTNAME: `writer.${PROXYSQL_PRIVATE_ZONE_NAME}`,
DB_READER_HOSTNAME: `reader.${PROXYSQL_PRIVATE_ZONE_NAME}`,
DB_WRITER_PORT: props.rdscluster ? AURORA_LISTENER_PORT.toString() : props.customBackend!.writerPort ? props.customBackend!.writerPort : '3306',
DB_READER_PORT: props.rdscluster ? AURORA_LISTENER_PORT.toString() : props.customBackend!.readerPort ? props.customBackend!.readerPort : '3306',
DB_MASTER_USERNAME: props.rdscluster ? DB_MASTER_USERNAME : props.customBackend!.masterUsername ?? 'undefined',
},
secrets: {
DB_MASTER_PASSWORD: ecs.Secret.fromSecretsManager(props.customBackend?.masterSecret ?? auroraMasterSecret),
RADMIN_PASSWORD: ecs.Secret.fromSecretsManager(radminSecret),
},
});
// proxysql.addPortMappings({ containerPort: 6032 })
proxysql.addPortMappings({ containerPort: PROXYSQL_TRAFFIC_PORT });
proxysql.addPortMappings({ containerPort: PROXYSQL_ADMIN_PORT });
const svc = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'NLBService', {
assignPublicIp: false,
cluster,
taskDefinition,
publicLoadBalancer: false,
listenerPort: NLB_LISTENER_PORT,
});
// if nlbSubnetIds provided, override the value of NLB subnets
if (props.nlbSubnetIds) {
const cfnLoadBalancer = svc.loadBalancer.node.tryFindChild('Resource') as elbv2.CfnLoadBalancer;
cfnLoadBalancer.addPropertyOverride('Subnets', props.nlbSubnetIds);
}
// if custom master secert is provided, grant the ecs task execution role to read this secret
if (props.customBackend?.masterSecret) {
// svc.taskDefinition.addToExecutionRolePolicy()
props.customBackend.masterSecret.grantRead(svc.taskDefinition.executionRole!);
}
// allow fargate service connect to dbcluster
props.rdscluster?.dbcluster.connections.allowDefaultPortFrom(svc.service);
// allow proxysql to listen on tcp 6033 for traffic
svc.service.connections.allowFrom(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(PROXYSQL_TRAFFIC_PORT));
// allow vpc cidr to visit proxysql admin port
svc.service.connections.allowFrom(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(PROXYSQL_ADMIN_PORT));
svc.targetGroup.setAttribute('deregistration_delay.timeout_seconds', '30');
svc.loadBalancer.setAttribute('load_balancing.cross_zone.enabled', 'true');
// create route53 alias mapping to the NLB
const zone = new route53.HostedZone(this, 'ProxySQLHZ', {
zoneName: PROXYSQL_PRIVATE_ZONE_NAME,
vpcs: [vpc],
});
// nlb.proxysql.local ALIAS to the internal NLB
const ar = new route53.ARecord(this, 'AliasRecord', {
zone,
recordName: 'nlb',
target: route53.RecordTarget.fromAlias(new alias.LoadBalancerTarget(svc.loadBalancer)),
});
if (props.rdscluster) {
// writer.proxysql.local CNAME to Aurora writer
new route53.CnameRecord(this, 'CnameAuroraWriter', {
recordName: 'writer',
domainName: props.rdscluster.clusterEndpointHostname,
zone,
});
// reader.proxysql.local CNAME to Aurora reader
new route53.CnameRecord(this, 'CnameAuroraReader', {
recordName: 'reader',
domainName: props.rdscluster.clusterEndpointHostname,
zone,
});
} else {
// writer.proxysql.local CNAME to custom writer
new route53.CnameRecord(this, 'CnameCustomWriter', {
recordName: 'writer',
domainName: props.customBackend!.writerHost,
zone,
});
// reader.proxysql.local CNAME to custom reader
new route53.CnameRecord(this, 'CnameCustomReader', {
recordName: 'reader',
domainName: props.customBackend!.readerHost,
zone,
});
}
printOutput(this, 'NLBAliasDN', ar.domainName);
printOutput(this, 'ECSClusterName', svc.cluster.clusterName);
printOutput(this, 'ECSServiceName', svc.service.serviceName);
}