175 lines
4.8 KiB
TypeScript
175 lines
4.8 KiB
TypeScript
import * as cdk from "aws-cdk-lib";
|
|
import * as ec2 from "aws-cdk-lib/aws-ec2";
|
|
import * as rds from "aws-cdk-lib/aws-rds";
|
|
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
|
|
import { Construct } from "constructs";
|
|
|
|
interface RdsStackProps extends cdk.StackProps {
|
|
/**
|
|
* Environment name (dev, staging, prod)
|
|
*/
|
|
environment: string;
|
|
|
|
/**
|
|
* VPC to deploy the database in
|
|
*/
|
|
vpc: ec2.IVpc;
|
|
|
|
/**
|
|
* Database credentials secret from SecretsStack
|
|
*/
|
|
databaseSecret: secretsmanager.ISecret;
|
|
|
|
/**
|
|
* Database name (default: rentall)
|
|
*/
|
|
databaseName?: string;
|
|
|
|
/**
|
|
* Instance type (default: t3.micro for Free Tier)
|
|
*/
|
|
instanceType?: ec2.InstanceType;
|
|
|
|
/**
|
|
* Allocated storage in GB (default: 20)
|
|
*/
|
|
allocatedStorage?: number;
|
|
|
|
/**
|
|
* Enable Multi-AZ deployment (default: false for dev/staging)
|
|
*/
|
|
multiAz?: boolean;
|
|
|
|
/**
|
|
* Backup retention days (default: 7)
|
|
*/
|
|
backupRetentionDays?: number;
|
|
}
|
|
|
|
export class RdsStack extends cdk.Stack {
|
|
/**
|
|
* The RDS database instance
|
|
*/
|
|
public readonly database: rds.DatabaseInstance;
|
|
|
|
/**
|
|
* Security group for the database
|
|
*/
|
|
public readonly databaseSecurityGroup: ec2.SecurityGroup;
|
|
|
|
/**
|
|
* Database endpoint address
|
|
*/
|
|
public readonly dbEndpoint: string;
|
|
|
|
/**
|
|
* Database port
|
|
*/
|
|
public readonly dbPort: number;
|
|
|
|
constructor(scope: Construct, id: string, props: RdsStackProps) {
|
|
super(scope, id, props);
|
|
|
|
const {
|
|
environment,
|
|
vpc,
|
|
databaseSecret,
|
|
databaseName = "rentall",
|
|
instanceType = ec2.InstanceType.of(
|
|
ec2.InstanceClass.T3,
|
|
ec2.InstanceSize.MICRO
|
|
),
|
|
allocatedStorage = 20,
|
|
multiAz = false,
|
|
backupRetentionDays = 7,
|
|
} = props;
|
|
|
|
// Security group for the database
|
|
this.databaseSecurityGroup = new ec2.SecurityGroup(
|
|
this,
|
|
"DatabaseSecurityGroup",
|
|
{
|
|
vpc,
|
|
securityGroupName: `rentall-db-sg-${environment}`,
|
|
description: `Security group for RDS database (${environment})`,
|
|
allowAllOutbound: false,
|
|
}
|
|
);
|
|
|
|
// Create the RDS instance
|
|
this.database = new rds.DatabaseInstance(this, "Database", {
|
|
instanceIdentifier: `rentall-db-${environment}`,
|
|
engine: rds.DatabaseInstanceEngine.postgres({
|
|
version: rds.PostgresEngineVersion.VER_15,
|
|
}),
|
|
instanceType,
|
|
vpc,
|
|
vpcSubnets: {
|
|
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
|
|
},
|
|
securityGroups: [this.databaseSecurityGroup],
|
|
credentials: rds.Credentials.fromSecret(databaseSecret),
|
|
databaseName,
|
|
allocatedStorage,
|
|
maxAllocatedStorage: allocatedStorage * 2, // Allow storage autoscaling up to 2x
|
|
storageType: rds.StorageType.GP2,
|
|
multiAz,
|
|
autoMinorVersionUpgrade: true,
|
|
deletionProtection: environment === "prod",
|
|
removalPolicy:
|
|
environment === "prod"
|
|
? cdk.RemovalPolicy.RETAIN
|
|
: cdk.RemovalPolicy.DESTROY,
|
|
backupRetention: cdk.Duration.days(backupRetentionDays),
|
|
preferredBackupWindow: "03:00-04:00", // UTC
|
|
preferredMaintenanceWindow: "Sun:04:00-Sun:05:00", // UTC
|
|
storageEncrypted: true,
|
|
monitoringInterval: cdk.Duration.seconds(60),
|
|
enablePerformanceInsights: true,
|
|
performanceInsightRetention: rds.PerformanceInsightRetention.DEFAULT, // 7 days (free)
|
|
parameterGroup: new rds.ParameterGroup(this, "ParameterGroup", {
|
|
engine: rds.DatabaseInstanceEngine.postgres({
|
|
version: rds.PostgresEngineVersion.VER_15,
|
|
}),
|
|
parameters: {
|
|
// Enforce SSL connections
|
|
"rds.force_ssl": "1",
|
|
// Log slow queries (> 1 second)
|
|
log_min_duration_statement: "1000",
|
|
},
|
|
}),
|
|
publiclyAccessible: false,
|
|
});
|
|
|
|
this.dbEndpoint = this.database.dbInstanceEndpointAddress;
|
|
this.dbPort = this.database.dbInstanceEndpointPort
|
|
? parseInt(this.database.dbInstanceEndpointPort)
|
|
: 5432;
|
|
|
|
// Outputs
|
|
new cdk.CfnOutput(this, "DatabaseEndpoint", {
|
|
value: this.database.dbInstanceEndpointAddress,
|
|
description: "Database endpoint address",
|
|
exportName: `DatabaseEndpoint-${environment}`,
|
|
});
|
|
|
|
new cdk.CfnOutput(this, "DatabasePort", {
|
|
value: this.database.dbInstanceEndpointPort,
|
|
description: "Database port",
|
|
exportName: `DatabasePort-${environment}`,
|
|
});
|
|
|
|
new cdk.CfnOutput(this, "DatabaseSecurityGroupId", {
|
|
value: this.databaseSecurityGroup.securityGroupId,
|
|
description: "Database security group ID",
|
|
exportName: `DatabaseSecurityGroupId-${environment}`,
|
|
});
|
|
|
|
new cdk.CfnOutput(this, "DatabaseInstanceIdentifier", {
|
|
value: this.database.instanceIdentifier,
|
|
description: "Database instance identifier",
|
|
exportName: `DatabaseInstanceIdentifier-${environment}`,
|
|
});
|
|
}
|
|
}
|