🐻‍❄️

ステージングサイトでAmazon Aurora Global DBを試してみた

2024/11/29に公開

はじめに

こんにちは。レンティオでエンジニアやっている宮原です。

今回は本番環境で導入されているAmazon Aurora Global DatabaseのPostgreSQL※のDBエンジンのバージョンアップを行いたかったので、一時的にステージング環境に同じものを構築して気軽に試せるようにしてみました。
この記事では自分のプロダクトでも試してみたい人向けに手順をざっくりまとめてみました。

※詳細は 🌏レンティオのディザスタリカバリ(災害復旧)への取り組みで導入 参照

試されるフルスタック、AWS戦闘力はいかほどか

AWS Cloud Quest内での記念撮影
ちなみに私のAWS戦闘力は無料のAWS Cloud Questのクラウドプラクティショナーをクリアした程度です。
プレイしてた頃のキャプチャー

レンティオに入社して驚いたのが、インフラ専任のエンジニアが居なかったことです。
ということは自分にインフラ関連のタスクが当たった時は頑張るしかないということで、AWSの知識を深めるためにも、AWS CDKを使って構築してみることにしました。

全体像

以下のような流れで検証しました。

前提条件

  • Git管理しているAWS CDKを利用している
  • 動作検証可能なステージングサイトもしくはアプリがある
  • すでにAuroraを利用している

🔨 検証用DBのスタック準備

既存のステージング用のスタックから複製で検証用のセカンダリがヘッドレス構成のグローバルデータベースクラスタを作成したいと思います。
構成図

cdkでインフラをデプロイするコードを準備

bin/aws-cdk.ts
#!/usr/bin/env node
import 'source-map-support/register'
import { App } from 'aws-cdk-lib'
// 中略
import { StagingClonedDbClusterStack } from '../lib/rds/staging-cloned-dbcluster-stack'
import { SecondaryStagingClonedDbClusterStack } from '../lib/rds/secondary-staging-cloned-dbcluster-stack'

const apNortheast1 = { env: { region: 'ap-northeast-1', account: process.env.CDK_DEFAULT_ACCOUNT } }
const apNortheast3 = { env: { region: 'ap-northeast-3', account: process.env.CDK_DEFAULT_ACCOUNT } }
const app = new App()
const cdkEnv = app.node.tryGetContext('env') // コンテキスト変数でコマンドを実行する環境を指定

if (cdkEnv === 'production') {
  // 中略
} else if (cdkEnv === 'staging') {
  // グローバルDB検証用(クローン)
  new StagingClonedDbClusterStack(app, 'rds-staging-cloned', apNortheast1)
  new SecondaryStagingClonedDbClusterStack(app, 'rds-secondary-staging-cloned', apNortheast3)
  // 中略
} else {
  throw new Error('Please specify environment')
}
lib/rds/staging-cloned-dbcluster-stack.ts(東京リージョン用)
import { Stack, StackProps, cloudformation_include } from 'aws-cdk-lib'
import { Construct } from 'constructs'

export class StagingClonedDbClusterStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props)

    new cloudformation_include.CfnInclude(this, 'Template', {
      templateFile: 'cfn-migration/rds/rds-staging-cloned.yml'
    })
  }
}
lib/rds/staging-cloned-dbcluster-stack.ts(大阪リージョン用)
import { Stack, StackProps, cloudformation_include } from 'aws-cdk-lib'
import { Construct } from 'constructs'

export class SecondaryStagingClonedDbClusterStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props)

    new cloudformation_include.CfnInclude(this, 'Template', {
      templateFile: 'cfn-migration/rds/rds-staging-secondary-cloned.yml',
    })
  }
}

東京リージョン用のrds-staging-cloned.ymlを作成

rds-staging.yml(既存のステージング用)からコピーでrds-staging-cloned.ymlを作成し編集します。

編集内容
  • 他の環境と被らないようにIPの変更
  • 開発用データを使いたいのでSnapshotIdentifierにテストデータ用のスナップショットを追加
cfn-migration/rds/rds-staging-cloned.yml
Parameters:
  vpcCidrBlock:
    (中略)
-    Default: "10.XXX.0.0/16"
+    Default: "10.120.0.0/16"
  subnetACidrBlock:
    (中略)
-    Default: "10.XXX.1.0/24"
+    Default: "10.120.1.0/24"
  subnetBCidrBlock:
    (中略)
-    Default: "10.XXX.2.0/24"
+    Default: "10.120.2.0/24"
  databaseName:
    Type: String
-    Default: "rentioStaging"
+    Default: "rentioStagingClone"
  (中略)
Resources:
  DBCluster:
    (中略)
    Properties:
      (中略)
+      SnapshotIdentifier: "snapshot-dbcluster-testdata-2024-11-26"

cdk deploy⚡️

このコマンドでcdk diff(比較)を実行してみます

npx cdk diff -c env=staging rds-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-staging-cloned
Stack rds-staging-cloned
Template
+[+] AWSTemplateFormatVersion AWSTemplateFormatVersion: 2010-09-09
+[+] Description Description:

Security Group Changes
┌───┬────────────────────────────────┬─────┬────────────┬──────────────────────┐
│   │ Group                          │ Dir │ Protocol   │ Peer                 │
├───┼────────────────────────────────┼─────┼────────────┼──────────────────────┤
+│ + │ ${Template/******************} │ In  │ TCP 5432   │ sg-************      │
+│ + │ ${Template/******************} │ Out │ Everything │ Everyone (IPv4)      │
└───┴────────────────────────────────┴─────┴────────────┴──────────────────────┘

Parameters
+[+] Parameter Template/vpcCidrBlock vpcCidrBlock: {"Type":"String","Default":"10.120.0.0/16","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/subnetACidrBlock subnetACidrBlock: {"Type":"String","Default":"10.120.1.0/24","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/subnetBCidrBlock subnetBCidrBlock: {"Type":"String","Default":"10.120.2.0/24","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/databaseName databaseName: {"Type":"String","Default":"rentioStagingClone"}
+[+] Parameter Template/dbUserName dbUserName: {"Type":"String","Default":"rentio"}
+[+] Parameter Template/dbUserPasswordParameterName dbUserPasswordParameterName: {"Type":"AWS::SSM::Parameter::Name","Default":"/dbPassword/staging"}
+[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Resources
+[+] AWS::EC2::VPC Template/vpcForDB vpcForDB
+[+] AWS::EC2::Subnet Template/subnetA subnetA
+[+] AWS::EC2::Subnet Template/subnetB subnetB
+[+] AWS::EC2::InternetGateway Template/igwForVPC igwForVPC
+[+] AWS::EC2::DHCPOptions Template/doptForVPC doptForVPC
+[+] AWS::EC2::NetworkAcl Template/aclForVPC aclForVPC
+[+] AWS::EC2::RouteTable Template/RouteTable RouteTable
+[+] AWS::EC2::Route Template/RouteToInternet RouteToInternet
+[+] AWS::EC2::SubnetRouteTableAssociation Template/SubnetARouteTableAssociation SubnetARouteTableAssociation
+[+] AWS::EC2::SubnetRouteTableAssociation Template/SubnetBRouteTableAssociation SubnetBRouteTableAssociation
+[+] AWS::RDS::DBClusterParameterGroup Template/DBClusterParameterGroupPostgresql15 DBClusterParameterGroupPostgresql15
+[+] AWS::RDS::DBSubnetGroup Template/dbsubnetdefaultvpcForDB dbsubnetdefaultvpcForDB
+[+] AWS::EC2::SecurityGroup Template/sgrdslaunchwizard6 sgrdslaunchwizard6
+[+] AWS::RDS::DBCluster Template/DBCluster DBCluster
+[+] AWS::RDS::DBInstance Template/MasterDBInstance MasterDBInstance
+[+] AWS::RDS::DBInstance Template/ReadReplicaDBInstance ReadReplicaDBInstance
+[+] AWS::EC2::NetworkAclEntry Template/acl1 acl1
+[+] AWS::EC2::NetworkAclEntry Template/acl2 acl2
+[+] AWS::EC2::SubnetNetworkAclAssociation Template/subnetacl1 subnetacl1
+[+] AWS::EC2::SubnetNetworkAclAssociation Template/subnetacl2 subnetacl2
+[+] AWS::EC2::VPCGatewayAttachment Template/gw1 gw1
+[+] AWS::EC2::VPCDHCPOptionsAssociation Template/dchpassoc1 dchpassoc1
+[+] AWS::EC2::SecurityGroupEgress Template/egress1 egress1
+[+] AWS::EC2::SecurityGroupIngress Template/ingressCopilotStaging ingressCopilotStaging
+[+] AWS::EC2::VPCPeeringConnection Template/EC2VPCPeeringConnectionCopilotStaging EC2VPCPeeringConnectionCopilotStaging
+[+] AWS::EC2::Route Template/EC2RouteCopilotStaging1ToRDS EC2RouteCopilotStaging1ToRDS
+[+] AWS::EC2::Route Template/EC2RouteCopilotStaging2ToRDS EC2RouteCopilotStaging2ToRDS
+[+] AWS::EC2::Route Template/EC2RouteRDSToCopilotStaging EC2RouteRDSToCopilotStaging


✨  Number of stacks with differences: 1

上記の内容で問題がなければdiffdeployに書き換えてデプロイ実行します。
(所要時間:30分程度)

デプロイが完了するとこのように既存のステージングと同等のデータベースクラスタができあがります。
デプロイ後

東京リージョン用のインスタンスクラスを変更

普段はコスト節約のためステージングではdb.t4g.mediumを使ってますが、グローバルデータベースにするにはメモリを大量に消費するアプリケーションに最適化されたDBインスタンスクラスが必要なので変更します。

編集内容
cfn-migration/rds/rds-staging-cloned.yml
Resources:
  (中略)
  MasterDBInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      (中略)
-      DBInstanceClass: db.t4g.medium
+      DBInstanceClass: db.r6g.large
  ReadReplicaDBInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      (中略)
-      DBInstanceClass: db.t4g.medium
+      DBInstanceClass: db.r6g.large

cdk deploy⚡️

diffを実行してインスタンスクラスを変更することが確認できたらdeployに書き換えてデプロイ実行します。
(所要時間:15分程度)

npx cdk diff -c env=staging rds-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-staging-cloned
Stack rds-staging-cloned
Resources
[~] AWS::RDS::DBInstance Template/MasterDBInstance MasterDBInstance
 └─ [~] DBInstanceClass
-     ├─ [-] db.t4g.medium
+     └─ [+] db.r6g.large
[~] AWS::RDS::DBInstance Template/ReadReplicaDBInstance ReadReplicaDBInstance
 └─ [~] DBInstanceClass
-     ├─ [-] db.t4g.medium
+     └─ [+] db.r6g.large

デプロイが完了するとインスタンスクラスがdb.r6g.largeの状態になります。
デプロイ後

セカンダリを作成しグローバルDB化する

東京リージョン用を複製しセカンダリの大阪リージョン用を作成

rds-staging-cloned.yml(東京リージョン用)からコピーでrds-staging-secondary-cloned.ymlを作成し、グローバルDB向けにそれぞれ編集します。

編集内容(プライマリ/東京リージョン用)
  • GlobalClusterIdentifierとGlobalClusterを追加
cfn-migration/rds/rds-staging-cloned.yml
Parameters:
  (中略)
+  GlobalClusterIdentifier:
+    Type: String
+    Default: "staging-cloned-global-database"
+    Description: Identifier used for global database cluster
+    AllowedPattern: '^[a-zA-Z]{1}(?:-?[a-zA-Z0-9]){0,62}$'

Resources:
  (中略)
+  GlobalCluster:
+    Type: 'AWS::RDS::GlobalCluster'
+    Properties:
+      GlobalClusterIdentifier: !Ref GlobalClusterIdentifier
+      SourceDBClusterIdentifier: !Ref "DBCluster"
編集内容(セカンダリ/大阪リージョン用)
  • ヘッドレス構成にするのでMasterDBInstance、ReadReplicaDBInstanceはカット
  • KMSキーを明示的に指定する必要があるので追加
  • セカンダリクラスタでは使わない設定は削除
cfn-migration/rds/rds-staging-secondary-cloned.yml
Parameters:(中略)
-  databaseName:
-    Type: String
-    Default: "rentioStagingClone"
-  dbUserName:
-    (中略)
-  dbUserPasswordParameterName:
-    (中略)
+  GlobalClusterIdentifier:
+    Type: String
+    Default: "staging-cloned-global-database"
+    Description: Identifier used for global database cluster
+    AllowedPattern: '^[a-zA-Z]{1}(?:-?[a-zA-Z0-9]){0,62}$'

Resources:
  (中略)
  DBCluster:
    Type: AWS::RDS::DBCluster
    DeletionPolicy: Snapshot
    Properties:
      (中略)
      EngineVersion: 15.2
+      GlobalClusterIdentifier: !Ref GlobalClusterIdentifier
      DBClusterIdentifier: !Sub dbcluster-${AWS::StackName}
-      DatabaseName: !Ref "databaseName"
      DeletionProtection: false
-      MasterUsername: !Ref "dbUserName"
-      MasterUserPassword: !Sub '{{resolve:ssm-secure:${dbUserPasswordParameterName}:1}}'
-      SnapshotIdentifier: "snapshot-dbcluster-testdata-2024-11-26"
      (中略)
+      KmsKeyId: "arn:aws:kms:ap-northeast-3:*********:key/***********************"

-  MasterDBInstance:
-      (中略)
-  ReadReplicaDBInstance:
-      (中略)
  (中略)
-  #
-  ## VPC Peering
-  #
-  EC2VPCPeeringConnectionCopilotStaging:
-    Type: "AWS::EC2::VPCPeeringConnection"
-  (中略)

cdk deploy⚡️

diffを実行して変更内容が確認できたらdeployに書き換えてデプロイ実行します。
(所要時間:20分程度)

npx cdk diff -c env=staging rds-staging-cloned rds-secondary-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-staging-cloned rds-secondary-staging-cloned
Stack rds-staging-cloned
Parameters
+[+] Parameter Template/GlobalClusterIdentifier GlobalClusterIdentifier: {"Type":"String","Default":"staging-cloned-global-database","AllowedPattern":"^[a-zA-Z]{1}(?:-?[a-zA-Z0-9]){0,62}$","Description":"Identifier used for global database cluster"}

Resources
+[+] AWS::RDS::GlobalCluster Template/GlobalCluster GlobalCluster

Stack rds-secondary-staging-cloned
Template
+[+] AWSTemplateFormatVersion AWSTemplateFormatVersion: 2010-09-09
+[+] Description Description:

Security Group Changes
┌───┬────────────────────────────────┬─────┬────────────┬─────────────────┐
│   │ Group                          │ Dir │ Protocol   │ Peer            │
├───┼────────────────────────────────┼─────┼────────────┼─────────────────┤
+│ + │ ${Template/******************} │ Out │ Everything │ Everyone (IPv4) │
└───┴────────────────────────────────┴─────┴────────────┴─────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Parameters
+[+] Parameter Template/vpcCidrBlock vpcCidrBlock: {"Type":"String","Default":"10.120.0.0/16","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/subnetACidrBlock subnetACidrBlock: {"Type":"String","Default":"10.120.1.0/24","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/subnetBCidrBlock subnetBCidrBlock: {"Type":"String","Default":"10.120.2.0/24","AllowedPattern":"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})","ConstraintDescription":"must be a valid IP CIDR range of the form x.x.x.x/x.","MaxLength":"18","MinLength":"9"}
+[+] Parameter Template/GlobalClusterIdentifier GlobalClusterIdentifier: {"Type":"String","Default":"staging-cloned-global-database","AllowedPattern":"^[a-zA-Z]{1}(?:-?[a-zA-Z0-9]){0,62}$","Description":"Identifier used for global database cluster"}
+[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Resources
+[+] AWS::EC2::VPC Template/vpcForDB vpcForDB
+[+] AWS::EC2::Subnet Template/subnetA subnetA
+[+] AWS::EC2::Subnet Template/subnetB subnetB
+[+] AWS::EC2::InternetGateway Template/igwForVPC igwForVPC
+[+] AWS::EC2::DHCPOptions Template/doptForVPC doptForVPC
+[+] AWS::EC2::NetworkAcl Template/aclForVPC aclForVPC
+[+] AWS::EC2::RouteTable Template/RouteTable RouteTable
+[+] AWS::EC2::Route Template/RouteToInternet RouteToInternet
+[+] AWS::EC2::SubnetRouteTableAssociation Template/SubnetARouteTableAssociation SubnetARouteTableAssociation
+[+] AWS::EC2::SubnetRouteTableAssociation Template/SubnetBRouteTableAssociation SubnetBRouteTableAssociation
+[+] AWS::RDS::DBClusterParameterGroup Template/DBClusterParameterGroupPostgresql15 DBClusterParameterGroupPostgresql15
+[+] AWS::RDS::DBSubnetGroup Template/dbsubnetdefaultvpcForDB dbsubnetdefaultvpcForDB
+[+] AWS::EC2::SecurityGroup Template/sgrdslaunchwizard6 sgrdslaunchwizard6
+[+] AWS::RDS::DBCluster Template/DBCluster DBCluster
+[+] AWS::EC2::NetworkAclEntry Template/acl1 acl1
+[+] AWS::EC2::NetworkAclEntry Template/acl2 acl2
+[+] AWS::EC2::SubnetNetworkAclAssociation Template/subnetacl1 subnetacl1
+[+] AWS::EC2::SubnetNetworkAclAssociation Template/subnetacl2 subnetacl2
+[+] AWS::EC2::VPCGatewayAttachment Template/gw1 gw1
+[+] AWS::EC2::VPCDHCPOptionsAssociation Template/dchpassoc1 dchpassoc1
+[+] AWS::EC2::SecurityGroupEgress Template/egress1 egress1


✨  Number of stacks with differences: 2

デプロイ後

ステージングサイトのDBエンドポイントを変更

あとは所定の方法でステージングサイトのDBエンドポイントを変更すれば準備完了です。
最近出てきたGlobal Database ライターエンドポイントを使うとリージョンまたぎフェイルオーバー後のエンドポイントの変更が不要になるようです。

エンドポイント

ステージングで動作検証

テストユーザーでログインしてみたりしてDBエンドポイントが変わっていることを確認しておきます。

何らか動作を試す

ステージングで動作確認している例
フェイルオーバーした時にサイトはどうなるのか試してみたり、ハートマークのお気に入りボタン押して商品を追加してみたり、削除してみたりDBに触れる操作するなど...
そのときどきで気になる動作を試してみたりします。

🧨 DBエンジンのバージョンアップを試す

段階を踏んでcdk deployするので注意が必要です。
本番用を用意した時はGitHubのPull Requestを各ステップごとに分けてAWSに詳しい人を含めた他メンバー達にレビューしていただき、リリースするときはSlackのハドルミーティングで画面共有しながらデプロイを行いました。

作業用Pull Request

セカンダリにインスタンス追加

編集内容
  • プライマリと同等のMasterDBInstanceを追加
  • PerformanceInsightsKMSKeyIdは大阪リージョン用のKMSキーを指定
cfn-migration/rds/rds-staging-secondary-cloned.yml
Resources:
+  MasterDBInstance:
+    Type: AWS::RDS::DBInstance
+    Properties:
+      (中略)
+      EngineVersion: 15.2
+      PerformanceInsightsKMSKeyId: "*********"
+      (中略)

cdk deploy⚡️

diffを実行して変更内容が確認できたらdeployに書き換えてデプロイ実行します。
(所要時間:5分程度)

npx cdk diff -c env=staging rds-secondary-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-secondary-staging-cloned
Stack rds-secondary-staging-cloned
Resources
+[+] AWS::RDS::DBInstance Template/MasterDBInstance MasterDBInstance


✨  Number of stacks with differences: 1

ヘッドレスクラスタだったセカンダリにインスタンスが1個追加されていることが確認できます。
デプロイ後

バージョンアップ💥

それぞれのバージョンを新しいものに変更します。

編集内容
cfn-migration/rds/rds-staging-cloned.yml
Resources:
  DBCluster:
      (中略)
-      EngineVersion: 15.2
+      EngineVersion: 15.8
  MasterDBInstance:
      (中略)
-      EngineVersion: 15.2
+      EngineVersion: 15.8
  ReadReplicaDBInstance:
      (中略)
-      EngineVersion: 15.2
+      EngineVersion: 15.8
cfn-migration/rds/rds-staging-secondary-cloned.yml
Resources:
  DBCluster:
      (中略)
-      EngineVersion: 15.2
+      EngineVersion: 15.8
  MasterDBInstance:
      (中略)
-      EngineVersion: 15.2
+      EngineVersion: 15.8

cdk deploy⚡️

diffを実行して変更内容が確認できたらdeployに書き換えてセカンダリ、プライマリの順にデプロイ実行します。
(所要時間:合計で10分程度)

セカンダリのバージョンアップ

npx cdk diff -c env=staging rds-secondary-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-secondary-staging-cloned
Stack rds-secondary-staging-cloned
Resources
[~] AWS::RDS::DBCluster Template/DBCluster DBCluster
 └─ [~] EngineVersion
-     ├─ [-] 15.2
+     └─ [+] 15.8
[~] AWS::RDS::DBInstance Template/MasterDBInstance MasterDBInstance
 └─ [~] EngineVersion
-     ├─ [-] 15.2
+     └─ [+] 15.8

プライマリのバージョンアップ

npx cdk diff -c env=staging rds-staging-cloned
diff実行結果
$ npx cdk diff -c env=staging rds-staging-cloned
Stack rds-staging-cloned
Resources
[~] AWS::RDS::DBCluster Template/DBCluster DBCluster
 └─ [~] EngineVersion
-     ├─ [-] 15.2
+     └─ [+] 15.8
[~] AWS::RDS::DBInstance Template/MasterDBInstance MasterDBInstance
 └─ [~] EngineVersion
-     ├─ [-] 15.2
+     └─ [+] 15.8
[~] AWS::RDS::DBInstance Template/ReadReplicaDBInstance ReadReplicaDBInstance
 └─ [~] EngineVersion
-     ├─ [-] 15.2
+     └─ [+] 15.8

セカンダリからインスタンス削除

diffを実行して変更内容が確認できたらdeployに書き換えてデプロイ実行します。
(所要時間:15分程度)

編集内容
  • MasterDBInstanceを削除
    • 次回も使うのでコメントアウト
cfn-migration/rds/rds-staging-secondary-cloned.yml
Resources:
-  MasterDBInstance:
-    Type: AWS::RDS::DBInstance
-    Properties:
-      (中略)
-      EngineVersion: 15.8
-      PerformanceInsightsKMSKeyId: "*********"
-      (中略)
+ ## NOTE: マイナーバージョンアップを試す場合は以下のコメントアウトを外す
+ ## MasterDBInstance:
+ ##   Type: AWS::RDS::DBInstance
+ ##   Properties:
+ ##     (中略)
+ ##     EngineVersion: 15.8
+ ##     PerformanceInsightsKMSKeyId: "*********"
+ ##     (中略)

cdk deploy⚡️

diff実行結果
$ npx cdk diff -c env=staging rds-secondary-staging-cloned
-[-] AWS::RDS::DBInstance MasterDBInstance destroy

✨  Number of stacks with differences: 1

後片付け

ステージングサイトのDBエンドポイントを元に戻す

所定の方法でステージングサイトのDBエンドポイントを元に戻します。
変更後は動作確認をしてちゃんと元に戻っていることを確認しておきます。

検証用DBのスタック削除

まずは差分をdiffで確認してから、diffdestroyに書き換えて実行します。
ラピュタの呪文にたとえると「バルス」なので、慎重にコピー&ペーストせず単語を打ち直して実行しました。

cdk destroy☠️

npx cdk diff -c env=staging rds-staging-cloned rds-secondary-staging-cloned

destroyのコマンドを直接書くと怖いのでキャプチャーだけですがこんな感じで削除されます。
destroyでスタックをバルスした時

よくあった自分のハマりポイントまとめ

スタックのデプロイや削除の実行に時間がかかるので作業で使っている一時クレデンシャルの期限切れでデプロイが中途半端になる場合がある。

  • 💡 実行後にdiffで差分がないことまで確認する。

AWSコンソールのCloudFormationで見ると作ったはずのセカンダリのスタックが見つからない

  • 💡 現在のリージョンを確認する。
    • 例

おわりに

たいていの会社は成長するとインフラ周りが専業体制になりがちですが、レンティオではエンジニア全員がインフラを触ったりレビューする機会がありますので、自分だけでなくチーム全体のAWS戦闘力も上がって良いことだと思います。

この記事がお役に立てれば幸いです。

採用情報

レンティオでは、今回のような感じでRailsやりつつインフラとかフロントエンドなど周辺スキルにもチャレンジできる環境に転生したいエンジニアを募集しています!
https://www.wantedly.com/companies/rentio

Discussion