Introduction#

  • Load balancer and auto scaling group
  • Aurora multiple AZ
  • Autoscaling stratergy (not yet here )

Architectrure#

aws_devops-ica drawio

GitHub

Aurora cluster stack#

get existed VPC

const vpc = aws_ec2.Vpc.fromLookup(this, 'ExistedVpc', {
region: props.region,
vpcId: props.vpcId
})

aurora cluster

const cluster = new aws_rds.DatabaseCluster(
this,
"IcaDatabase",
{
removalPolicy: RemovalPolicy.DESTROY,
defaultDatabaseName: props.dbName,
engine: aws_rds.DatabaseClusterEngine.auroraMysql({
version: aws_rds.AuroraMysqlEngineVersion.VER_2_08_1,
}),
credentials:
aws_rds.Credentials.fromGeneratedSecret("admin"),
instanceProps: {
instanceType: aws_ec2.InstanceType.of(
aws_ec2.InstanceClass.BURSTABLE2,
aws_ec2.InstanceSize.SMALL
),
vpcSubnets: {
subnetType: aws_ec2.SubnetType.PUBLIC,
},
vpc,
},
}
);
}

Application load balancer stack#

get existed VPC

const vpc = aws_ec2.Vpc.fromVpcAttributes(this, 'ExistedVpc', {
availabilityZones: props.availabilityZones,
privateSubnetIds: props.privateSubnetIds,
publicSubnetIds: props.publicSubnetIds,
vpcId: props.vpcId
})

role for EC2 to download from S3, access SSM, and Secret Mangement

const role = new aws_iam.Role(this, `RoleForEc2AsgToAccessSSM`, {
roleName: `RoleForEc2AsgToAccessSSM-${this.region}`,
assumedBy: new aws_iam.ServicePrincipal('ec2.amazonaws.com')
})
role.attachInlinePolicy(
new aws_iam.Policy(this, `PolicyForEc2AsgToReadS3`, {
policyName: `PolicyForEc2AsgToReadS3-${this.region}`,
statements: [
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['s3:*'],
resources: ['arn:aws:s3:::haimtran-workspace/*']
}),
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['secretsmanager:*'],
resources: ['*']
})
]
})
)
role.addManagedPolicy(
aws_iam.ManagedPolicy.fromManagedPolicyArn(
this,
`PolicyForEc2AsgToAccessSSM-${this.region}`,
'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore'
)
)

auto scaling group

const asg = new aws_autoscaling.AutoScalingGroup(this, 'ASG', {
vpc,
instanceType: aws_ec2.InstanceType.of(
aws_ec2.InstanceClass.T2,
aws_ec2.InstanceSize.SMALL
),
machineImage: new aws_ec2.AmazonLinuxImage({
generation: aws_ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
edition: aws_ec2.AmazonLinuxEdition.STANDARD
}),
minCapacity: 2,
maxCapacity: 3,
role: role
})
asg.addUserData(
fs.readFileSync('./lib/script/userdata-ap-southeast-1.sh', 'utf8')
)

application load balancer

const alb = new aws_elasticloadbalancingv2.ApplicationLoadBalancer(
this,
'ALB',
{
vpc,
internetFacing: true
}
)

listen port 80

const listener = alb.addListener('Listener', {
port: 80
})
listener.addTargets('Target', {
port: 80,
targets: [asg]
})
listener.connections.allowDefaultPortFromAnyIpv4('Open to the world')
asg.scaleOnRequestCount('AmodestLoad', {
targetRequestsPerMinute: 60
})

UserData#

#!/bin/bash

cd ~
mkdir web
cd web
aws s3 cp s3://haimtran-workspace/aurora-web.zip .
unzip aurora-web.zip
sudo python3 -m pip install -r requirements.txt
sudo python3 app.py

Mysql connector python#

get DB credentials from secret management

# sm client
secrete_client = boto3.client('secretsmanager',
region_name=REGION)
# get secret string
secret = secrete_client.get_secret_value(
SecretId=SECRET_ID
)

connector

conn = mysql.connector.connect(
host=secret_dic['host'],
user=secret_dic['username'],
port=secret_dic['port'],
password=secret_dic['password'],
database=secret_dic['dbname']
)

create table

# cursor
cur = conn.cursor()
# drop table if exists
drop = "DROP TABLE IF EXISTS employees"
cur.execute(drop)
# create table
employee_table = (
"CREATE TABLE employees ("
" id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, "
" name VARCHAR(30) DEFAULT '' NOT NULL, "
" age TEXT, "
" time TEXT, "
"PRIMARY KEY (id))"
)
cur.execute(employee_table)

query table

stmt_select = "SELECT id, name, age, time FROM employees ORDER BY id"
cur.execute(stmt_select)
# parse
for row in cur.fetchall():
print(row)