1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

インフォ・ラウンジAdvent Calendar 2023

Day 9

古めのAWS CDKv2で作ったAuroraServerlessV2を新しいCDKに対応させたときに悩んだ話

Last updated at Posted at 2023-12-08

インフォ・ラウンジ Advent Calendar 2023 の9日目です。

summary

AWS CDKの2.82.0から、AuroraServerlessV2がL2で作成できるようになっています。ただし、旧バージョンのCDKでAuroraServerlessV2を作成した場合、そのままアップデートしてcdk deployしてしまうと、インスタンスのリプレイスが発生し、運用に支障が出ることがわかりました。諸々の問題がありましたが、2.89.0で新方式に切り替えることができました。機能が追加された際にはドキュメントよく確認してアップデートを行いましょう

(DEPRECATED)CDK 2.82.0未満を使用していた頃

先にも書きましたが、Aurora Serverless V2がCDKでL2対応したのは2.82.0からです

それ以前のバージョンでは、直接L2 Constructでは記述が不可能であったため普通にデータベースクラスターを作成したあと、別枠で定義されていたServerlessV2ScalingConfigurationPropertyを使って以下のような形でDBクラスターにキャパシティを割り当てていました。これで作成は可能で運用はできていたのですが、エスケープハッチと呼ばれる手法を使用しており、ベストな方法なのかはわからず少しモヤモヤしていました。

const dbCluster = new rds.DatabaseCluster(this, 'DbCluster', {
  engine: rds.DatabaseClusterEngine.auroraMysql({
    // Aurora Serverless v2に対応した3系を指定
    version: rds.AuroraMysqlEngineVersion.VER_3_02_1
  }),
  instances: 2,
  instanceProps: {
    vpc: props.vpc,
    // インスタンスタイプにサーバーレスを指定
    instanceType: new ec2.InstanceType('serverless'),
    vpcSubnets: vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }),
  }

  // ServerlessV2に対応していないので、Aspectsを使って設定を書き換える
  Aspects.of(dbCluster).add({
    visit(node) {
      if (node instanceof rds.CfnDBCluster) {
        node.serverlessV2ScalingConfiguration = {
          minCapacity: 0.5,
          maxCapacity: 4
        }
      }
    }
  })
}

エスケープハッチとは、L2の機能をL1を使って変更するもので、ここではAspectsを使って書き換えています。動くには動いていたのですが、説明すると深いのでこの点は今回は割愛します(参考リンクを置いておきます)。

CDK2.82.0以上を使用する

満を持してリリースされた2.82.0以降では、以下のようにしてAuroraServerlessV2のクラスタをエスケープハッチ無しで直接立ち上げることができるようになりました。

const dbCluster = new rds.DatabaseCluster(this, 'DbCluster', {
  engine: rds.DatabaseClusterEngine.auroraMysql({
    version: rds.AuroraMysqlEngineVersion.VER_3_02_1
  }),
  vpc: props.vpc,
  vpcSubnets: props.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }),
  writer: rds.ClusterInstance.serverlessV2('Writer', {
    instanceType: new ec2.InstanceType('serverless')
  }),
  readers: [
   rds.ClusterInstance.serverlessV2('Reader', {
     scaleWithWriter: true
   })
  ],
  serverlessV2MinCapacity: 0.5,
  serverlessV2MaxCapacity: 4
})

変更点としては、instancesおよびinstancePropsが非推奨となり、writerreadersserverlessV2MaxCapacityserverlessV2MinCapacityが追加になりました。
writerは単数形、readersは複数形ですね。)

これにより、書き込みインスタンスと読み込みインスタンスそれぞれに個別の設定がすることができるようになり、キャパシティ設定もAspectsを使うことなくプロパティとして割り当てるように記述できるようになりました。わかりやすいですね。

今から新たに作成するときはこちらが良いでしょう。

(はまった)cdkを2.82.0未満から以上へバージョンアップするとインスタンスの置換が発生してしまう。

問題が発生するのは、このバージョンをまたいでCDKをアップデートした場合です。
バージョンアップをしてから、cdk diffを行うと、インスタンスが再作成されるよと警告が出ます。

$ cdk --version
2.82.0

$ cdk diff DatabaseStack

()
Resources
[-] AWS::RDS::DBInstance DbCluster/Instance1 DatabaseInstance1XXXXX destroy
[+] AWS::RDS::DBInstance DbCluster/Writer DatabaseWriterYYYYY

それでは困るので調べて見ると、Identifierが変更されてしまうらしいことがわかったので、以下のようにインスタンスの識別名を既存インスタンスに従うようにしました。
(Identifierがすべての環境で一緒とは限らないので、それぞれの環境でよく確認してください)

// 'Instance1' と明示的に指定する
writer: rds.ClusterInstance.provisioned('Instance1', {
  instanceType: new ec2.InstanceType('serverless'),
}),
readers: [
  rds.ClusterInstance.serverlessV2('Instance2', {
    scaleWithWriter: true
  })
],

しかし、それだけではdestroyの表示が消えません。
これはインスタンスが一度消え、同じ名前で再作成されるように見えます。

Resources
[-] AWS::RDS::DBInstance DbCluster/Instance1 DatabaseInstance1XXXXX destroy
[+] AWS::RDS::DBInstance DbCluster/Instance1 DatabaseInstance1XXXXX

そこで改めてドキュメントを参照してみると、isFromLegacyInstanceProps というマイグレーション時に使うものが実装されていることがわかったので利用してみます。

Only used for migrating existing clusters from using instanceProps to writer and readers.

// 'Instance1' と名前を指定しつつマイグレーション用のフラグを立てる
writer: rds.ClusterInstance.serverlessV2('Instance1', {
  instanceType: new ec2.InstanceType('serverless'),
  isFromLegacyInstanceProps: true
}),
readers: [
  rds.ClusterInstance.serverlessV2('Reader', {
    scaleWithWriter: true,
    isFromLegacyInstanceProps: true
  })
],

今度こそ、と思いながら実行しましたが、isFromLegacyInstancePropsが存在しないという警告が出てハマります。

Object literal may only specify known properties, and 'isFromLegacyInstanceProps' does not exist in type 'ServerlessV2ClusterInstanceProps'.

なぜだ。。。このために実装されたプロパティではなかったのか。。。
(ここでハマってアップデートできず)

***

実はこの時点ではisFromLegacyInstancePropsProvisionedClusterInstancePropsに実装されたプロパティであって、ServerlessV2ClusterInstancePropsには実装されていなかったのです。よく確認できていませんでした。。というか紛らわしい。

要望を出そうにもなんと説明するかとあれこれ悩んでいるうちに、これを解決するPRが立てられ、2.89.0でServerlessV2ClusterInstancePropsにもisFromLegacyInstancePropsが実装されました。

rds: isFromLegacyInstanceProps migration flag with ClusterInstance.serverlessV2

これによりめでたくCDKを最新にすることができました。感謝ですね。[※]

$ cdk --version
2.89.0

$ cdk diff DatabaseStack
There were no differences

[※]: ちなみに、一度アップデートに成功したからといって isFromLegacyInstancePropsを消すことはできないようです(再びdestroy表示になる)。いずれ外せるのかもしれませんが。

まとめ

CDK2.82.0未満で作られたAuroraServerlessV2があるときは以下のようにしましょう

  • CDKを2.82.0以上にアップデートする
    • ServerlessV2ClusterInstancePropsを使用している場合は2.89.0以上
  • インスタンスのIdentifier(名前)を一致させる
  • instance,instancePropsをやめ、writer,readersに書き換える
  • isFromLegacyInstancePropstrueに設定する

AWS CDKは次々と機能追加や仕様変更が入っています(現時点では2.114.1まで進んでいます)。基本的には新しいバージョンを使っていく方がよいですが、バージョンアップ時に予期せぬ変更が入ったり、インスタンスの置換や廃棄が行われてしまうことがあります。溜まっていくと多方面でdiffが発生して大変になってくるので、定期的にバージョンを上げるようにしたほうがいいですね。逆に対応したからといってすぐに書き換えるのではなく、変更点をよく読んで修正をあてていきましょう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?