CDKを使ってRDS (MySQL)を作成する方法

基本

参考

EC2の踏み台サーバーをPublic subnetに配置して、RDSはPrivate subnetに配置する場合、 VPCやセキュリティグループは以下のようになります。

    const stackName = "CdkTestDb_";

    // vpc
    const vpc = new Ec2.Vpc(this, `${stackName}Vpc`, {
      vpcName: `${stackName}Vpc`,
      natGateways: 0,
      // maxAzs: 1,
      availabilityZones: ["ap-northeast-1a", "ap-northeast-1c"],

      ipAddresses: Ec2.IpAddresses.cidr("10.0.0.0/16"),
      enableDnsHostnames: true,
      enableDnsSupport: true,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: "PublicSubnet",
          subnetType: Ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: "PrivateSubnet",
          subnetType: Ec2.SubnetType.PRIVATE_ISOLATED,
        },
      ],
    });

    const bastionSg = new Ec2.SecurityGroup(this, "Bastion-securityGroup", {
      vpc: vpc,
      description: "Allow ssh access to bastion instance",
      allowAllOutbound: true,
    });

    const dbSg = new Ec2.SecurityGroup(this, "Db-securityGroup", {
      vpc: vpc,
      description: "Allow access to DB",
      allowAllOutbound: true,
    });

    // 踏み台からMySQLへ接続できるようにする
    dbSg.addIngressRule(
      bastionSg,
      Ec2.Port.tcp(3306),
      "Allow access from bastion to DB"
    );

RDSのインスタンス作成の例は以下になります。RDSのユーザー名は admin で、パスワードなどはシークレットに作成します。

    // MySQLのユーザー名を指定
    const dbUser: string = "admin";
    const rdsCredentials: Rds.Credentials = Rds.Credentials.fromGeneratedSecret(dbUser);

    // rds
    const rdsInstance = new Rds.DatabaseInstance(
      this,
      `${stackName}DBInstance`,
      {
        databaseName: `${stackName}DBInstance`,

        engine: Rds.DatabaseInstanceEngine.mysql({
          version: Rds.MysqlEngineVersion.VER_8_0_39,
        }),
        credentials: rdsCredentials,

        instanceType: Ec2.InstanceType.of(
          Ec2.InstanceClass.T4G,
          Ec2.InstanceSize.MEDIUM
        ),
        vpc: vpc,
        vpcSubnets: {
          subnetType: Ec2.SubnetType.PRIVATE_ISOLATED,
        },

        securityGroups: [dbSg],

        // 試験のためRDSインスタンス削除時にスナップショットを作成しないようにする
        removalPolicy: Cdk.RemovalPolicy.DESTROY,

        // 試験のためRDSインスタンス削除できるようにする
        deletionProtection: false,

        parameterGroup: new Rds.ParameterGroup(
          this,
          `${stackName}RdsParameterGroup`,
          {
            engine: Rds.DatabaseInstanceEngine.mysql({
              version: Rds.MysqlEngineVersion.VER_8_0_39,
            }),
            parameters: {
              time_zone: "Asia/Tokyo",
              character_set_client: "utf8mb4",
              general_log: "1",
              slow_query_log: "1",
              long_query_time: "1",
              log_output: "FILE",
            },
          }
        ),

        // CloudWatchにログを記録
        cloudwatchLogsExports: ["error", "general", "slowquery"],
      }
    );
注意 上記は試験用で、削除保護を無効にしてインスタンス削除ができるようにしているのと、インスタンス削除時のスナップショット作成も無効にしています。

パラメータグループ

MySQLのcharacter_set_clientなどを設定したい場合、Rds.ParameterGroup で設定可能です。

        parameterGroup: new Rds.ParameterGroup(
          this,
          `${stackName}RdsParameterGroup`,
          {
            engine: Rds.DatabaseInstanceEngine.mysql({
              version: Rds.MysqlEngineVersion.VER_8_0_39,
            }),
            parameters: {
              time_zone: "Asia/Tokyo",
              character_set_client: "utf8mb4",
              character_set_connection: "utf8mb4",
              character_set_database: "utf8mb4",
              character_set_results: "utf8mb4",
              character_set_server: "utf8mb4",
              collation_connection: "utf8mb4_bin",
            },
          }
        ),

トラブル

アベイラビリティゾーン

AZが2つ以上必要なようで、1つの場合エラーになりました。

例 AZが1つの場合のエラー

$ npm run cdk deploy
...

CdkTestStack: deploying... [1/1]
CdkTestStack: creating CloudFormation changeset...
9:56:11 PM | CREATE_FAILED        | AWS::RDS::DBSubnetGroup                     | CdkTestDbDBInstanceSubnetGroup1234ABC
B
Resource handler returned message: "The DB subnet group doesn't meet Availability Zone (AZ) coverage requirement. Curre
nt AZ coverage: ap-northeast-1a. Add subnets to cover at least 2 AZs. 

...

インスタンスタイプエラー

RDSのバージョンによって対応インスタンスタイプが異なります。 非対応のインスタンスタイプを指定した場合、cdk diff ではエラーになりませんが、cdk deploy でエラーになります。

例 インスタンスタイプ t2.micro に対応していないエラー

$ npm run cdk deploy
...

CdkTestStack: deploying... [1/1]
CdkTestStack: creating CloudFormation changeset...
10:12:30 PM | CREATE_FAILED        | AWS::RDS::DBInstance                        | CdkTestDbDBInstanceXXXXXXXX
Resource handler returned message: "RDS does not support creating a DB instance with the following combination: D
BInstanceClass=db.t2.micro, Engine=mysql, EngineVersion=8.0.39, LicenseModel=general-public-license. For supporte
d combinations of instance class and database engine version, see the documentation. 
....

❌  CdkTestStack failed: The stack named CdkTestStack failed creation, it may need to be manually deleted from the
 AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "RDS does not support creating a DB instance
  with the following combination: DBInstanceClass=db.t2.micro, Engine=mysql, EngineVersion=8.0.39, LicenseModel=general
  -public-license. For supported combinations of instance class and database engine version, see the documentation. 
.....

参考