はじめに
説明
Cloud Native PostgreSQL(CNP)とはEDB社の提供しているPostgreSQLのKubernates Operatorになります。
Kubernates Operatorを初耳の方も多いと思いますが、一言で申しますとクラスタ管理・構築ツールになります。
今回はオンプレのPostgreSQLから同じオンプレのminikube(kvm2)上のCloud Native PostgreSQLのレプリケーションを行います。
構築所要時間
30分程度を想定しております
前提やトラブルシュート
CNPの構築は初回の記事を参考にして下さい。
レプリケーションがうまく行かない場合、前回の記事でまずオンプレ同士で構築することを推奨します。
CNPのパラメータ制約
CNPのパラメータには一部制限がございます。
このためストリーミングレプリケーションのスタンバイになることは難しそうです。
ロジカルレプリケーションのサブスクリプションには執筆時点では支障がございません。
wal_level
wal_log_hints
synchronous_standby_names
hot_standby
primary_conninfo
restore_command
パブリケーションの設定
パラメータ確認
パブリケーションの設定を確認します。
こちらは普通に作成下さい。
クライアント認証で接続可能か、wal_levelがlogicalかを確認します。
他のパラメーターはデフォルトであれば動作するはずですが必要に応じて確認ください。
$ cat /var/lib/pgsql/*/data/pg_hba.conf
$ psql
psql# show wal_level;
wal_level
-----------
logical
パブリケーション設定
パブリケーションを作成します。
psql# CREATE ROLE replica WITH ENCRYPTED PASSWORD 'password' LOGIN REPLICATION;
psql# create database app;
psql# \c app
psql# create table japan ( id serial primary key, pref text, city text );
psql# CREATE PUBLICATION "logical_pub" FOR TABLE japan;
psql# \dRp
名前 | 所有者 | 全テーブル | Insert文 | Update文 | Delete文
-------------+----------+------------+----------+----------+----------
logical_pub | postgres | f | t | t | t
psql # SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
-------------+------------+-----------
logical_pub | public | japan
第一弾のデータを流し込みます。
psql# INSERT INTO japan
( pref , city )
VALUES
( '東京都', '八王子市' ),
( '東京都', '立川市' ),
( '東京都', '武蔵野市' ),
( '東京都', '三鷹市' ),
( '東京都', '青梅市' ),
( '東京都', '府中市' ),
( '東京都', '昭島市' ),
( '東京都', '調布市' ),
( '東京都', '小金井市' ),
( '東京都', '小平市' ),
( '東京都', '日野市' ),
( '東京都', '東村山市' ),
( '東京都', '国分寺市' ),
( '東京都', '国立市' ),
( '東京都', '福生市' ),
( '東京都', '狛江市' ),
( '東京都', '東大和市' ),
( '東京都', '清瀬市' ),
( '東京都', '東久留米市' ),
( '東京都', '武蔵村山市' ),
( '東京都', '多摩市' ),
( '東京都', '稲城市' ),
( '東京都', '羽村市' ),
( '東京都', 'あきる野市' ),
( '東京都', '西東京都市' );
psql# select * from japan;
\q
$ exit
サブスクリプションの設定
CNPのプライマリを確認します。
pingするとわかりますがPodにpingは通りません。
$ kubectl cnp status クラスタ名
kubectl cnp status cluster-example
Pod name Current LSN Received LSN Replay LSN System ID Primary Replicating Replay paused Pending restart Status
-------- ----------- ------------ ---------- --------- ------- ----------- ------------- --------------- ------
cluster-example-1 0/E000000 6976160584607547411 ✓ ✗ ✗ ✗ OK
cluster-example-2 0/E000000 0/E000000 6976160584607547411 ✗ ✓ ✗ ✗ OK
cluster-example-3 0/E000000 0/E000000 6976160584607547411 ✗ ✓ ✗ ✗ OK
$ kubectl get pod プライマリPod -o wide | tail -n1 | awk {'print $6'} | xargs ping
kubectl get pod cluster-example-1 -o wide | tail -n1 | awk {'print $6'} | xargs ping
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
プライマリpodにログインしてサブスクリプションを設定します。
$ kubectl exec -it プライマリPod -- /bin/bash
kubectl exec -it cluster-example-1 -- /bin/bash
$ psql -U replica -h パブリケーションIP postgres
psql -U replica -h 192.168.1.99 postgres
psql# \q
$ psql
psql# create table japan ( id serial primary key, pref text, city text );
psql# CREATE SUBSCRIPTION "logical_sub2" CONNECTION 'hostaddr=パブリケーションIP port=5432 dbname=app user=replica' publication "logical_pub";
CREATE SUBSCRIPTION "logical_sub2" CONNECTION 'hostaddr=192.168.1.99 port=5432 dbname=app user=replica' publication "logical_pub";
psql# SELECT * FROM pg_subscription;
oid | subdbid | subname | subowner | subenabled | subconninfo | subslotname | subsynccommit | subpublications
-------+---------+--------------+----------+------------+--------------------------------------------------------------+--------------+---------------+-----------------
24594 | 13434 | logical_sub2 | 10 | t | hostaddr=192.168.1.99 port=5432 dbname=postgres user=replica | logical_sub2 | off | {logical_pub}
psql# select * from japan;
筆者もびっくりしたのですがレプリケーションが構築できました。
テーブルの内容が同期されているはずです。
動作確認
通信先の確認
パブリケーションを確認するとnodeではなくKVMホストに対してセッションを張ってます。
$ ss -natp | grep 5432
LISTEN 0 128 192.168.1.99:5432 0.0.0.0:*
ESTAB 0 0 192.168.1.99:5432 192.168.122.15:52946
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
minikube Ready control-plane,master 19h v1.20.7 192.168.39.33 <none> Buildroot 2020.02.12 4.19.182 docker://20.10.6
$ sudo virsh net-dhcp-leases default
Expiry Time MAC アドレス Protocol IP address Hostname Client ID or DUID
-----------------------------------------------------------------------------------------------------------
2021-06-22 13:07:27 52:54:00:ba:8f:a4 ipv4 192.168.122.15/24 minikube 01:52:54:00:ba:8f:a4
INSERT,UPDATE,DELETEの確認
パブリケーションでinsert,update,deleteを行います
$ psql
psql# \c app
psql# INSERT INTO japan
( pref , city )
VALUES
( '神奈川県', '横浜市' ),
( '神奈川県', '川崎市' ),
( '神奈川県', '相模原市' ),
( '神奈川県', '町田市' ),
( '神奈川県', '横須賀市' ),
( '神奈川県', '平塚市' ),
( '神奈川県', '鎌倉市' ),
( '神奈川県', '藤沢市' ),
( '神奈川県', '小田原市' ),
( '神奈川県', '茅ヶ崎市' ),
( '神奈川県', '伊豆市' ),
( '神奈川県', '三浦市' ),
( '神奈川県', '秦野市' ),
( '神奈川県', '厚木市' ),
( '神奈川県', '大和市' ),
( '神奈川県', '伊勢原市' ),
( '神奈川県', '海老名市' ),
( '神奈川県', '座間市' ),
( '神奈川県', '南足柄市' ),
( '神奈川県', '綾瀬市' );
psql# UPDATE japan SET pref = '東京都' where city = '町田市';
psql# DELETE FROM japan WHERE pref = '神奈川県';
レプリケーティングPodでデータを確認します。
insert,update,deleteの結果、東京26市が残るはずです。
$ kubectl exec -it レプリケーティングPod -- /bin/bash
kubectl exec -it cluster-example-2 -- /bin/bash
psql# select * from japan;
あとがき
オンプレからPodにpingを行えない厳しい環境でレプリケーションが構築できましたので
多くの環境でレプリケーション構築が期待できそうです。
なお、マニュアルに記載がございませんので利用になる際はサポート対象か確認をお願いします。
ここまでお読みいただき、ありがとうございました!