Aurora PostgreSQLメージャーバージョンアップの振り返り

現在担当しているシステムで初めてAurora PostgreSQL 12から16へとメジャーバージョンのアップグレードを担当したので、振り返りとして記事を書いてみます。

## バージョンアップの背景

Aurora PostgreSQL 12が標準サポートを終了する前に対応する必要があったからです。Aurora PostgreSQLの標準サポート終了日については、以下のドキュメントで事前に確認することができます。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/aurorapostgresql-release-calendar.html

また、去年の11,12月ごろにAWS Health経由でも標準サポート終了のアナウンスをもらっています。

> Aurora PostgreSQL 互換エディションの新しいバージョンが利用可能になり、2025 年 2 月 28 日に Amazon Aurora PostgreSQL 12.x の標準サポートが終了することをお知らせします。Aurora バージョンポリシー [1] に従い、データベースクラスターをアップグレードする時間を設けるよう、事前通知を行っています。
> 
> Amazon Aurora PostgreSQL メジャーバージョン 12.x を実行しているデータベースを、2025 年 2 月 28 日までのご都合の良いときに、Amazon Aurora PostgreSQL 13 以降に事前にアップグレードすることをお勧めします。
> 
> サポート期限が終了する前に、最新情報やリマインダーをお送りします。
> A. 今から 2025 年 2 月 28 日まで - Amazon Aurora PostgreSQL 12.x インスタンスの Amazon Aurora PostgreSQL 13 以上へのアップグレードはいつでも開始できます。
>
> B. 2025 年 2 月 28 日以降、お客様が Aurora PostgreSQL 12.x を実行しているデータベースを Amazon Aurora PostgreSQL 13 以上の新しいメジャーバージョンにアップグレードしない場合、
> または Amazon Aurora PostgreSQL 12.9 長期サポート (LTS) を使用していない場合、
> Amazon Aurora はメンテナンスウィンドウにて Amazon Aurora PostgreSQL 12.x データベースを適切な延長サポートマイナーバージョンにアップグレードします。
> 延長サポート料金は 2025 年 3 月 1 日から開始されます。延長サポートでは、12.x データベースを最大 3 年間継続して実行できます。
> 延長サポート料金は、新しいメジャーバージョンにアップグレードするまで継続されます。
> 
> C. 2025 年 2 月 28 日以降に Amazon Aurora PostgreSQL 12.x データベースのスナップショットを復元すると、復元されたデータベースはその時点で Amazon Aurora PostgreSQL 12.x の延長サポートバージョンに自動的にアップグレードされます。
> 2025 年 3 月 1 日以降、お客様には Amazon RDS 延長サポート料金が発生します。

少しまとめると

- 2025年2月28日に Amazon Aurora PostgreSQL 12.x の標準サポートが終了する
- アップグレードを行わない場合、2025年3月1日以降は自動的に延長サポートへ移行し、延長サポート料金が発生する
- 2025年3月1日以降に 12.x のスナップショットを復元すると、自動的に延長サポート対象のバージョン（LTS バージョン(12.9)または最新のマイナーバージョン）へアップグレードされ、延長サポートが適用される

ということになります。

## システムの構成

全体システムはより複雑ですが、今回の作業に関わる部分だけ簡単に説明します。

Amazon Aurora Global Database(PostgreSQL)を用いたクラスター構成を採用しており、東京および大阪リージョンにそれぞれ2つのインスタンスを配置しています。データベースのエンドポイント情報は Amazon Route 53 に登録されており、各サービス(ECS)は Route 53 を通じてエンドポイントを取得し、データベースに接続する設計となっています。

この構成により、リージョン間の高可用性と災害対策(DR)を実現しつつ、Route 53 を活用することで動的な接続先の管理やフェイルオーバー対応も柔軟に行えることができます。


既存のバージョンはPostgreSQL 12.20でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738941/aa7d6ee2-2726-43f9-a0c8-b6269457401a.png)

## バージョンアップの全体流れ

以下の流れでバージョンアップを実施しています。全体的には普段のシステムリリースと変わらない流れです。

1. 事前調査と検討
2. STG環境での検証
3. 本番アップグレード
4. アップグレード後のモニタリング

## 事前調査と検討
### アップグレード方式の検討

Amazon Aurora PostgreSQLをメジャーバージョンする方式としては、大きく４つがあります。

|  | 方式名 | 説明 | 特徴 | 参考URL |
| --- | --- | --- | --- | --- |
| 1 | エクスポート・インポート(Dump) | 事前にバージョンアップのDBを立てておき、エクスポート・インポートにより移行する |作業中DB利用不可<br>作業負荷が大きい |  |
| 2 | インプレース(In-place) | 既存のDBをそのままバージョンアップをする | 手順が一番簡単<br>アップグレード中、DB利用不可 | [Upgrading the Aurora PostgreSQL engine to a new major version](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.PostgreSQL.MajorVersion.html#USER_UpgradeDBInstance.Upgrading.Manual) |
| 3 | Blue/Green(論理レプリケーション利用) | 論理レプリケーション機能を利用して２つDBを同期させることで、バージョンアップを行い、DBを切り替える(Blue/Green)| 切替時間が短い<br>レプリケーションはテーブルのみ対象で、他は手動で移動する必要がある  | [Using logical replication to perform a major version upgrade for Aurora PostgreSQL](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.MajorVersionUpgrade.html) |
| 4 | Blue/Green(AWS機能利用) | Blue/Green Deployments機能を利用し、バージョンアップを行う | 切替時間が短い<br>Global DBでは利用不可 | [Overview of Amazon Aurora Blue/Green Deployments](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/blue-green-deployments-overview.html) |

Global Databaseで実行できない4番の方法を除き、1番～3番の方法を検討しました。結果として、手順が最もシンプルな2番のインプレース方式を採用することにしました。3番の方式はユーザーへの影響（停止時間）を最小限に抑えられる利点がありましたが、一部のリソースを手動で移行する必要があることから見送りました。

なお、インプレース方式でも、作業中にクローンDBを用意することでRead処理は可能となり、ユーザーへの影響を軽減できます。イメージとしては以下のような図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738941/524487fe-b772-416b-a866-067794c466e8.png)

### アップグレード先のバージョンの検討

まずはDBと関連するリソースのシステム要件を確認します。

メジャーバージョンアップでは互換性のない変更が含まれることがあるため、各バージョンの変更点を確認し、それがサービスに影響を及ぼさないかを慎重に検証する必要があります。当システムではサポート期限を考慮し、PostgreSQL16へのアップグレードを決定しました。

PostgreSQL12から16に、4バージョンを跨ぐアップグレードとなりますが、アプリケーション側でデータベースの利用が比較的シンプルであったため、対応は可能と判断しました。互換性についても、アプリケーションのバージョンアップとの時期を調整することで問題が生じないことを確認済みです。

次にマイナーバージョンを決めます。通常はメンテナンスの観点からLTS（Long-term support）バージョンを選択しますが、AuroraのPostgreSQL 16ではLTSが未定のため、当時の最新バージョンである16.4を採用することにしました。

### バージョンアップ時期の検討

制約がない限り、標準サポートが終了する2025年2月28日までにバージョンアップを実施するのが一般的です。ただし、プロジェクトの状況によっては、延長サポート料金を支払う選択肢もありかと思います。

例えば、我々のチームでは2025年5、6月にアプリケーションのバージョンアップを予定していたため、延長サポート料金（本番・STG環境合わせて約18万円）を2、3か月支払い、同時期にアップグレードを実施することで、テスト工数を一回に抑えられると検討しました。

しかし、検証中にアプリケーションの制約が発見され、迂回策も検討しましたが、検証時間や作業リスクを考慮した結果、データベースのみを2月28日までにバージョンアップすることを決定しています。

今回のバージョンアップではこの検討が一番難しい＆時間がかかったところでした。

-----
#### 時期検討のプロセス

※ここではデータベースのみをアップグレードすることに至った過程を詳細に書きますが、我々のプロジェクト特有の制約となり、直接PostgreSQLのアップグレードと関係ない部分も含まれるため、読み飛ばしても問題ありません。

まず、アプリケーション(ある OSS ソフトウェアを利用してます)の要件は以下の通りです。
- アプリケーション側ではデータベース設計を刷新しており、旧設計(OLD_DB)から新設計(NEW_DB)への移行が推奨されている
- 現時点では OLD_DB を利用中
- 5月〜6月にかけてアプリケーションのバージョンアップを計画しており、このタイミングで OLD_DB から NEW_DB への移行を予定
- データ量が多いため、影響がないデータについては事前に NEW_DB へ移行しておきたい

今回特に問題となったのは、PostgreSQL 16から導入された生成列(generated column)の制約です。
> 親列が生成列である場合、その子列も生成列でなければなりません。 親列が生成列でない場合、その子列も生成列であってはなりません。 
https://www.postgresql.jp/document/16/html/ddl-generated-columns.html 

この仕様により、NEW_DBではPostgreSQLのバージョン(PostgreSQL 16未満であるかどうか)に応じてテーブル定義を分けています。

ここで PostgreSQL のアップグレードに話を戻ります。
作業負荷だけを考慮すれば、インプレース(in-place)方式が最も簡単です。 しかし、前述のとおり PostgreSQL 16 における生成列の制約により、NEW_DB のテーブル定義がバージョンに依存する状況となり、バージョンアップ作業と同時期にインプレース方式ではアップグレードが不可能になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738941/be05f915-1212-4e12-9f2e-53dedff68566.png)


アップグレードためには以下のいずれかを選択する必要が出てきました。

1. 時期をずらして、データベースのみを先にアップグレードする
2. インプレース方式をあきらめ、別のアップグレード手法を採用する
3. 事前データ移行をあきらめ、アプリケーションのバージョンアップ時に一括移行する

③事前データ移行をあきらめると、アプリケーションのバージョンアップ作業時の負荷が大きくなるため、これは極力避けたいと考えました。そのため、②インプレース方式以外の手法も検討しましたが、それぞれデメリットが存在しました。

- Dump 方式は停止時間および作業時間が長くなる
- 論理レプリケーション方式は手動対応が必要な項目があり、作業負荷が高い
- 2つの方式とも導入実績がなく、検証に時間がかかる。インプレースより作業が複雑になる

当初、バージョンアップと同時期に DB アップグレードを実施したいと考えた理由は、テストの時間(工数)を削減できるというメリットがあったためです。しかし、アップグレード作業の複雑化によりテスト効率のメリットが失われると判断し、最終的には①インプレース方式によってデータベースのみをアップグレードする方針を採用しました。

-----

### 事前確認が必要な項目について調査

作業前には、アップグレード前に確認することがいい点についてAWS のドキュメントやサポートを通じて確認しました。

今回のバージョンアップでは、サポートからも案内された以下のドキュメントを参考にして進めました。

[メジャーバージョンアップグレードの実行 - Amazon Aurora](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.PostgreSQL.MajorVersion.html#USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Upgrade.preliminary)

ドキュメントを参考にし、Aurora PostgreSQL 12での確認項目をまとめると以下になりました。

- アップグレード前
    - (必要な場合)バージョン互換のパラメータグループを用意する
    - template1 と template0 のデータベースの datistemplate値が、`ｔ`であることを確認する
    - 論理的なレプリケーションスロットを削除する
    - 一部拡張機能は最新バージョン化する
    - (Global DBの場合)`global_db_rpo` パラメータをリセットする
    - 準備されているトランザクションがないことを確認する
    - すべての reg* データ型を削除する
- アップグレード後
    - すべての PostgreSQL DB インスタンスのすべてのデータベースに対して、`ANALYZE` を実施する

### 新しいバージョンのパラメータグループの確認

パラメータグループはメジャーバージョンによって異なるので、メジャーバージョンアップ時は新しくパラメータグループを生成する必要があります。

デフォルトのパラメータグループでも、バージョンによって定義されるパラメータやその値が異なる場合があります。そのため、事前に確認することをおすすめします。また、クラスターパラメータグループとインスタンスパラメータグループの2種類がある点にも注意が必要です。

個別のカスタムパラメータグループを利用している場合、アップグレード時にはデフォルトのパラメータグループが固定で選択されます。そのため、アップグレード後に改めてパラメータグループを変更する必要があります。

### ロールバックについて考える

徹底的に準備してもアップグレードに失敗する可能性はゼロではありません。そのため、失敗時の対応策を事前に考えておくことが重要です。

一般的には、アップグレード前に取得したスナップショットからロールバックする方法が取られます。ただし、スナップショットからインスタンスを作成するには時間がかかるため、迅速な対応が求められる場合には、事前にクローンを作成しておき、問題がないと判断されるまで保持しておくという選択肢も有効です。

## STG環境での検証

調査結果をもとに手順書を作成し、テスト検証を進めます。

今回の検証では、作業手順に問題がないこと、およびアップグレード後にサービスの機能・非機能要件でデグレが発生しないことを確認することを目的としています。

そのため、機能面ではユーザーの利用シーンを想定したシナリオテストを実施し、非機能面では既存の負荷に耐えられるかを確認するため、複数の負荷テストを行いました。

また、本番同様の構成でクローンを作成し、アップグレード手順の確認と作業時間の見積もりも実施しました。ここで、STG環境（1インスタンス×2リージョン）と本番同様構成のクローン（2インスタンス×2リージョン）でのインプレースアップグレード時間がほぼ変わらない結果（約15分程度）であった点が特に印象的でした。

## 本番アップグレード

いよいよ本番をアップグレードします。
STG環境で検証した内容を基に、以下の手順で実施しました。

1. DBの状態を確認
    - インスタンスにアクティブなトランザクションが存在しないことを確認する
    - インスタンスの論理的なレプリケーションスロットを削除する
2. スナップショットを取得
3. インスタンスをアップグレード
    - 実はここでもアップグレード直前のスナップショットが取れますが、念のため２でもスナップショットを取得しています
4. 統計情報を更新 (`ANALYZE`)
5. 基本どうさテスト

作業はテストも含めて約3時間程度でアップグレードを完了することができました。

### 延長サポートの開始はUTC基準

プロジェクトの事情により、アップグレードは2月28日の夜間に日をまたいで実施することになりました。標準サポートの終了日が2月28日であるため、3月1日になる場合の料金が気になっていましたが、UTC基準のため、日本時間では3月1日午前8時59分に標準サポートが終了することになるようです。詳細は以前作成したブログ記事をご参照ください。

[Amazon Auroraの延長サポート料金は何時から発生する？ - Qiita](https://qiita.com/aguoys3/items/7954ab244130b86c52a3)

## アップグレード後のモニタリング

CloudWatchメトリクスをこまめにチェックし、アップグレード完了後に異常がないか確認します。今回のアップグレードでは、3月1日のアップグレード後にFreeLocalStorageが減り続ける現象を発見し、AWSサポートに問い合わせを行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738941/d20eb0c5-d243-4fbb-8ff8-8d7d27e59618.png)

サポートからは、これはアップグレードによる影響であり、ログファイルが特定のサイズに達すると落ち着くとの連絡を受けました。そして実際に、約2週間後にWriter(オレンジ)のほうは安定し始めていることを確認しました。しかし、Reader(みどり)のほうは依然として緩やかでありますが減り続けているため、引き続き継続的なモニタリングを行っています。

## まとめ

今回のAurora PostgreSQLメジャーバージョンアップでは、事前の準備、STG環境での検証、本番アップグレードの各ステップを通じて多くの学びがありました。特に制約の課題を乗り越えてどうすればユーザ影響少なく、運用する我々の負荷が低く作業できるかを考えるのが楽しかったです。

DBのバージョンアップは１回で終わりではなく、サポート終了につれて継続的に実施する必要があります。次回は今回得られた学びをベースに、よりスムーズに実施できるようにしたいと思っています。