Skip to main content
© 2022 NTT DATA Corporation
CloudNativePGを動かしてみた!
~PostgreSQL on Kubernetes~
2022年 7月 29日 第34回PostgreSQLアンカンファレンス@オンライン
株式会社NTTデータ 技術開発本部
加藤 健
© 2022 NTT DATA Corporation 2
自己紹介
加藤 健
【経歴】
• PostgreSQLの研究開発+サポート
• 社会人2年目
• PostgreSQL歴 1年
• Kubernetes歴 半年
【これまでのPostgreSQLアンカンファレンス】
• 第29回「OSS-DB Gold 合格体験記」
© 2022 NTT DATA Corporation 3
PostgreSQL Operatorとは
PostgreSQL Operatorを使うことで、Kubernetes上にPostgreSQLを簡単に構築できる。
Kubernetes上でPostgreSQLを動かすことにより、様々な運用管理を自動化できる。
Kubernetes
モニタリング
PostgreSQL PostgreSQL
PostgreSQL
バックアップ ログ管理
HA構成 HA構成
© 2022 NTT DATA Corporation 4
PostgreSQL Operator 一覧
Kubernetes上での運用が注目され始めており、様々な企業/コミュニティがPostgreSQL Operatorを提供している。
今回は、最近リリースされたばかりのCloudNativePGについて調査する。
• CloudNativePG (旧称 Cloud Native PostgreSQL)
• Zalando Postgres Operator
• Crunchy Data PostgreSQL Operator
• StackGres
• Stolon
• KubeDB
• Vmware Tanzu SQL with PostgreSQL for Kubernetes
© 2022 NTT DATA Corporation 5
CloudNativePGとは
CloudNativePGは、PostgreSQL専業ベンダーであるEnterpriseDBが開発し、OSSとして公開されている。
EDB PostgreSQL for Kubernetesは、CloudNativePGをベースに一部機能を追加して提供されている。
メイン開発企業 EnterpriseDB
初回リリース 2022年4月
最新バージョン 1.16.0
対応PostgreSQL
メジャーバージョン
PostgreSQL 10+
ライセンス Apache License 2.0
スター数 366
コントリビュータ数 23
商用サポート EDB PostgreSQL for Kubernetes
メイン実装言語 Go
© 2022 NTT DATA Corporation 6
CloudNativePGのアーキテクチャ
CloudNativePGではクライアントからのリクエストをServiceで受け、Podに割り振る。
Operator(図中のcnpg-controller-manager)がPodの配置、状態を管理する。
Client Request
cluster-example-rw
(Service)
Client Request
cluster-example-ro
(Service)
cnpg-controller-manager (Deployment)
cluster-example-1
(Pod)
postgres
(Container)
cluster-example-2
(Pod)
postgres
(Container)
cluster-example-3
(Pod)
postgres
(Container)
カスタムリソースの定義に従って管理
© 2022 NTT DATA Corporation 7
確認項目
現時点で最新バージョンであるCloudNativePG v1.16.0を動かしてみる。
今回の環境として、minikube v1.25.2を使用する。
以下の項目について確認する。
• CloudNativePGデプロイ
• PostgreSQLクラスタ作成
• PostgreSQLインスタンスへの接続確認
• 同期レプリケーション確認
• 自動フェールオーバー
• ローリングアップデート
© 2022 NTT DATA Corporation 8
CloudNativePGデプロイ
CloudNativePGをデプロイする方法は2つ: ①マニフェストを使用する ②Helm Chartを使用する
今回は①の方法でCloudNativePGをデプロイする。
1. 既に用意されているOperatorのマニフェストを使用し、CloudNativePGをデプロイする。
$ kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-
pg/release-1.16/releases/cnpg-1.16.0.yaml
2. CloudNativePGがデプロイされたか確認する。
$ kubectl get deployments –n cnpg-system
NAME READY UP-TO-DATE AVAILABLE AGE
cnpg-controller-manager 1/1 1 1 52s
© 2022 NTT DATA Corporation 9
PostgreSQLクラスタ作成 (1/2)
CloudNativePGの機能を使えば、簡単にHA構成のクラスタを作成できる。
今回はプライマリx1、同期スタンバイx1 非同期スタンバイx1の3台構成とする。
$ vi cluster-example.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example #クラスタ名
spec:
instances: 3 #インスタンス数
imageName: ghcr.io/cloudnative-pg/postgresql:14.3 #イメージの指定
minSyncReplicas: 1 #同期レプリケーションの最小数
maxSyncReplicas: 1 #同期レプリケーションの最大数
primaryUpdateStrategy: unsupervised #アップデート時のプライマリの挙動
storage:
size: 1Gi #ストレージサイズ
1. マニフェストに設定を定義する。
© 2022 NTT DATA Corporation 10
PostgreSQLクラスタ作成 (2/2)
CloudNativePGの機能を使えば、簡単にHA構成のクラスタを作成できる。
今回はプライマリx1、同期スタンバイx1 非同期スタンバイx1の3台構成とする。
$ kubectl apply –f cluster-example.yaml
cluster.postgresql.cnpg.io/cluster-example created
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/cluster-example-1 1/1 Running 0 71s
pod/cluster-example-2 1/1 Running 0 56s
pod/cluster-example-3 1/1 Running 0 47s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cluster-example-any ClusterIP 10.102.86.16 <none> 5432/TCP 75s
service/cluster-example-r ClusterIP 10.109.11.121 <none> 5432/TCP 75s
service/cluster-example-ro ClusterIP 10.111.129.103 <none> 5432/TCP 75s
service/cluster-example-rw ClusterIP 10.100.52.161 <none> 5432/TCP 75s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
2. 定義したマニフェストをもとにPostgreSQLクラスタを作成する。
© 2022 NTT DATA Corporation 11
PostgreSQLインスタンスへの接続確認 (1/3)
インスタンスへ接続する方法は3つ: ①コンテナに直接入る ②ポートフォワードを使用する ③Ingressを使用する
今回は③の方法でインスタンスへ接続する。
$ minikube addons enable ingress
1. MinikubeでIngressを有効化する。
2. ConfigMapを編集し、Ingressの5432ポートからプライマリにリダイレクトするように設定する。
$ kubectl patch configmap tcp-services -n ingress-nginx 
> --patch '{"data":{"5432":"default/cluster-example-rw:5432"}}'
© 2022 NTT DATA Corporation 12
PostgreSQLインスタンスへの接続確認 (2/3)
インスタンスへ接続する方法は3つ: ①コンテナに直接入る ②ポートフォワードを使用する ③Ingressを使用する
今回は③の方法でインスタンスへ接続する。
$ vi patch.yaml
spec:
template:
spec:
containers:
- name: controller
ports:
- containerPort: 5432
hostPort: 5432
name: postgres
protocol: TCP
$ kubectl patch deployment ingress-nginx-controller --patch "$(cat patch.yaml)" -n
ingress-nginx
deployment.apps/ingress-nginx-controller patched
3. 外部からIngressの5432ポートにアクセスできるように編集し、その設定を適用する。
© 2022 NTT DATA Corporation 13
PostgreSQLインスタンスへの接続確認 (3/3)
インスタンスへ接続する方法は3つ: ①コンテナに直接入る ②ポートフォワードを使用する ③Ingressを使用する
今回は③の方法でインスタンスへ接続する。
$ export PGPASSWORD=$(kubectl get secrets cluster-example-app -o go-
template='{{.data.password | base64decode}}’)
$ psql –h $(minikube ip) –p 5432 –U app
psql (14.1, server 14.3 (Debian 14.3-1.pgdg110+1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-ECDSA-AES256-GCM-SHA384, bits: 256,
compression: off)
Type "help" for help.
app=>
4. psqlを使い、プライマリインスタンスへ接続する。
© 2022 NTT DATA Corporation 14
同期レプリケーション確認 (1/2)
CloudNativePGでは、クォーラムコミットの同期レプリケーションがサポートされている。
$ vi cluster-example.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example #クラスタ名
spec:
instances: 3 #インスタンス数
minSyncReplicas: 1 #同期レプリケーションの最低数
maxSyncReplicas: 1 #同期レプリケーションの最大数
storage:
size: 1Gi #ストレージサイズ
1. マニフェストに“minSyncReplicas”と”maxSyncReplicas”を指定し、PostgreSQLクラスタを作成すると、
同期レプリケーションが有効化される。(「PostgreSQLクラスタ作成」で実施済み)
© 2022 NTT DATA Corporation 15
同期レプリケーション確認 (2/2)
CloudNativePGでは、クォーラムコミットの同期レプリケーションがサポートされている。
postgres=# SELECT application_name, state, sync_state FROM pg_stat_replication;
application_name | state | sync_state
-------------------+-----------+------------
cluster-example-2 | streaming | quorum
cluster-example-3 | streaming | quorum
(2 rows)
postgres=# SHOW synchronous_standby_names;
synchronous_standby_names
-------------------------------------------------
ANY 1 ("cluster-example-2","cluster-example-3")
(1 row)
2. synchronous_standby_namesを確認すると、クォーラムコミットの設定になっている。
3. pg_stat_replicationを見てみると、クォーラムコミットで同期レプリケーションされていることが確認できる。
© 2022 NTT DATA Corporation 16
自動フェールオーバー (1/2)
多くのOperatorは、Patroniという外部ツールを使い、自動フェールオーバーを実現している。
CloudNativePGは、Postgres instance managerという独自ツールを使い実現している。
$ kubectl delete pod cluster-example-1
pod "cluster-example-1" deleted
$ kubectl get pods --selector=cnpg.io/cluster=cluster-example -
o=jsonpath='{range .items[*]}{.metadata.name}{"t"}{.metadata.labels.role}{"t"}{.status.p
hase}{"n"}{end}’
cluster-example-1 primary Running
cluster-example-2 replica Running
cluster-example-3 replica Running
1. フェールオーバー前の状態を確認する。
2. 今回はPodの障害を想定し、プライマリのPodを削除する
© 2022 NTT DATA Corporation 17
自動フェールオーバー (2/2)
多くのOperatorは、Patroniという外部ツールを使い、自動フェールオーバーを実現している。
CloudNativePGは、Postgres instance managerという独自ツールを使い実現している。
$ ps aux | grep instance
26 126048 0.1 0.2 747084 45864 ? Ssl 07:06 0:01 /controller/manager
instance run --log-level=info
26 130997 0.2 0.2 747084 41092 ? Ssl 07:21 0:00 /controller/manager
instance run --log-level=info
26 131878 3.2 0.2 747340 41940 ? Ssl 07:23 0:00 /controller/manager instance
run --log-level=info
$ kill -9 126048
$ kubectl get pods --selector=cnpg.io/cluster=cluster-example -
o=jsonpath='{range .items[*]}{.metadata.name}{"t"}{.metadata.labels.role}{"t"}{.status.p
hase}{"n"}{end}'
cluster-example-1 replica Running
cluster-example-2 primary Running
cluster-example-3 replica Running
3. 更新系クエリを投げ続けながら実施したが、ダウンタイム10秒ほどで切り替わった。
補足: コンテナプロセスに障害を起こした場合も、同様に10秒ほどで切り替わった。
© 2022 NTT DATA Corporation 18
ローリングアップデート (1/3)
PostgreSQLのマイナーバージョンアップに際して、ローリングアップデートがサポートされている。
全てのスタンバイが1つずつアップデートされた後、プライマリがアップデートされる。
$ $ vi cluster-example.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:14.4 #イメージを14.3 -> 14.4に変更する
primaryUpdateStrategy: unsupervised #アップデート時のプライマリの挙動
storage:
size: 1Gi
1. PostgreSQLクラスタ作成時に定義したマニフェストの、イメージ名を変更する。
“primaryUpdateStrategy”を”unsupervised”にすると、スイッチオーバーが自動化される。
(“supervised”にすると、手動でスイッチオーバーを実施しなければならない。)
© 2022 NTT DATA Corporation 19
ローリングアップデート (2/3)
PostgreSQLのマイナーバージョンアップに際して、ローリングアップデートがサポートされている。
全てのスタンバイが1つずつアップデートされた後、プライマリがアップデートされる。
2. 変更前の状態を確認する。
3. 編集したマニフェストを適用する。
$ kubectl get pods --selector=cnpg.io/cluster=cluster-example -
o=jsonpath='{range .items[*]}{.metadata.name}{"t"}{.metadata.labels.role}{"t"}{.status.p
hase}{"t"}{.spec.containers[].image}{"n"}{end}’
cluster-example-1 primary Running ghcr.io/cloudnative-pg/postgresql:14.3
cluster-example-2 replica Running ghcr.io/cloudnative-pg/postgresql:14.3
cluster-example-3 replica Running ghcr.io/cloudnative-pg/postgresql:14.3
$ kubectl apply -f cluster-example.yaml
cluster.postgresql.cnpg.io/cluster-example configured
© 2022 NTT DATA Corporation 20
ローリングアップデート (3/3)
PostgreSQLのマイナーバージョンアップに際して、ローリングアップデートがサポートされている。
全てのスタンバイが1つずつアップデートされた後、プライマリがアップデートされる。
4. 新しいイメージに変更され、スイッチオーバーが発生したことが確認できる。
$ kubectl get pods --selector=cnpg.io/cluster=cluster-example -
o=jsonpath='{range .items[*]}{.metadata.name}{"t"}{.metadata.labels.role}{"t"}{.status.p
hase}{"t"}{.spec.containers[].image}{"n"}{end}’
cluster-example-1 replica Running ghcr.io/cloudnative-pg/postgresql:14.4
cluster-example-2 primary Running ghcr.io/cloudnative-pg/postgresql:14.4
cluster-example-3 replica Running ghcr.io/cloudnative-pg/postgresql:14.4
補足: 存在しないイメージ(14.5)を指定しアップデートに失敗すると、元のイメージ(14.4)を指定し直しても復旧できなくなる。
$ $ kubectl get pods --selector=cnpg.io/cluster=cluster-example -
o=jsonpath='{range .items[*]}{.metadata.name}{"t"}{.metadata.labels.role}{"t"}{.status.p
hase}{"t"}{.spec.containers[].image}{"n"}{end}'
cluster-example-1 replica Running ghcr.io/cloudnative-pg/postgresql:14.4
cluster-example-2 primary Running ghcr.io/cloudnative-pg/postgresql:14.4
cluster-example-3 Pending ghcr.io/cloudnative-pg/postgresql:14.5
© 2022 NTT DATA Corporation 21
まとめ
最近リリースされたばかりのCloudNativePG v1.16.0を動かしてみての感想。
• ドキュメントがしっかりしていて、初めてでもとっつきやすかった。
• 最低限の機能だけでなく、ローリングアップデートなどの仕組みが備わっていてとても高機能な印象を受けた。
• クォーラムコミットの同期レプリケーションなど、他のOperatorにない機能がある。
• 異常時の挙動についてはまだ検討の余地がありそう。
• フェールオーバーの仕組みにPatroniを使っていないので、もう少し詳細にフェールオーバーの仕組み・実装を見てみたい。
© 2022 NTT DATA Corporation
その他、記載されている会社名、商品名、又はサービス名は、
各社の登録商標又は商標です。