AWS CDKで作るサーバーレスデータベース基盤 【第1回】 Aurora Serverless V2構築

AWS CDKで作るサーバーレスデータベース基盤 【第1回】 Aurora Serverless V2構築

Clock Icon2025.03.15

こんにちは!製造ビジネステクノロジー部の小林です。

「インフラをコードで管理したい」
「サーバーレスデータベースの実力が知りたい」
「CDK使ってみようかなあ」

そんな疑問や興味をお持ちの方に向けて、「AWS CDKで作るサーバーレスデータベース基盤」シリーズをスタートします!

このシリーズで学べること

AWS CDKの魅力は、おなじみのプログラミング言語でAWSリソースを定義できること。

第1回となる本記事では、

  • AWS CDKの基本的な使い方
  • Amazon Auroraの構築
    を、実際のコード例とともに解説します。

最終ゴールは?

シリーズの最終回では、RDS ProxyとRDS Data APIを比較する予定です。

  • どちらが高速なのか?
  • どんなユースケースに向いているのか?
  • 実装の難易度は?

AWS X-Ray、Apache Benchを活用し、実測データに基づいた分析で、それぞれのパフォーマンスを評価していきます。
ステップバイステップで解説していきますので、最後までお付き合いいただけたら嬉しいです。

本シリーズで使用する環境

  • AWS CDK V2(TypeScript)
  • AWS Lambda(TypeScript)
  • Amazon API Gateway
  • Amazon Aurora Serverless V2(PostgreSQL)
  • Amazon RDS Proxy
  • Amazon RDS Data API

システム構成図

以下は本シリーズで構築するシステムの全体像です。
今回の記事では、VPCとAurora Serverlessの部分を構築します。
system-diagram

最終的なディレクトリ構成

cdk-aurora
├── bin
│   └── main.ts                 # CDKアプリケーションのエントリーポイント
├── lambda
│   ├── data-api-lambda.ts      # Data APIを使用するLambda関数のソースコード
│   ├── package-lock.json       # Lambda関数の依存関係ロックファイル
│   ├── package.json            # Lambda関数の依存関係定義
│   └── rds-proxy-lambda.ts     # RDS Proxyを使用するLambda関数のソースコード
├── lib
│   ├── apigateway.ts           # API Gatewayリソースを定義
│   ├── aurora.ts               # Aurora Serverless v2リソースを定義
│   ├── lambda.ts               # Lambda関数リソースを定義
│   ├── main-stack.ts           # メインCDKスタック(全リソースの統合)
│   └── vpc.ts                  # VPCリソースを定義
├── package-lock.json           # プロジェクト全体の依存関係ロックファイル
├── package.json                # プロジェクト全体の依存関係とスクリプト定義
├── test                        # テストコードディレクトリ
├── tsconfig.json               # TypeScriptコンパイラ設定
├── cdk.json                    # CDK設定ファイル
└── README.md                   

やってみる

環境
以下の環境で実装しています。CDKはTypeScriptで実装しています。

$ sw_vers
ProductName:     macOS
ProductVersion:  14.7.4
BuildVersion:    23H420

$ node -v
v20.18.3

$ npm -v
10.8.2

$ cdk --version
2.1003.0 (build b242c23)

では構築していきます。
本記事では以下のリソースを構築します。

  • Amazon VPC
    • プライベートサブネット(2つのアベイラビリティゾーン)
    • セキュリティグループ
  • Amazon Aurora Serverless V2(PostgreSQL)
    • PostgreSQL 16.1互換エンジン
    • 最小容量: 0.5 ACU
    • 最大容量: 1 ACU
  • AWS Secrets Manager
    • データベースのパスワード管理用

これらのリソースはAWS CDK V2を使用してTypeScriptで定義し、CloudFormationスタックとしてデプロイします。構築したAurora Serverless V2は、後続の記事で紹介するRDS Proxy、Lambda関数、API Gatewayと連携させる基盤となります。

CDKプロジェクトを作成します。

mkdir cdk-aurora
cd cdk-aurora
cdk init app --language=typescript

lib/vpc.tsファイルを作成し、VPCを定義します。

vpc.ts
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class Vpc extends Construct {
  public readonly vpc: ec2.Vpc;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    this.vpc = new ec2.Vpc(this, 'AuroraVpc', {
      maxAzs: 2,
      natGateways: 0,
      subnetConfiguration: [
        {
          name: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
          cidrMask: 24
        }
      ]
    });
  }
}

lib/aurora.tsファイルを作成し、Aurora Serverless v2クラスターを定義します。

aurora.ts
import * as cdk from 'aws-cdk-lib';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import { Construct } from 'constructs';

export class Aurora extends Construct {
  public readonly cluster: rds.DatabaseCluster;
  public readonly dbSecret: secretsmanager.Secret;

  constructor(scope: Construct, id: string, vpc: ec2.Vpc) {
    super(scope, id);

    // データベース認証情報のシークレットを作成
    this.dbSecret = new secretsmanager.Secret(this, 'AuroraSecret', {
      generateSecretString: {
        secretStringTemplate: JSON.stringify({ username: 'postgres' }),
        generateStringKey: 'password',
        excludeCharacters: '/@" ',
      },
    });

    // セキュリティグループの作成
    const dbSecurityGroup = new ec2.SecurityGroup(this, 'DBSecurityGroup', {
      vpc,
      description: 'Security group for Aurora Serverless v2',
      allowAllOutbound: true,
    });

    // VPC内からの接続を許可
    dbSecurityGroup.addIngressRule(
      ec2.Peer.ipv4(vpc.vpcCidrBlock),
      ec2.Port.tcp(5432),
      'Allow database connections from within VPC'
    );

    // Aurora Serverless v2クラスターの作成
    this.cluster = new rds.DatabaseCluster(this, 'AuroraCluster', {
      engine: rds.DatabaseClusterEngine.auroraPostgres({
        version: rds.AuroraPostgresEngineVersion.VER_16_1,
      }),
      credentials: rds.Credentials.fromSecret(this.dbSecret),
      defaultDatabaseName: 'demodb',
      vpc,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      },
      securityGroups: [dbSecurityGroup],
      writer: rds.ClusterInstance.serverlessV2('Writer', {
        autoMinorVersionUpgrade: true,
      }),
      serverlessV2MinCapacity: 0.5,
      serverlessV2MaxCapacity: 1,
    });

    // 出力値の設定
    new cdk.CfnOutput(this, 'ClusterEndpoint', {
      value: this.cluster.clusterEndpoint.hostname,
      description: 'Aurora Serverless v2 Cluster Endpoint',
    });

    new cdk.CfnOutput(this, 'SecretArn', {
      value: this.dbSecret.secretArn,
      description: 'Secret ARN for database credentials',
    });

    new cdk.CfnOutput(this, 'DatabaseName', {
      value: 'demodb',
      description: 'Default Database Name',
    });
  }
}

lib/main-stack.tsファイルを作成し、スタック全体を組み立てます。

main-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Vpc } from './vpc';
import { Aurora } from './aurora';

export class MainStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPCの作成
    const vpcStack = new Vpc(this, 'VpcConstruct');

    // Aurora Serverless v2の作成
    const auroraStack = new Aurora(this, 'AuroraConstruct', vpcStack.vpc);
  }
}

bin/main.tsファイルを更新して、main-stackを参照するようにします。

main.ts
import * as cdk from 'aws-cdk-lib';
import { MainStack } from '../lib/main-stack';

const app = new cdk.App();
new MainStack(app, 'MainStack', {
});

最後に、cdk.jsonの2行目のbin/をmain.tsに修正します。

{
  "app": "npx ts-node --prefer-ts-exts bin/main.ts",
  "watch": {
    "include": [
      "**"
    ],  
# 省略...

デプロイしていく

これでコードの準備ができました。
デプロイする前に、CDKが初めての環境では「ブートストラップ」が必要です。
ブートストラップの詳細については以下をご参照ください。
https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/bootstrapping.html

# CDKブートストラップ(初回のみ)
cdk bootstrap
# デプロイ前の構文チェックとCloudFormationテンプレート生成
cdk synth

cdk synthコマンドを実行すると、CDKが定義したインフラストラクチャがどのようなCloudFormationリソースに変換されるかが表示されます。コマンド実行結果の一部を見てみましょう。

VPCとサブネット

VpcConstructAuroraVpcF6C2749C:
  Type: AWS::EC2::VPC
  Properties:
    CidrBlock: 10.0.0.0/16
    EnableDnsHostnames: true
    EnableDnsSupport: true
    # 省略...

VpcConstructAuroraVpcPrivateSubnet1Subnet7CEADCDF:
  Type: AWS::EC2::Subnet
  Properties:
    AvailabilityZone:
      Fn::Select:
        - 0
        - Fn::GetAZs: ""
    CidrBlock: 10.0.0.0/24
    MapPublicIpOnLaunch: false
    Tags:
      - Key: aws-cdk:subnet-name
        Value: Private
      - Key: aws-cdk:subnet-type
        Value: Isolated
    # 省略...

VPCと2つのプライベートサブネット(アベイラビリティゾーンごとに1つずつ)が作成されます。
サブネットタイプはIsolatedとなっており、インターネットへの接続がないことがわかります。

Secret

AuroraConstructAuroraSecretB62C0F2A:
  Type: AWS::SecretsManager::Secret
  Properties:
    GenerateSecretString:
      ExcludeCharacters: '/@" '
      GenerateStringKey: password
      SecretStringTemplate: '{"username":"postgres"}'
  # 省略...

Secrets Managerにデータベースの認証情報が保存されます。
パスワードは自動生成され、ユーザー名は「postgres」に設定されています。

セキュリティグループ

AuroraConstructDBSecurityGroup87E99755:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Security group for Aurora Serverless v2
    SecurityGroupEgress:
      - CidrIp: 0.0.0.0/0
        Description: Allow all outbound traffic by default
        IpProtocol: "-1"
    SecurityGroupIngress:
      - CidrIp:
          Fn::GetAtt:
            - VpcConstructAuroraVpcF6C2749C
            - CidrBlock
        Description: Allow database connections from within VPC
        FromPort: 5432
        IpProtocol: tcp
        ToPort: 5432
    # 省略...

データベース用のセキュリティグループが作成され、VPC内からの5432ポート(PostgreSQL)へのアクセスが許可されています。

Aurora Serverless v2クラスター

AuroraConstructAuroraClusterC9A177F7:
  Type: AWS::RDS::DBCluster
  Properties:
    CopyTagsToSnapshot: true
    DBClusterParameterGroupName: default.aurora-postgresql16
    DBSubnetGroupName:
      Ref: AuroraConstructAuroraClusterSubnetsA9C71745
    DatabaseName: demodb
    Engine: aurora-postgresql
    EngineVersion: "16.1"
    # 省略...
    ServerlessV2ScalingConfiguration:
      MaxCapacity: 1
      MinCapacity: 0.5
    # 省略...

Aurora Serverless v2クラスターが作成され、PostgreSQL 16.1エンジンを使用しています。
最小キャパシティは0.5 ACU、最大キャパシティは1 ACUに設定されています。

DBインスタンス(ライター)

AuroraConstructAuroraClusterWriter49EBEE50:
  Type: AWS::RDS::DBInstance
  Properties:
    AutoMinorVersionUpgrade: true
    DBClusterIdentifier:
      Ref: AuroraConstructAuroraClusterC9A177F7
    DBInstanceClass: db.serverless
    Engine: aurora-postgresql
    PromotionTier: 0
    PubliclyAccessible: false
  # 省略...

Serverlessインスタンスタイプ(db.serverless)を使用したライターインスタンスが作成されます。

出力値

Outputs:
  AuroraConstructClusterEndpointAD49D660:
    Description: Aurora Serverless v2 Cluster Endpoint
    Value:
      Fn::GetAtt:
        - AuroraConstructAuroraClusterC9A177F7
        - Endpoint.Address
  AuroraConstructSecretArnE826CA4E:
    Description: Secret ARN for database credentials
    Value:
      Ref: AuroraConstructAuroraSecretB62C0F2A
  AuroraConstructDatabaseName66DB7FE9:
    Description: Default Database Name
    Value: demodb

デプロイ後に参照できる重要な情報(クラスターエンドポイント、シークレットARN、データベース名)が出力値として定義されています。

cdk synthコマンドは、実際のデプロイ前にCloudFormationテンプレートを確認することで、意図したリソースが正しく定義されているかを検証するのに役立ちますね。

# デプロイを実行
cdk deploy

デプロイが完了すると、以下のような出力が表示されます。
スクリーンショット 2025-03-16 1.22.25

デプロイ時間
約624秒(10分24秒)かかりました。

CloudFormationのコンソールでも確認してみましょう。
VPC、Secret、セキュリティグループ、Auroraが作成されていますね。
スクリーンショット 2025-03-16 1.43.23

RDSのコンソールです。Aurora Serverless V2が作成できました!
スクリーンショット 2025-03-16 1.47.07

おわりに

今回は「AWS CDKで作るサーバーレスデータベース基盤」の第1回として、AWS CDKを使用してAmazon Aurora Serverless v2をデプロイする方法を解説しました。

今回構築したAurora Serverless v2は、次回以降構築していくサーバーレスアプリケーションの重要な基盤となります。

次回は、API Gateway + Lambda + RDS Proxyを利用して、リクエストを受け付けるAPIを構築し、Lambdaを通じてAurora Serverless v2に接続するフローを解説します。
最後までお読みいただき、ありがとうございました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.