RDS for PostgreSQLエンジンのアップグレード戦略
AWSから使ってるPostgreSQLのバージョン12は2月末にサポート切れるよっていうメールが届いてた。
アップグレード方法調べたらブルーグリーンデプロイメントだとダウンタイムが数分以内に終わるとのことで、概要と手順をまとめた。
以下に概要と手順をざっくりメモ。
本番環境向けのALBの設定等も記載した。
概要
ブルーグリーンデプロイメントは、現在動いているDBインスタンスとは別にもう一台DBインスタンスを構築する。
既存のDBをブルー環境、新しく構築したDBをグリーン環境と呼ぶ。
グリーン環境はブルー環境をレプリケーションしており、ブルー環境と同期する。
現在動いているブルー環境に影響を与えずに、グリーン環境のDBに変更を加えることができる。メジャー/マイナーバージョンのアップブレード、ファイルシステム設定のアップグレード、データベースパラメータの変更をグリーン環境で行うことができる。
グリーン環境をテストし、準備ができたらDBの向き先をブルーからグリーン環境に切り替える。
aws Amazon RDS ブルー/グリーンデプロイの概要より
対象バージョン
現在のPostgresqlのバージョンは12.19。
12.19 → 16.3まで上げる。
ベストプラクティス
- グリーン環境での十分なテスト
- レプリケーションの競合が発生する場合があるため、グリーン環境では読み取り専用のまま維持。切り替え後に意図しないデータ書き込みが発生する可能性もある。
- DBのスキーマの変更(例: 列名、テーブル名の変更など)はグリーン環境へのレプリケーションを中断させるので極力避けること。テーブル、カラムの追加はOK。
ブルーグリーンデプロイの準備
awsのドキュメントに沿って以下の設定をブルーグリーンデプロイ作成前にやっておく
- 自動バックアップを有効にする
- 論理レプリケーション(rds.logical_replication)をオンにする
- 必要であれば次の構成設定を調整する
- max_replication_slots
- max_wal_senders
- max_logical_replication_workers
- max_worker_processes
- 以下のPostgresqlの拡張機能を無効にする
- ブルーグリーンデプロイ作成するときに、ブルー環境でpg_partmanを無効にする
- ブルーグリーンデプロイ作成後、pg_cron無効にする
- ブルーグリーンデプロイ作成するときに、ブルー環境でpglogical、pgactiveを無効にする
手順
事前準備①: ALBにリダイレクト処理の設定を追加(本番環境用)
ALBにて、対象画面に対してメンテナンス画面へのリダイレクト処理を入れる。
事前準備②: 常時動いているバッチなどによるDB書き込みがあり、あるテーブルのbooleanフィールドで制御している場合は止める(本番環境用)
以下のSQL文を実行し、あるテーブルのbooleanフィールドで有効になっているデータを取得する。
SELECT *
FROM
specified_table s
WHERE
s.is_valid = True;
さらに、上記で表示されたidをIN句の後に追加していき、DBへの書き込みを止めておく。
これでDBバージョンアップグレード中にレコードの追加を止めておく。
UPDATE specified_table
SET is_valid = False
WHERE id IN (<取得したidのリスト>);
1. rdsの論理レプリケーション(rds.logical_replication)をオンにする
- このパラメータは 1 に設定する。rds.logical_replication パラメータは、スタンドアロンの PostgreSQL サーバーの wal_level パラメータや、ログ先行書き込みファイル管理を制御するその他のパラメータと同じ目的を果たす。
2. 以下のパラメータを必要であれば調整する
- max_replication_slots:
- このパラメータの値を、作成する予定のサブスクリプションの総数に設定する
- デフォルト: 10
- max_wal_senders:
- 同時接続数に加えて、いくつかの追加接続数を設定して、管理タスクや新しいセッションに使用できるようにする
- デフォルト: 10
- max_logical_replication_workers:
- 予想される論理レプリケーションワーカーとテーブル同期ワーカーの数に設定します。通常、レプリケーションワーカーの数は max_wal_senders に使用するのと同じ値に設定すると、安全。ワーカーは、サーバーに割り当てられたバックグラウンドプロセス (max_worker_processes) のプールから取得される
- デフォルト: -
- max_worker_processes:
- サーバーのバックグラウンドプロセス数に設定する。この数は、レプリケーション、自動バキュームプロセス、および同時に行われる可能性があるその他のメンテナンスプロセスにワーカーを割り当てるのに十分な大きさである必要がある
- デフォルト: 8
以下のSQLをtable plusで実行し、確認する。
SELECT name, setting FROM pg_settings WHERE name in
('rds.logical_replication', 'max_replication_slots',
'max_wal_senders', 'max_logical_replication_workers',
'max_worker_processes');
環境別パラメータ設定値 | dev | stg |
---|---|---|
rds.logical_replication | 1 | 1 |
max_replication_slots | 15 | 15 |
max_wal_senders | 15 | 15 |
max_logical_replication_workers | 5 | 5 |
max_worker_processes | 10 | 10 |
各パラメータについては以下を参照。
3. ストレージの確保
以下4つのメトリクスはストレージに関するもの。
RDS for Postgresqlでは論理レプリケーションを使用しWAL(先行書き込みログ)をグリーン環境に反映するまでブルー環境に保存する。
もし、ブルー環境のストレージが逼迫している場合はストレージ割当てを増やす。
それでも不足する場合、各メトリクスに応じてパラメータを確認し、パラメータの値を変更する。
もしくはストレージの自動スケーリングの設定をしておく。
- FreeStorageSpace
- TransactionLogsGeneration
- TransactionLogsDiskUsage
- OldestReplicationSlotLag
ちなみに、ストレージタイプが現在汎用SSD(gp2)を使用してる場合、gp3に変えておくと良い。
スループット、IOPS性能・価格的にgp2より優れている。
参考:
4. ブルーグリーンデプロイの作成
グリーン環境作成の際に、RDS for Postgresqlのバージョン16を指定する。
また、3でストレージ割り当てを増やしている場合は、同じ値を設定する。
作成後、ブルーグリーンデプロイ環境が作成され、以下のような表示になれば成功。
5. ブルーグリーンデプロイのテスト
現在、ブルー環境がメインで動き、グリーン環境はリードレプリカ(読み取り専用)の役割で動いている。例えば、とあるデータ作成画面などでレコードを作成すると、データがまずブルー環境に反映され、その後グリーン環境に同期される。
ブルー環境はtable plusで確認し、グリーン環境は以下のコマンドでDBのレコードが反映されているかを確認する。
// appコンテナに入る
aws ecs execute-command --cluster <cluster-name> --task xxxxxxx --container xxxxxx --interactive --command "/bin/sh"
// appコンテナ内からDBに入る
psql -h <cluster-name>-db-green-xxxx.<password>.ap-northeast-1.rds.amazonaws.com -U <db_user> -d <db>
// 最新のレコードに作成したデータがあるかを確認
SELECT s.name FROM specified_table AS s ORDER BY created_at DESC LIMIT 3;
6. DBをブルー環境からグリーン環境に切り替える(スイッチオーバー)
切り替え前に以下のコマンドを実行する。
pg_current_wal_lsn はデータベースの現在の位置を表す。lsn_distanceが0のとき、レプリカが追いついたことを意味する。
SELECT slot_name,
confirmed_flush_lsn as flushed,
pg_current_wal_lsn(),
(pg_current_wal_lsn() - confirmed_flush_lsn) AS lsn_distance
FROM pg_catalog.pg_replication_slots
WHERE slot_type = 'logical';
切り替えが始まると、ダウンタイムが数分(最大5分くらい)発生し、完了後グリーン環境のDB識別子・エンドポイントはグリーンからブルーだったものに切り替わる。
作成したグリーン環境はブルーになり、もともとのブルー環境はオールドブルーになっているはず。
table pulsなどのクライアントで確認すると16になってることが確認できる。
7. DBの書き込みの再開(本番環境用)
事前準備②でDBへの書き込みを止めている場合、以下のSQL文を実行し、書き込みを再開させる。
UPDATE specified_table
SET is_valid = True
WHERE id IN (<取得したidのリスト>);
補足: スイッチオーバーでエラーが発生した場合
スイッチオーバーの際にタイムアウト時間を超える場合やエラーが発生した場合、自動でロールバックしてくれる。
以下参考。
注意点
- グリーン環境は中身のデータはブルーと同じものを構築するため、停止するまで2台分の費用が請求される。スイッチオーバーが完了したら、作成したブルーグリーンデプロイメントを削除して、オールドブルーはスナップショットを取って削除したほうがいい。
おわりに
PostgreSQLは1年に1回新しいバージョンをリリースしているので、3〜5年に1回はRDSのバージョンアップグレードしないといけなさそう。
だが、1度ブルーグリーンデプロイメントやってみたら、驚くほど簡単でDBのアップグレードに対する心理的なハードルがなくなった。
system manager automationでパラメータの設定やブルーグリーンデプロイメントの作成も自動化できたかなーとか思ったけどどうでしょう。
パラメータ設定むずい。
Discussion