infrastructure with aws cdk
This commit is contained in:
174
infrastructure/cdk/lib/rds-stack.ts
Normal file
174
infrastructure/cdk/lib/rds-stack.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
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}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user