如何使用CDK(TypeScript)为已有Aurora MySQL集群添加数据库?
问题描述
我们正从Terraform切换到TypeScript版CDK,已成功创建包含2个实例的Aurora MySQL集群,集群创建的代码转换过程很顺利,但找不到用CDK为集群添加数据库的相关文档。
Terraform中是通过MySQL Provider来创建数据库的,示例代码如下:
# Configure the MySQL provider provider "mysql" { endpoint = "my-database.example.com:3306" username = "app-user" password = "app-password" } # Create a Database resource "mysql_database" "app" { name = "my_awesome_app" }
多方查找后仍未找到CDK中为已有集群添加数据库的等效构造和流程,请问这在CDK中是否可行?
更新:CDK创建集群的代码
new rds.DatabaseCluster( this, `db-cluster`, { clusterIdentifier: `cluster`, credentials: rds.Credentials.fromSecret(...), engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.of(...) }), instances: 2, instanceProps: { vpc, securityGroups: [dbSecurityGroup], instanceType: new ec2.InstanceType(...) }, subnetGroup, instanceIdentifierBase: 'instance-', })
解决方案
CDK本身没有提供直接创建RDS数据库(Schema)的L2/L3构造,因为这属于数据库内部操作,不属于AWS基础设施资源范畴。要实现类似Terraform的效果,有几种可行方式:
1. 使用自定义资源(Custom Resource)执行SQL
这是最贴合基础设施即代码的方式,通过自定义资源调用Lambda函数,连接到Aurora集群执行CREATE DATABASE语句。
核心实现思路
- 创建Lambda函数:从Secret Manager获取数据库凭证,连接集群,执行创建数据库的SQL(判断数据库不存在时再创建)。
- 定义CDK自定义资源:关联上述Lambda函数,传入集群端点、数据库名称、Secret ARN等参数。
CDK代码片段
// 1. 创建用于创建数据库的Lambda函数 const createDbLambda = new lambda.Function(this, 'CreateDbLambda', { runtime: lambda.Runtime.NODEJS_18_X, code: lambda.Code.fromAsset('lambda'), handler: 'create-db.handler', vpc: vpc, securityGroups: [dbSecurityGroup], environment: { SECRET_ARN: credentials.secretArn, CLUSTER_ENDPOINT: cluster.clusterEndpoint.hostname, DB_NAME: 'my_awesome_app' } }); // 2. 赋予Lambda必要权限:读取Secret、连接RDS credentials.secret.grantRead(createDbLambda); dbSecurityGroup.connections.allowFrom(createDbLambda, ec2.Port.tcp(3306)); // 3. 创建自定义资源触发Lambda执行 new customresources.AwsCustomResource(this, 'CreateDatabase', { onUpdate: { service: 'Lambda', action: 'invoke', parameters: { FunctionName: createDbLambda.functionName, InvocationType: 'RequestResponse' }, physicalResourceId: customresources.PhysicalResourceId.of(`create-db-${Date.now()}`) } });
Lambda核心逻辑(lambda/create-db.js)
const mysql = require('mysql2/promise'); const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager'); const client = new SecretsManagerClient({ region: process.env.AWS_REGION }); exports.handler = async () => { // 从Secret Manager获取数据库凭证 const secret = await client.send(new GetSecretValueCommand({ SecretId: process.env.SECRET_ARN })); const { username, password } = JSON.parse(secret.SecretString); // 连接数据库并创建Schema const connection = await mysql.createConnection({ host: process.env.CLUSTER_ENDPOINT, user: username, password: password, port: 3306 }); await connection.execute(`CREATE DATABASE IF NOT EXISTS ${process.env.DB_NAME}`); await connection.end(); return { status: 'success' }; };
2. 使用RDS初始化脚本(User Data)
如果是在创建集群时一并初始化数据库,可以通过instanceProps的initScript参数传入SQL脚本,脚本会在实例首次启动时执行。但这种方式仅适用于集群创建阶段,无法用于已有集群的后续数据库添加。
代码片段
instanceProps: { // ...其他配置项 initScript: fs.readFileSync('./init-db.sql', 'utf8') }
init-db.sql内容:
CREATE DATABASE IF NOT EXISTS my_awesome_app;
3. 手动执行或CI/CD流程补充
如果不需要在基础设施部署时自动创建,也可以在集群部署完成后,通过CI/CD工具(如GitHub Actions、GitLab CI)连接数据库执行SQL,或者手动通过MySQL客户端创建数据库。
内容的提问来源于stack exchange,提问作者CKT
相关产品推荐
相关产品推荐

