はじめに
説明
Cloud Native PostgreSQL(CNP)とはEDB社の提供しているPostgreSQLのKubernates Operatorになります。Kubernates Operatorを初耳の方も多いと思いますが、一言で申しますとクラスタ管理・構築ツールになります。
今回はオンプレのPostgreSQLから同じオンプレのminikube(kvm2)上のCloud Native PostgreSQLのレプリケーションを行います。
構築所要時間
30分程度を想定しております。
前提やトラブルシュート
CNPの構築は「Cloud Native PostgreSQLを構築してログインにチャレンジ」のブログを参考にして下さい。レプリケーションがうまく行かない場合、「PostgeSQLのロジカルレプリケーションについて」のブログでまずオンプレ同士で構築することを推奨します。
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を行えない厳しい環境でレプリケーションが構築できましたので、多くの環境でレプリケーション構築が期待できそうです。なお、マニュアルに記載がございませんので利用になる際はサポート対象か確認をお願いします。
次回の内容はまだ未定です。
ここまでお読みいただき、ありがとうございました!