はじめに
以前 Aurora for PostgreSQLのフルマネージドの Blue/Green デプロイを利用して 13.2 ⇒ 15.4 バージョンアップを行う形を試してみました。(Blue/Greenデプロイの説明はそちらに記載がありますので、基本的なことを確認したければ、以下を参照ください)
今回は Blue/Green を利用して 稼働中のデータベースに対してメンテナンス(テーブル追加・カラム追加)を行ってみます。
具体的には、Blue/Greenデプロイを作成したAurora for postgreSQL環境に対して、Green環境にメンテナンス(テーブル追加・カラム追加)を行った後にその環境へ切り替えを行う事で、実行環境(Blue環境)への負荷やサービス中断を発生させることなくメンテを行う事ができる、というものになります。
という事でやってみます。
Aurora for PostgreSQL Blue/Green 環境の作成(再掲)
rds.logical_replicationを設定しておく必要がある事を忘れずに。
「アクション」から「ブルー/グリーンデプロイの作成 -新規」を選択してBlue/Greenデプロイを作成します
今回は前述のとおり、グリーン側のエンジンバージョンはブルー側と同じ 13.12 を選択します。
バージョンが同じだとグリーン環境のバージョンアップが行われないため、高速にグリーン環境を作成することができます。(違うバージョンでももちろんメンテナンスは可能です)
グリーン環境のメンテナンス
Blue/Greenの状態確認
作成されたグリーン環境の状態は以下のようになります。
ブルー環境と同様にtesttblというテーブルが一つあり、idとdateという二つのカラムが確認できます。
bgtest=> \dt
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | testtbl | table | postgres
(1 row)
bgtest=> \d testtbl
Table "public.testtbl"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
id | integer | | not null |
date | timestamp without time zone | | |
Indexes:
"test_pk" PRIMARY KEY, btree (id)
ブルー環境のtesttblテーブルにデータを挿入すると、グリーン環境にもデータがレプリケートされます。
bgtest=> select * from testtbl order by id;
id | date
----+----------------------------
1 | 2024-03-14 01:37:36.894382
2 | 2024-03-14 01:37:53.47027
3 | 2024-03-14 01:37:54.501774
4 | 2024-03-14 01:37:55.530055
5 | 2024-03-14 01:37:56.560074
6 | 2024-03-14 01:37:57.601018
(6 rows)
両方とも同じデータであることが確認できます。
bgtest=> select * from testtbl order by id;
id | date
----+----------------------------
1 | 2024-03-14 01:37:36.894382
2 | 2024-03-14 01:37:53.47027
3 | 2024-03-14 01:37:54.501774
4 | 2024-03-14 01:37:55.530055
5 | 2024-03-14 01:37:56.560074
6 | 2024-03-14 01:37:57.601018
(6 rows)
グリーン環境へのメンテナンス実施(失敗)
グリーン環境に接続し、先ほどのtesttblへカラム追加を行ってみますが、エラーが出て失敗してしまいます。
$ psql -h bgdb01-cluster-green-w1l5mu.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -p 5432 -U postgres -d bgtest
psql (13.7, server 13.12)
SSL connection (protocol: TLSv1.2, cipher: AES128-SHA256, bits: 128, compression: off)
Type "help" for help.
bgtest=> alter table testtbl add column testcol varchar(20);
ERROR: cannot execute ALTER TABLE in a read-only transaction
マニュアルを確認すると、「ブルー/グリーンデプロイを作成すると、グリーン環境の DB クラスターはデフォルトで書き込み操作を許可します」 となっています。
おかしいな、と思って 英語版のマニュアル も確認すると以下のような記載となっており、グリーン環境がデフォルトで書き込み可能なのはMySQLのみになるようです。
グリーン環境ではdefault_transaction_read_onlyパラメータがデフォルトでON(1)になっていました。
bgtest=> select name, setting , unit from pg_settings where name ='default_transaction_read_only';
name | setting | unit
-------------------------------+---------+------
default_transaction_read_only | on |
(1 row)
グリーン環境へのメンテナンス実施(成功)
グリーン環境のRead Onlyを、新しくパラメータグループをセットすることで解除します。
パラメータグループをセットする必要があるため、グリーン環境を一度再起動する必要があります。
(もしくは、最初から default_transaction_read_only を 0 としてパラメータグループを設定しておく)
bgtest=> select name, setting , unit from pg_settings where name ='default_transaction_read_only';
name | setting | unit
-------------------------------+---------+------
default_transaction_read_only | off |
(1 row)
無事グリーン環境のRead Onlyが解除されたため、testtblへカラム追加を行います。
bgtest=> alter table testtbl add column testcol varchar(20);
ALTER TABLE
bgtest=> \d testtbl
Table "public.testtbl"
Column | Type | Collation | Nullable | Default
---------+-----------------------------+-----------+----------+---------
id | integer | | not null |
date | timestamp without time zone | | |
testcol | character varying(20) | | |
Indexes:
"test_pk" PRIMARY KEY, btree (id)
bgtest=> select * from testtbl order by id;
id | date | testcol
-----+----------------------------+---------
1 | 2024-03-14 01:37:36.894382 |
2 | 2024-03-14 01:37:53.47027 |
3 | 2024-03-14 01:37:54.501774 |
4 | 2024-03-14 01:37:55.530055 |
5 | 2024-03-14 01:37:56.560074 |
6 | 2024-03-14 01:37:57.601018 |
(6 rows)
Blue/Greenの切替
無事グリーン環境のメンテナンス(カラム追加)が完了したため、Blue/Greenの切替を実施します。
グリーン側のパラメータグループはRW用のパラメータグループになっています。(インスタンスではなくクラスタパラメータグループで設定した方が本当は良いですね)
切替が完了すると以下のように表示されます。
前回の検証時に比べるとどのインスタンスが現在のプロダクションかが視認しやすくなってますね。
新しいブルー環境のtesttblテーブルを確認すると、カラムが追加された状態になっていることがわかります。
$ psql -h bgdb01.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -p 5432 -U postgres -d bgtest
psql (13.7, server 13.12)
SSL connection (protocol: TLSv1.2, cipher: AES128-SHA256, bits: 128, compression: off)
Type "help" for help.
bgtest=> select * from testtbl where id=(select max(id) from testtbl);
id | date | testcol
-----+----------------------------+---------
286 | 2024-03-14 02:27:26.548948 |
(1 row)
まとめ
Aurora for PostgreSQLのフルマネージドなBlue/Greenデプロイを利用したメンテナンスを実行してみました。
メンテナンス自体はもちろんBlue/Greenデプロイを利用せずとも実施できますが、例えば今回実施したカラム追加はロックを確保するため、大規模なテーブルに対してカラム追加を実施する場合に長時間利用できなくなる、という場合もあります。
そのような場合に、グリーン環境というステージング環境を利用することで長時間の停止等を行うことなくカラム追加等のメンテナンスを行うことができる、というのは一つの選択肢として検討できると考えてます。
手動で実装するには大仰ですが、フルマネージドでしたら実装も検討しやすいと思いますので、大規模メンテナンスの場合にもこのフルマネージドのBlue/Greenデプロイを検討してみましょう!
おまけ
マニュアルでは「default_transaction_read_only パラメータ (Aurora PostgreSQL の場合) を 1 に設定」してRead Onlyにしてください、とあるので、逆に default_transaction_read_only を 0 に設定して Read Onlyを解除しようとしたのですが、最初はDB上から設定しようとして暫く悩みました。
bgtest=> alter database bgtest set default_transaction_read_only = off;
ERROR: cannot execute ALTER DATABASE in a read-only transaction
bgtest=> alter system set default_transaction_read_only to off;
ERROR: must be superuser to execute ALTER SYSTEM command
おまけ2(default値があるカラム追加)
カラム追加時にdefault値をつけると、Green環境のテーブルに値を入れることができます。
今回は testcol 列に test という文字列を default として設定してみました。
bgtest=> alter table testtbl add column testcol varchar(10) default 'test';
ALTER TABLE
bgtest=> select * from testtbl;
id | date | testcol
----+----------------------------+---------
1 | 2024-03-19 06:56:34.716652 | test
2 | 2024-03-19 07:16:01.68611 | test
3 | 2024-03-19 07:16:02.717927 | test
4 | 2024-03-19 07:16:03.755583 | test
5 | 2024-03-19 07:16:04.789024 | test
6 | 2024-03-19 07:16:05.827665 | test
(6 rows)
bgtest=> \d testtbl
Table "public.testtbl"
Column | Type | Collation | Nullable | Default
---------+-----------------------------+-----------+----------+---------------------------
id | integer | | not null |
date | timestamp without time zone | | |
testcol | character varying(10) | | | 'test'::character varying
Indexes:
"test_pk" PRIMARY KEY, btree (id)
ブルー環境にデータを入れつつ切り替えると、以下のような状態になります。
切り替わるタイミングで id 223 の行にtestcol列が追加されていることが確認できます。
INSERT 0 1
WARNING: there is no transaction in progress
COMMIT
id | date
-----+----------------------------
223 | 2024-03-19 07:40:54.550932
(1 row)
Tue Mar 19 07:40:54 UTC 2024
ERROR: cannot execute INSERT in a read-only transaction
WARNING: there is no transaction in progress
COMMIT
id | date | testcol
-----+----------------------------+---------
223 | 2024-03-19 07:40:54.550932 | test
(1 row)
Tue Mar 19 07:41:18 UTC 2024
INSERT 0 1
WARNING: there is no transaction in progress
COMMIT
id | date | testcol
-----+----------------------------+---------
224 | 2024-03-19 07:41:41.879575 | test
(1 row)
Tue Mar 19 07:41:41 UTC 2024
おまけ3(グリーン環境へのテーブル作成)
グリーン環境に testtbl2 テーブルを作成します。
bgtest=> create table testtbl2 ( id integer, date date) ;
CREATE TABLE
bgtest=> \dt
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | testtbl | table | postgres
public | testtbl2 | table | postgres
(2 rows)
bgtest=> \d testtbl2
Table "public.testtbl2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | |
date | date | | |
特にひねってないのでそのままですが、切替後、新しいBlue環境でも同じようにtesttbl2テーブルが残っていることが確認できます。
bgtest=> \dt
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | testtbl | table | postgres
public | testtbl2 | table | postgres
(2 rows)
bgtest=> \d testtbl2
Table "public.testtbl2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | |
date | date | | |