mazyu36の日記

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

AWS CDKで作ったAuroraクラスターはRDS Blue/Green Deploymentsを使って運用できるのか

本ブログでは何回かAWS CDKで構築したAurora(RDS)クラスターを運用の観点で検証してきました。

当たり前ですがCDKで作ったとしても、そのあとは運用を行っていく必要があるので、運用継続ができるかは重要かと思います。特にDB(ステートフルなリソース)は扱いが難しいため、さまざまな検証をしています。

今回はAmazon RDS Blue/Green Deployments(以降B/G デプロイと記載)が題材です。

B/GデプロイはCloudFormation(CDK)非対応なので、マネコン等からの操作を行う必要があります。そのため実施するとCDKの実装と実態が必ず乖離します。

今回はAWS CDKで作ったAuroraクラスターに対してB/G デプロイを行い、その後CDKと実態を一致させることで運用継続ができるのかを検証します。

https://pages.awscloud.com/rs/112-TZM-766/images/20221222_25th_ISV_DiveDeepSeminar_RDS_BlueGreenDeployments.pdf

先に結論を記載すると、「できなくはないが、CDKと実態を一致させる際にクラスターの再起動が行われる可能性がある」です。

Amazon RDS Blue/Green Deployments とは

2022/11にGAした機能で、RDSにおいてBlue/Green Deploymentsの考え方を適用し、ダウンタイムを最小限にしてアップグレード等が行えます。

aws.amazon.com

制約などは以下の記事がよくまとまっており、非常に参考になります。

zenn.dev

当初ECSのそれと同じような感じかと思っていましたが、以下のような違いがあります。

  • ダウンタイムは完全にゼロとはならない。とはいえ通常のクラスター更新よりは圧倒的に短時間で済む。
  • BlueからGreenに切り替えた後は戻ることはできない(ECSのB/Gデプロイは戻れる)。

EOLによるクラスターのバージョンアップなどはいずれ必ず発生するので、使用を検討したいところです。しかし公式のドキュメント上、CloudFormation(CDK)は非対応であることが明記されています。

docs.aws.amazon.com

しかし、B/Gデプロイ実施後に、CDKの実装を実態に合わせることでその後運用を継続できそうな気もするので検証してみます。

やりたいこと整理

今回流れが若干複雑なので整理します。

0. 前提

ここではメジャーバージョンアップを想定し、Aurora MySQL v.2.11.1 → v.3.02.0 のアップグレードで検証してみることにします。

また、通常運用ではパラメータグループをカスタマイズしていることが多いと思うので、クラスターパラメータグループは変更あり(≠デフォルト)として進めます。

1. 初期状態

test-auroraの名称で v2.11.1クラスターを作成します。なお右端のCDKの枠の中のAuroraはCDK上の実装のバージョンを示します。

この状態ではリソースとCDKの実装のバージョンは一致しています。

2. B/Gデプロイ発動

Greenのクラスター(v.3.02.0)が作成されます。この段階ではtest-auroraのバージョンはまだ変わっていません。

3. 切り替え

B/Gデプロイの切り替え操作を行うことで、test-aurorav.3.02.0になります。この段階でCDKの実装のバージョンとズレが生じることになります。

また旧バージョンのクラスターがoldの名称で残りますが、こちらは用済みなので削除します。

4. CDKの実装を実態と一致させる

CDKの実装においてv.3.02.0とし、実態と一致させます。この後クラスターに対してCDKの変更が反映できるか(運用を継続できるか)を検証することになります。

検証

0. 前提

今回用意した実装としては以下になります。ポイント箇所はコメントを付与しています。

    // Aurora MySQL 2.10.0用のクラスターパラメータグループ
    const clusterParameterGroupV2 = new rds.ParameterGroup(scope, ' ClusterParameterGroupV2', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_2_11_1
      }),
      parameters: {
        'binlog_format': 'MIXED' // B/G デプロイで必要。 
      }
    })


    // Aurora MySQL 3.02.0用のクラスターパラメータグループ
    const clusterParameterGroupV3 = new rds.ParameterGroup(scope, 'ClusterParameterGroupV3', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_3_02_0
      }),
      parameters: {
        'binlog_format': 'MIXED'
      }
    }).bindToCluster({});  // クラスターパラメータグループを生成するため。

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_2_11_1  // v2.11.1を指定
      }),
      clusterIdentifier: 'test-aurora',
      credentials: {
        username: 'admin',
        secretName: 'dbSecret'
      },
      instances: 1,
      parameterGroup: clusterParameterGroupV2,
      instanceProps: {
        vpc: props.vpcConstruct.vpc,
        instanceType: ec2.InstanceType.of(InstanceClass.T3, InstanceSize.LARGE),
        publiclyAccessible: false,
        deleteAutomatedBackups: false,
        securityGroups: [props.securityGroupConstruct.databaseSg],
        vpcSubnets: {
          subnets: [props.vpcConstruct.subnetDB1a, props.vpcConstruct.subnetDB1c],
        }
      },
      port: 3306,
      defaultDatabaseName: 'test',
      subnetGroup: dbSubnetGroup,
      backup: {
        retention: cdk.Duration.days(1)
      },
      storageEncrypted: false,
      removalPolicy: cdk.RemovalPolicy.DESTROY
    })

初期状態のクラスターとして、v2.11.1のクラスターパラメータグループとv2.11.1のAuroraクラスターを作成します。なおB/Gデプロイを使うためには、'binlog_formatMIXEDであることが必要です。このパラメーターはstaticなので適用のためには再起動が必要です。

またアップグレード後のv3.02.0に対応するクラスターパラメータグループも作成しておきます。理由としては検証で以下のようにマネコン上からGreenを作成する際に使用したいからです。

  • マネコン上からGreenを作成する際に、CDKで作成しておいたv3.02.0のクラスターパラメータグループをアタッチして作成する。
  • B/Gデプロイの切り替え実施後に、CDKの実装を一致させる。この際CDK上でv3.02.0のクラスターパラメータグループをアタッチして実態と一致させる。

なお、実装上クラスターにアタッチされていないクラスターパラメータグループはそのままだと作成されない点に注意が必要です。.bindToCluster({})を付与することで、クラスターにアタッチされていないクラスターパラメータグループも作成されます。詳細は以下のIssueに記載されています。

github.com

1. 初期状態

Auroraクラスター(test-aurora)のデプロイを行います。この段階ではv2.11.1クラスターが作成されます。

2. B/Gデプロイ発動

マネコン上からB/Gデプロイの操作を行います。Greenを作成する際に以下の設定としています。

  • バージョンはv3.02.0
  • クラスターパラメータグループはCDKで生成しておいたもの(≠デフォルト)

上記を元にしばし待つとGreenが作成されました。

3. 切り替え

切り替えを行うと、test-aurorav3.02.0(元Green)に変わります。クラスターパラメータグループはCDKで生成しておいたものがセットされています。

また元Blueのクラスターがoldとして残ります。oldは不要なので削除しておきます。

4. CDKの実装を実態と一致させる

ここからが本題です。まずCDKの実装を実態と一致させます。

    // Aurora MySQL 3.02.0用のクラスターパラメータグループ
    const clusterParameterGroupV3 = new rds.ParameterGroup(scope, 'ClusterParameterGroupV3', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_3_02_0
      }),
      parameters: {
        'binlog_format': 'MIXED'
      }
    }) //変更

    //https://github.com/aws/aws-cdk/issues/9741

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_3_02_0 // 変更
      }),
      clusterIdentifier: 'test-aurora',
      credentials: {
        username: 'admin',
        secretName: 'dbSecret'
      },
      instances: 1,
      parameterGroup: clusterParameterGroupV3, // 変更

      // 以下略

v3.02.0クラスターパラメータグループに付与していた.bindToCluster({})は除去します。その上でクラスターのエンジンのバージョンおよび、パラメータグループの切り替えを行います。

この状態でcdk deployを行いエラーとならないことを確認します。CloudFormationテンプレートは更新されるが、リソース反映は空振りして終わるのが期待値です。

では実施してみます。

16:46:52 | UPDATE_FAILED        | AWS::RDS::DBCluster                         | DatabaseB269D8BB
Resource handler returned message: "Cannot upgrade aurora-mysql from 8.0.mysql_aurora.3.02.2 to 8.0.mysql_aurora.3.02.0 (Service: Rds, Status Code: 400, Request ID: d763416d-b
65b-455c-88fb-457f3893371d)" (RequestToken: ffa8e3f9-3f16-0ecb-6288-285e9ea04be7, HandlerErrorCode: InvalidRequest)

...エラーになりました。v3.02.0からv3.02.0にアップデートしようとし、おかしくなっていようです。直接CDKの実装と実態を一致させるのは難しそうです。

延長戦

どうにか一致させられないか試行錯誤してみたところ、一旦クラスターパラメータグループをデフォルトにして、再度付け直すということを行えば可能でした。

以下のようにクラスターパラメータグループを一旦コメントアウトします。

    // DBクラスターを作成
    this.dbCluster = new rds.DatabaseCluster(scope, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_3_02_0
      }),
      clusterIdentifier: 'test-aurora',
      credentials: {
        username: 'admin',
        secretName: 'dbSecret'
      },
      instances: 1,
      // parameterGroup: clusterParameterGroupV3, // コメントアウト
   // 以下略

この状態でcdk deployを行うと反映させることができ、CDKの実装と実態を一致させることができました(デフォルトのクラスターパラメータグループを使用している状態)。

あとはコメントアウトを外して再度cdk deployを行うことで、変更したクラスターパラーメータグループをアタッチした状態でCDKの実装と実態を一致させることができます。

ただし注意点として、クラスターパラメータグループを変更する際は再起動が走ります(上記だと結果的に2回再起動が行われることになる)。

まとめ

以下の条件で、AuroraにおいてB/Gデプロイを発動し、その後CDKと実態を一致させられるかを検証しました。

  • メジャーバージョンアップを実施。
  • クラスターパラメータグループは変更あり(≠デフォルト)

その結果、CDKと実態を一致させるタイミングではストレートに反映させることはできないことがわかりました。

また、一度クラスターパラメータグループをデフォルトに変えて反映し、再度変更ありのクラスターパラメータグループを反映する、というように二段階にすれば解決できました。ただしこの際にクラスターの再起動が発生することがわかりました。

今回はエンジンのメジャーバージョンアップにより、変更ありのクラスターパラメータグループのバージョンアップも発生しています。そのため以下のようなケースでは、CDKとB/Gデプロイ実施後の実態をストレートに一致させることができそうです。

  • パラメータグループを変更していない、デフォルトでしか使っていない場合(ただし実運用だとこれは稀な認識)
  • マイナーバージョンアップである。パラメータグループのバージョンアップが生じない。

以下私見です。

まずB/Gデプロイによりダウンタイムが減らすのは価値があるかと思います。クラスターパラメータグループ適用による再起動の可能性があるとはいえ、インプレースでアップグレードする時よりもダウンタイムははるかに短いからです。

ですが数分でもダウンタイムは発生するので、オンライン無停止で行うのは厳しいという印象です(そもそもCDKを使わないB/Gデプロイでもダウンタイムは0ではないですが)。たとえ短時間であっても計画停止の期間を取り、安全に行うのが良いかと思います。

あまり綺麗な結果ではないですが、アップグレード戦略の1つとして今回はRDS Blue/Green Deployments×CDKの検証結果についてまとめました。ご参考になれば幸いです。

※CDKで変更有りのパラメータグループを使用したAurora(RDS)クラスターを、インプレースでアップグレードする手順は以下で紹介しています。

mazyu36.hatenablog.com