AWS CDK/CloudFormation管理下のRDS/Auroraインスタンスのバージョンアップが今はすごい簡単な話


はじめに

昔はAWS CDK/CloudFormation管理下のRDS/Auroraインスタンスのバージョンアップをするにはインスタンスの再作成が必要でした。
CloudFormation Resource Importの登場後はこの機能を使うことで再作成を回避できましたが、それでもDeletionPolicy: Retainを一時的に指定してCloudFormationの管理下から外してその後Importするという手間がかかりました。

CloudFormation Resource ImportによるRDSバージョンアップ時の定義差分を解消する一手法 - ZOZO TECH BLOG

だけど今は、CDK/CFnから任意のタイミングでバージョンアップすることもできます。さらに、マネジメントコンソール上でバージョンアップしてからCDK/CFnコードの変更&デプロイを行うことでコード結果的に整合性を持たせることができます。前者は即時更新されますが、後者の方法はメンテナンスタイムにバージョンアップするように設定してバージョンアップ後にコードを更新ということができます。

ただし、インプレースアップグレードに対応しているバージョンである必要があるので注意してください。たとえばAurora PostgreSQLの11→12対応は割と最近でした。

Amazon Aurora が PostgreSQL 11 から 12 へのインプレースアップグレードをサポート

なんでできるようになったの

AWS::RDS::DBCluster - EngineVersionAWS::RDS::DBInstance - EngineVersionUpdate requiresReplacementからSome interruptionsに変更されたからです。

スタックのリソースの更新動作 - AWS CloudFormation

いつ更新されたかはわからないです、ドキュメントの更新履歴を検索してみたけど残念ながらヒットしませんでした。

やってみた

AWS CDKで下記のとおりスタックを定義します。

lib/database-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  AuroraPostgresEngineVersion,
  DatabaseCluster,
  DatabaseClusterEngine,
} from 'aws-cdk-lib/aws-rds';
import { SubnetType, Vpc } from 'aws-cdk-lib/aws-ec2';

export class DatabaseStack extends Stack {
  public readonly cluster: DatabaseCluster;

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

    const vpc = new Vpc(this, 'Vpc', {});

    const cluster = new DatabaseCluster(this, 'MyDatabase', {
      engine: DatabaseClusterEngine.auroraPostgres({
        version: AuroraPostgresEngineVersion.VER_10_18, // before
        // version: AuroraPostgresEngineVersion.VER_11_13, // after
      }),
      instanceProps: {
        vpc,
        vpcSubnets: {
          subnetType: SubnetType.PUBLIC,
        },
        autoMinorVersionUpgrade: false,
      },

      instances: 1,
    });
    this.cluster = cluster;
  }
}

クロススタック参照されている状態でも問題なく更新できることをチェックしたかったので、データベースクラスターの識別子を参照してS3バケットを作成しておきます。

bin/cdk-aurora-rds-engine-upgrade-test.ts
#!/usr/bin/env node

import 'source-map-support/register';
import { App } from 'aws-cdk-lib';
import { DatabaseStack } from '../lib/database-stack';
import { DependentStack } from '../lib/dependent-stack';

const app = new App();
const { cluster } = new DatabaseStack(app, 'DatabaseStack', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
  },
});
new DependentStack(app, 'DependentStack', {
  clusterName: cluster.clusterIdentifier,
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
  },
});
lib/dependent-stack.ts
import { RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Bucket } from 'aws-cdk-lib/aws-s3';

interface DependentStackProps extends StackProps {
  clusterName: string;
}

export class DependentStack extends Stack {
  constructor(scope: Construct, id: string, props: DependentStackProps) {
    super(scope, id, props);

    new Bucket(this, 'Bucket', {
      bucketName: props.clusterName,
      removalPolicy: RemovalPolicy.DESTROY,
    });
  }
}
  1. CDKでデプロイ
  2. マネコンでアップグレード
  3. CDKのコードを更新(バージョンを合わせる)
  4. CDKでデプロイ

diffではmay be replacedと表示されるが何も起こらずデプロイが完了する。

 npm run cdk diff -- --all

> [email protected] cdk
> cdk "diff" "--all"

Stack DatabaseStack
Resources
[~] AWS::RDS::DBCluster MyDatabase MyDatabase1E2517DB 
 ├─ [~] DBClusterParameterGroupName
 │   ├─ [-] default.aurora-postgresql10
 │   └─ [+] default.aurora-postgresql11
 └─ [~] EngineVersion
     ├─ [-] 10.14
     └─ [+] 11.11
[~] AWS::RDS::DBInstance MyDatabase/Instance1 MyDatabaseInstance12A2ABB05 may be replaced
 └─ [~] EngineVersion (may cause replacement)
     ├─ [-] 10.14
     └─ [+] 11.11

Stack DependentStack
  1. CDKでデプロイ
  2. CDKのコードを更新(バージョンを上げる)
  3. CDKでデプロイ

インプレースでバージョンアップが行われた。リソースの再作成は行われていない。

npm run cdk diff -- --all

> [email protected] cdk
> cdk "diff" "--all"

Stack DatabaseStack
Resources
[~] AWS::RDS::DBCluster MyDatabase MyDatabase1E2517DB 
 ├─ [~] DBClusterParameterGroupName
 │   ├─ [-] default.aurora-postgresql10
 │   └─ [+] default.aurora-postgresql11
 └─ [~] EngineVersion
     ├─ [-] 10.14
     └─ [+] 11.11
[~] AWS::RDS::DBInstance MyDatabase/Instance1 MyDatabaseInstance12A2ABB05 may be replaced
 └─ [~] EngineVersion (may cause replacement)
     ├─ [-] 10.14
     └─ [+] 11.11

Stack DependentStack
There were no differences

あとがき

簡単にバージョンアップできてうれしい。何か穴や考慮漏れがあればコメントを貰えるとありがたいです。