mazyu36の日記

某SIer所属のクラウドエンジニアのブログ

AWS CDKでカスタムパラメータグループを使用しているAuroraのアップグレード方法(+v.2.50.0時点でServerless v2を使用する方法)

背景

AWS CDKでAurora MySQL 2(5.7互換)を使用していた。しかしAurora Serverless v2の検証をしたいため、Aurora MySQL 3(8互換)にアップグレードをする必要があった。

以下の記事に記載の通り、簡単にアップグレードできるものと踏んでいたが、かなりハマったので試したことをまとめておく。

zenn.dev

※おまけでCDK v2.50.0時点でAurora Serverless v2を実装する方法も記載。

前提

今回アップグレード対象のAurora MySQLは独自のDBクラスターパラメータグループ、DBパラメータグループ(カスタムパラメータグループ)を使用しているAuroraクラスターである。

2つのパラメータグループの違いや適用優先度等は以下を参照。

https://dev.classmethod.jp/articles/aurora-parameter-group-priority/

また、アップグレードとしてはAurora MySQL 2.10.0 -> Aurora MySQL 3.02.0であり、インプレースアップグレードがサポートされている。

aws.amazon.com

検証結果

先に結論。No.4の2段階でアップグレードする手順だとうまくいった。

No 内容 結果
1 カスタムパラメータグループとDBクラスターのバージョンのみ書き換える エラーになる。
2 カスタムパラメータグループの名称を変更してアップグレード後のものを新規作成する エラーになる。
3 DBクラスターの定義でカスタムパラメータグループの使用をコメントアウトし、一旦デフォルトを使用する エラーになる。旧DBパラメータグループが削除されず、参照先がデフォルトになってくれない。※クラスターパラメータグループだけカスタムならこれでできる。
4 DBクラスターの定義で、一旦デフォルトのパラメータグループを使用するよう明示して変更する。その後アップグレードする。 うまくいった。

検証内容詳細

0.事前状態

以下のようにslow_query_logを設定したカスタムパラメータグループを使用する。

※DBクラスターパラメータグループとDBパラメータグループで同じ項目を設定しても意味はない。あくまでカスタムパラメータグループの例として記載。

    // クラスターパラメータグループを作成
    const clusterParameterGroup = new rds.ParameterGroup(scope, 'ClusterParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_2_10_0
      }),
      parameters: {
        'slow_query_log': '1',
      }
    })


    //パラメータグループを作成
    const instanceParameterGroup = new rds.ParameterGroup(scope, 'InstanceParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_2_10_0
      }),
      parameters: {
        'slow_query_log': '1',
      }
    })

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_2_10_0
      }),
      parameterGroup: clusterParameterGroup, // クラスターパラメータグループを指定
      instanceProps: {
        parameterGroup: instanceParameterGroup, // インスタンスパラメータグループを指定
        allowMajorVersionUpgrade: true, // メジャーアップグレードを許可
      //以下略
    })

1. カスタムパラメータグループとDBクラスターのバージョンのみ書き換える

まずはシンプルにバージョンのみ直接書き換えてアップグレードを試してみる。

    // クラスターパラメータグループを作成
    const clusterParameterGroup = new rds.ParameterGroup(scope, 'ClusterParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略
    })


    //パラメータグループを作成
    const instanceParameterGroup = new rds.ParameterGroup(scope, 'InstanceParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略
    })

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略
    })

しかし以下のようにエラーになる。エンジンバージョンを変える場合は新しいパラメータグループを指定せよと言われる。

The current DB instance parameter group cdkfargatebastionstack-instanceparametergroupa9fcf4ba-1ecfumiwyxog is custom. You must explicitly specify a new DB instance parameter group, either default or custom, for the engine version upgrade. (Service: Rds, Status Code: 400, Request ID: d3b0aab7-d2a1-4da4-957e-3859697c4028)

2. カスタムパラメータグループの名称を変更してアップグレード後のものを新規作成する

調査したところCloudFormationに関して以下の記事を見つけた。

カスタムパラメータグループを使用している状態でアップグレードする場合、パラメータグループの論理IDを変更して新規作成扱いにすればうまくいくというものである。

https://dev.classmethod.jp/articles/upgrade-amazon-rds-using-aws-cloudformation/

そのため以下のように変更してみた。1との差分は論理IDに該当する部分にNewをつけて新規作成扱いしている点である。

    // クラスターパラメータグループを作成
    const clusterParameterGroup = new rds.ParameterGroup(scope, 'NewClusterParameterGroup', { //変更
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略

    })


    //パラメータグループを作成
    const instanceParameterGroup = new rds.ParameterGroup(scope, 'NewInstanceParameterGroup', { //変更
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略
    })

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      //以下略
    })

これはうまくいくかと思ったが、残念ながらうまくいかなかった。1と同じエラーになった。

The current DB instance parameter group cdkfargatebastionstack-instanceparametergroupa9fcf4ba-1ecfumiwyxog is custom. You must explicitly specify a new DB instance parameter group, either default or custom, for the engine version upgrade. (Service: Rds, Status Code: 400, Request ID: a631d2d4-8754-4651-87ad-ee5f559bf61f)

3. DBクラスターの定義でカスタムパラメータグループの使用をコメントアウトし、一旦デフォルトを使用する

ここで作戦を変更し、一旦Aurora MySQL2の状態でデフォルトパラメータグループを使用の状態に変更→その後アップグレードという2段階で行うことを考えた。

初手として以下のようにカスタムパラメータグループの使用箇所をコメントアウトしてデプロイを試みる。

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_2_10_0
      }),
      //parameterGroup: clusterParameterGroup, // コメントアウト
      instanceProps: {
        //parameterGroup: instanceParameterGroup, // コメントアウト
      //以下略
    })

しかしこれもうまくいかない、DBクラスターパラメータグループはデフォルトになってくれたが、DBパラメータグループがデフォルトにならない。削除しようとするが、インスタンスが使用中という状態になり、削除を試行→失敗を繰り返した後デプロイ失敗となってしまった。

上記のためDBクラスターパラメータだけカスタムしている場合は、これでもうまくいく。

One or more database instances are still members of this parameter group cdkfargatebastionstack-instanceparametergroupa9fcf4ba-1ecfumiwyxog, so the group cannot be deleted (Service: Rds, Status Code: 400, Request ID: c554810f-de50
-46fa-8934-6e19f3998862)

4. DBクラスターの定義で、一旦デフォルトのパラメータグループを使用するよう明示して変更する。その後アップグレードする(うまくいった手順)

3と同じく2段階だが、初手のデフォルトパラメータグループを明示する方法に変更してやってみた。

まず以下のように明示的にデフォルトパラメータグループを指定する。

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_2_10_0
      }),
      parameterGroup: rds.ParameterGroup.fromParameterGroupName(scope, 'DefaultClusterParameterGroup', 'default.aurora-mysql5.7'), //明示的にデフォルトを指定
      instanceProps: {
        allowMajorVersionUpgrade: true,
        parameterGroup: rds.ParameterGroup.fromParameterGroupName(scope, 'DefaultParameterGroup', 'default.aurora-mysql5.7'),//明示的にデフォルトを指定
        //
      },

この状態でcdk diffを取ると以下のようにカスタムパラメータグループは削除、かつクラスターやインスタンスはデフォルトのパラメータグループを参照する形となる。

Resources
[-] AWS::RDS::DBClusterParameterGroup ClusterParameterGroupF60E75FA destroy
[-] AWS::RDS::DBParameterGroup InstanceParameterGroupA9FCF4BA destroy
[~] AWS::RDS::DBCluster Database DatabaseB269D8BB
 └─ [~] DBClusterParameterGroupName
     └─ @@ -1,3 +1,1 @@
        [-] {
        [-]   "Ref": "ClusterParameterGroupF60E75FA"
        [-] }
        [+] "default.aurora-mysql5.7"
[~] AWS::RDS::DBInstance Database/Instance1 DatabaseInstance1844F58FD
 └─ [~] DBParameterGroupName
     └─ @@ -1,3 +1,1 @@
        [-] {
        [-]   "Ref": "InstanceParameterGroupA9FCF4BA"
        [-] }
        [+] "default.aurora-mysql5.7"

これでデプロイすると、デフォルトのパラメーターグループになった!

2段階目として、カスタムパラメータグループとDBクラスターのバージョンを変更する。この際DBクラスターはカスタムパラメータグループを参照するようにする。

    // クラスターパラメータグループを作成
    const clusterParameterGroup = new rds.ParameterGroup(scope, 'ClusterParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      parameters: {
        'slow_query_log': '1',
      }
    })


    //パラメータグループを作成
    const instanceParameterGroup = new rds.ParameterGroup(scope, 'InstanceParameterGroup', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      parameters: {
        'slow_query_log': '1',
      }
    })

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: AuroraMysqlEngineVersion.VER_3_02_0 //変更
      }),
      parameterGroup: clusterParameterGroup, // カスタムパラメータグループを指定
      instanceProps: {
        parameterGroup: instanceParameterGroup, // カスタムパラメータグループを指定
        allowMajorVersionUpgrade: true, 
      //以下略
    })

この状態でデプロイを行うと、アップグレードに成功した。またDBクラスターもカスタムパラメータグループを参照している。めでたしめでたし。

オマケ

CDK v.2.50.0ではAurora Serverlessv2用のL2 Constructは存在しない。しかしCloudFormationは対応しているので、以下のようにEscape Hatchesを使用すれば簡単に実装できる。

    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      // 中略
      instanceProps: {
        instanceType: new ec2.InstanceType('serverless'), //インスタンスタイプでserverlessを指定
      //
    })

    // Escape Hatchesを使用して設定。
    const cfnCluster = this.dbCluster.node.defaultChild as rds.CfnDBCluster;
    cfnCluster.addPropertyOverride('ServerlessV2ScalingConfiguration', {
      'MaxCapacity': 5,
      'MinCapacity': 0.5,
    });
    cfnCluster.addPropertyDeletionOverride('EngineMode');

この状態でデプロイすれば以下の通りServerless v2のインスタンスが作成される。

おわりに

簡単にアップグレードできると思いきや意外にハマってしまった... カスタムパラメータグループ使ってるとなかなか厄介。