KEMBAR78
つくって壊して直して学ぶ Database on Kubernetes (CloudNative Days Summer 2025 発表資料) | PDF
© 2025 NTT DATA Japan Corporation
つくって壊して直して学ぶ
Database on Kubernetes
2025/5/23
株式会社NTTデータ
小林 隆浩、加藤 慎也
れ
© 2025 NTT DATA Japan Corporation 2
今日話すこと
⚫ Database(PostgreSQL) on Kubernetesを構築する際に気にするべきポイントや、
実際の運用で発生するかも知れない障害とその対応を紹介する。
• 「壊して」というより「壊れて学ぶ」のやり方
⚫ Operatorはここ数年で進化したが、やはりDBには固有の運用があり、理解が難しい。
• 例えば、バックアップやリストア
• 急なDBクラスターの停止、など
⚫ Kubernetesのストレージ周りの機能を使いながら、Database on Kubernetesを運用する際に
そうした機能をどう活かすかについても、一緒に学んでいこう。
© 2025 NTT DATA Japan Corporation 3
アジェンダ
1. はじまり - DB on Kubernetesは突然に -
2. つくって学ぶDatabase on Kubernetes
3. 壊して直して学ぶDatabase on Kubernetes
4. 問い合わせ#1 「晴れ時々エラー!?」
5. 問い合わせ#2 「生き返らないクラスター!?」
6. 問い合わせ#3 「消えないで!テーブル!?」
7. まとめ
© 2025 NTT DATA Japan Corporation 4
© 2025 NTT DATA Japan Corporation
1.
はじまり
© 2025 NTT DATA Japan Corporation 5
Database on Kubernetesは突然に
⚫ カトウ君に上司の藤井さんから依頼が届いているようです!
(今回の登場人物)
藤井さん
カトウ君 こばさん
ポスグレチーム
アプリケーションチーム
依頼
問い合わせ
© 2025 NTT DATA Japan Corporation 6
データベース要件の確認
制定日:2024/8/1
0 DB種別 ■ PostgreSQL □ MySQL □ Oracle(ライセンスは持ち込みのみ) ※必須
1 インスタンス数 □ 1 (冗長性なし。開発環境での利用を想定) ※必須
□ 2 (冗長性あり。非同期を前提とするため、ラグ・データ損失を許容)
■ 3 (冗長性あり。同期を前提とするため、データ損失はゼロ)
2 バックアップ □ コールドバックアップ ※必須
□ オンラインバックアップ
■ オンラインバックアップ+アーカイブログ (PITRに対応可能)
3 保持期間 30 日間 ※必須
4 申請日 西暦 2025 年 4 月 1 日 ※必須
5 申請承認者 ※必須
金融第一事業部 部長 xxxxx
6 記入者 事業部等・担当名 金融第一事業部 ※必須
氏名 yyyyy ※必須
7 連絡先 事業部等・担当名
■ 記入者と同じ場合はこちらをチェック
2024.8版
DBクラスター 作成申請書
担当・グループ名 役職 氏名 担当・グループ名
© 2025 NTT DATA Japan Corporation 7
想定するPostgreSQLの構成
⚫ 3インスタンスで同期レプリケーションを構成し、バックアップとアーカイブを取得する。
プライマリ スタンバイ① スタンバイ②
Data WAL
アーカ
イブ
WAL Data WAL Data
更新 参照
WALをスタンバイに転送
①、②のうち1台に、同
期レプリケーションが完了
すればOK
定期的にWALをアーカイブ
バック
アップ
© 2025 NTT DATA Japan Corporation 8
(参考)RDSのMulti-AZ DB Cluster
⚫ 3インスタンスの構成。
⚫ それぞれのインスタンスが、別AZ
に配置される。
⚫ Write以外のインスタンスでも、
読み取りクエリの処理が可能。
但し、更新ラグが発生する。
⚫ エンドポイントは下記の3種類。
• Read/Write
• Readのみ
• 個別インスタンス
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html#multi-az-db-clusters-concepts-overview
© 2025 NTT DATA Japan Corporation 9
© 2025 NTT DATA Japan Corporation
2.
つくって学ぶ
Database on Kubernetes
© 2025 NTT DATA Japan Corporation 10
KubernetesにおけるPostgreSQL Operatorとは
⚫ Kubernetes上でのデータベース運用を補助する機能が実装されている。
• レプリケーションを使った高可用性構成、障害時切り替え等をYAMLで簡単に設定できる。
• バックアップ/リストアも設定可能で、クラウドストレージと連携できる。
PostgreSQL Operator
プライマリ スタンバイ スタンバイ
プライマリ向けService
© 2025 NTT DATA Japan Corporation 11
PostgreSQL Operatorの比較
⚫ PostgreSQL向けにも複数のOperatorが存在。今回はCloudNativePGを利用する。
名称 開発主体 ライセンス 備考
PGO Crunchy Data Apache 2.0 *
• 古参Operatorの1つ。機能は十分揃っている。
• 従来のPostgreSQL向けOSSを組み合わせた構成。
• コンテナイメージの商用利用が実質できない。
postgres-operator Zalando MIT
• 古参Operatorの1つ。機能は十分揃っている。
• 従来のPostgreSQL向けOSSを組み合わせた構成。
• Kubernetesに詳しいエンジニアが利用しやすい。
CloudNativePG EDB Apache 2.0
• PostgreSQL開発で有名なEDBによるOperator。
• EDBが提供されているマネージドサービス内部でも利用されている。
• 2025年、CNCF Sandbox Projectに。
StackGres OnGres AGPL 3
• 充実した管理UIを提供。
• ライセンスがネックとなる可能性あり。
Percona Operator
for PostgreSQL
Percona Apache 2.0
• MySQLやPostgreSQLの開発で有名なPerconaのOperator。
• PGOをフォークして開発。完全OSSでの利用が可能。
• 比較的新しいOperator。
© 2025 NTT DATA Japan Corporation 12
PostgreSQL on Kubernetesのシステム構成
⚫ GKE上でCloudNativePGを用いて、以下の構成のPostgreSQL on Kubernetesを構築する。
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
WALをGCSにアーカイブ
© 2025 NTT DATA Japan Corporation 13
(例)PostgreSQLクラスター用のYAML
⚫ 3インスタンス
⚫ 同期レプリケーションの設定
⚫ データストレージ
⚫ WAL用のストレージ
⚫ バックアップ設定
© 2025 NTT DATA Japan Corporation 14
© 2025 NTT DATA Japan Corporation
3.
壊して直して学ぶ
Database on Kubernetes
© 2025 NTT DATA Japan Corporation 15
①壊して直して学ぶ:Podの障害
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
Primary Podの障害
© 2025 NTT DATA Japan Corporation 16
①Primary Podの疑似障害
⚫ クラスタの状態を確認
⚫ Primary Podを削除
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-1 0/6055A58 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-2 0/6055A58 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn
test-db-3 0/6055A58 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
$ kubectl delete pod test-db-1
pod "test-db-1" deleted
© 2025 NTT DATA Japan Corporation 17
①Primary Pod障害の確認と復旧
⚫ CloudNativePGのログ
⚫ クラスタの状態を確認
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-2 0/70066E0 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn
test-db-1 0/70066E0 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-3 0/70066E0 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
{"level":"info","ts":"2025-05-19T00:54:27.598548554Z","msg":"Current primary isn't healthy, initiating a
failover","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluste
r":{"name":"test-db","namespace":"default"},"namespace":"default","name":"test-
db","reconcileID":"a90e0a46-6bf1-4f36-9dca-b83f6bb5567e"}
{"level":"info","ts":"2025-05-19T00:54:27.740028855Z","msg":"Failing over",
"controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name"
:"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"a90e0a46-6bf1-
4f36-9dca-b83f6bb5567e","newPrimary":"test-db-2"}
© 2025 NTT DATA Japan Corporation 18
②壊して直して学ぶ:Podの障害
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
Standby Podの障害
© 2025 NTT DATA Japan Corporation 19
②Standby Podの疑似障害
⚫ クラスタの状態を確認
⚫ Standby Podを削除
$ kubectl delete pod test-db-1
pod "test-db-1" deleted
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn
test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
© 2025 NTT DATA Japan Corporation 20
②Standby Pod障害の確認と復旧
⚫ CloudNativePGのログ
⚫ クラスタの状態を確認
{“level”:“info”,"ts":"2025-05-19T01:06:20.510661896Z","msg":"Creating new Pod to reattach a PVC",
"controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name"
:"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"9812324d-b86d-
4d21-a43d-39fb6ac7f77b","pod":"test-db-1","pvc":"test-db-1"}
{"level":"info","ts":"2025-05-19T01:06:31.80588422Z","msg":"Setting replica label",
"controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name"
:"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"eb962e67-b7a2-
4ba0-9bce-29b5c4de5049","pod":"test-db-1"}
{"level":"info","ts":"2025-05-19T01:06:37.768017501Z","msg":"Cluster has become healthy",
"controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name"
:"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"c47b81a5-dc5b-
4c9c-9673-edfbd7dfac6e"}
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn
test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
© 2025 NTT DATA Japan Corporation 21
⚫ CloudNativePGはデフォルトでノード障害に耐えられる設定となっている。
ゾーン
障害に備えたPodの配置戦略(podAntiAffinity)
ノード
P
S
S
ゾーン
ノード
P
ゾーン
S
S
ノード
P
S
S
ノード障害で全滅 ノード障害に耐性 ゾーン障害に耐性
enablePodAntiAffinity:true
topologyKey:kubernetes.io/hostname
enablePodAntiAffinity:false enablePodAntiAffinity:true
topologyKey:topology.kubernetes.io/zone
© 2025 NTT DATA Japan Corporation 22
⚫ 特定のラベルをもつノードにスケジューリングする。
⚫ データベースは特定HWが設定されたノードにスケジューリングしたい場合などに有用。
• DB高速化のためにメモリ増強、高速SSDを搭載など
• 今後はGPU搭載なども要件として登場するかもしれない
性能も考慮したPodの配置戦略(nodeSelector)
nttdata.com/role: db nttdata.com/role: app
© 2025 NTT DATA Japan Corporation 23
CloudNativePGでの設定方法
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pgcluster-prod
spec:
affinity:
enablePodAntiAffinity: true
topologyKey: kubernetes.io/hostname
podAntiAffinityType: required
nodeSelector:
nttdata.com/role: db
⚫ podAntiAffinityを有効化
⚫ ホスト名で分散
⚫ 条件を満たすことが必須
⚫ データベース用ノードに
⚫ GKEノードプールに
ラベルを設定済み
© 2025 NTT DATA Japan Corporation 24
③壊して直して学ぶ:Nodeの障害
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
Primary Podが存在するノードの障害
© 2025 NTT DATA Japan Corporation 25
③Nodeの疑似障害
⚫ クラスタの状態を確認
⚫ Primary Podのあるノードを削除
$ kubectl delete node gke-cluster-bb3caaa1-2swn
node "gke-cluster-kato-default-pool-bb3caaa1-2swn" deleted
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn
test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
© 2025 NTT DATA Japan Corporation 26
③Node障害の確認と復旧
⚫ CloudNativePGのログ
⚫ クラスタの状態を確認
{"level":"info","ts":"2025-05-19T01:33:40.453415481Z","msg":"Current primary isn't healthy, initiating a
failover","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluste
r":{"name":"test-db","namespace":"default"},"namespace":"default","name":"test-
db","reconcileID":"3e4c576c-1e4a-4b0d-9bd0-3fd129e86716"}
{"level":"info","ts":"2025-05-19T01:33:40.718655379Z","msg":"Failing over",
"controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name"
:"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"3e4c576c-1e4a-
4b0d-9bd0-3fd129e86716","newPrimary":"test-db-1"}
$ kubectl cnpg status test-db
Instances status
Name Current LSN Replication role Status QoS Manager Version Node
---- ----------- ---------------- ------ --- --------------- ----
test-db-1 0/B000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv
test-db-2 0/B000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-td3t
test-db-3 0/B000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
z
© 2025 NTT DATA Japan Corporation 27
ここまでのまとめ
⚫ PostgreSQL Operatorは複数あるので、要件に合わせて選択しましょう。
• 机上での比較だとあまり差異がわからないので、実際に使ってみることも重要
⚫ すべての障害への対策は不可能だが、何が許容できる・できないかを整理することが重要。
• Pod障害/ノード障害/ゾーン障害/リージョン障害
• RPO/RTO
⚫ パフォーマンスの観点からデータベースPodはアプリケーションPodとは
別のノードにスケジューリングすることも考える。
• 大容量メモリ・高いIO性能/低遅延・広帯域の安定したネットワークが必要
• 他Podとのリソース競合を避ける
© 2025 NTT DATA Japan Corporation 28
© 2025 NTT DATA Japan Corporation
4.
#1 晴れ時々エラー
© 2025 NTT DATA Japan Corporation 29
#1 エラーになったり、ならなかったり?
(更新時にエラーが発生している画面)
(同じ画面、同じレコードでも成功することもある)
(エラー時のサーバ側ログ)
© 2025 NTT DATA Japan Corporation 30
#1 アプリケーションと動作確認時の接続経路
⚫ PoC的な位置づけで、本番時の接続と異なる経路でテストを行っていた。
APL
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
動作確認
?
© 2025 NTT DATA Japan Corporation 31
#1 Serviceの比較
(CloudNativePGが生成したService) (外部からの接続用に作成したService)
© 2025 NTT DATA Japan Corporation 32
#1 Podのラベルを確認する
⚫ プライマリを指すためのSelectorは cnpg.io/instanceRole=primary
⚫ cnpg.io/podRole=instance は全てのインスタンスを指す。
⚫ cnpg.io/podRole=instance も「読取可能な何処かに繋がる」エンドポイントで使われている。
(プライマリPodのラベル) (スタンバイPodのラベル)
© 2025 NTT DATA Japan Corporation 33
#1 まとめ
⚫ データベースのクラスターにおいて、各インスタンスの役割理解は重要。
⚫ Database on Kubernetesでは、それらの役割はLabelで表現され、Operatorが管理する。
• カスタムエンドポイントを追加する場合には、Operatorの仕様を理解しないと、
今回のようにトラブルが発生する可能性あり。
⚫ Read/Write、Read、ReadOnlyなどのエンドポイントは、殆どのOperatorで生成されるため、
アプリケーションはどのクエリを何処に投げるかをきちんと考えて設計する。
• 全てRead/Writeというのも良くない。
• Readを分散するために、ReadOnlyエンドポイントの活用は重要。
© 2025 NTT DATA Japan Corporation 34
© 2025 NTT DATA Japan Corporation
5.
#2 生き返らないクラスター
© 2025 NTT DATA Japan Corporation 35
#2 PostgreSQLクラスターの状態を確認
⚫ エラーの原因!?
⚫ プライマリが落ちて、
スタンバイも昇格していない
© 2025 NTT DATA Japan Corporation 36
#2 CloudNativePGでWAL領域があふれると、
⚫ 基本的に同じディスク構成となるため、フェイルオーバしてもそちらもあふれる。
⚫ そのため、CloudNativePGではWALあふれでフェイルオーバしない仕様となっている。
プライマリ スタンバイ① スタンバイ②
Data WAL WAL Data WAL Data
この仕様がない場合、プライマリからスタンバイへフェイルオーバして、切り替わり先で障害が発生する。
それが再度フェイルオーバを引き起こし、クラスター内でぱたぱた切り替わるような状態となる。
DBではもっとも避けるべき状況の1つ。
© 2025 NTT DATA Japan Corporation 37
#2 PVC/PVのResizeとは
⚫ Volume拡張では、PVに対応するストレージの拡張だけではなく、コンテナ内のファイル
システムで利用できるサイズも拡張される。
Snapshot
Snapshot
Snapshot
RW
R
RO
P
S
S
© 2025 NTT DATA Japan Corporation 38
#2 PVCの拡張作業
$ kubectl patch pvc production-db-2-wal -p "{¥"spec¥":{¥"resources¥":{¥"requests¥":{¥"storage¥": ¥"5Gi¥"}}}}"
• PVCの確認。WAL用PVCは全て2Gi。
• kubectl patchでPVCを拡張PVCの確認。
• PVC、PVともに拡張されていることを確認。
© 2025 NTT DATA Japan Corporation 39
#2 まとめ
⚫ データベースで高可用性構成を組んでも、フェイルオーバされないケースは存在する。
• (今回のような)ディスクあふれのケース
• 全インスタンスに関わる致命的なパラメータの誤り
⚫ そうした際、Kubernetesリソースを変更する正しい手順を理解しておくことは重要。
• ボリューム拡張では、PVのサイズを直接編集してはいけない。
• ファイルシステムの拡張等、一連の処理が動かない可能性あり
• PVCのサイズを拡張し、以降はKubernetesおよびCSIドライバーが担当。
⚫ こんなことにならないように、そもそもディスク使用量の監視をしましょう。
© 2025 NTT DATA Japan Corporation 41
© 2025 NTT DATA Japan Corporation
6.
#3 消えないで!テーブル!?
© 2025 NTT DATA Japan Corporation 42
⚫ 過去の任意の時点の状態にデータベースをリカバリする機能
⚫ ベースバックアップとWAL(更新ログ)を組み合わせて実現
#3 PITR(Point-In-Time Recovery)とは
ベースバックアップ
WAL(更新ログ)
この時点にリカバリ
ベースバックアップにWALを適用することでリカバリ
© 2025 NTT DATA Japan Corporation 43
#3 CloudNativePGにおけるPITRの注意点
⚫ ベースバックアップの保存先として、
オブジェクトストレージとVolumeSnapshot
を選択できる。
⚫ インプレースのPITRはサポートしておらず
新規クラスターとしてリカバリされる
バックアップ
既存クラスター 新規クラスター
バックアップ
クラスター
クラスター
Snapshot
VolumeSnapshot
インプレースリカバリ
新規クラスターとしてリカバリ
© 2025 NTT DATA Japan Corporation 44
#3 バックアップ設定とテーブル削除日時
⚫ 毎日0時00分00秒にVolumeSnapshotを取得
⚫ 2025年5月23日15時00分01秒にテーブル削除
⚫ オブジェクトストレージにWALを保存
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: production-db-backup
spec:
schedule: "0 0 0 * * *"
backupOwnerReference: self
cluster:
name: production-db
5月22日
0時00分00秒
5月23日
0時00分00秒
5月23日
15時00分01秒
Volume
Snapshot
Volume
Snapshot
テーブル
削除
backup.yaml
© 2025 NTT DATA Japan Corporation 45
#3 リカバリのフロー
production-db
のバックアップ
削除したテーブルの
ダンプファイル
1. 新規クラスター
をテーブル削除
直前にPITR
production-db
recovery-db
2. テーブルデータを
pg_dumpで抽出
3. 抽出したデータを
元のクラスターに
pg_restoreで復旧
⚫ pg_dump:PostgreSQLデータベースのバックアップを取得するツール
⚫ pg_restore:pg_dumpで作成したバックアップをリストアするツール
© 2025 NTT DATA Japan Corporation 46
#3 リカバリー用DBのYAML
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: recovery-db
spec:
instances: 1
bootstrap:
recovery:
backup:
name: production-db-backup
recoveryTarget:
targetTime: "2025-05-23 15:00:00.000000+09"
recovery-db.yaml
⚫ テーブルデータを抽出する
だけなので1インスタンスで作成
⚫ bootstrapセクションに
バックアップとリストアの情報を設定
⚫ 新規クラスター名
© 2025 NTT DATA Japan Corporation 47
#3 PITR実行時のログ
⚫ recovery-dbのログ
⚫ recovery-dbの状態
$ kubectl logs recovery-db-1
{"level":"info","ts":"2025-05-
20T12:20:03.561931773Z","logger":"postgres","msg":"record","logging_pod":"recovery-db-
1","record":{"log_time":"2025-05-20 12:20:03.561
UTC","process_id":"26","session_id":"682c7373.1a","session_line_num":"3","session_start_time":"2025-05-20
12:20:03 UTC","transaction_id":"0","error_severity":"LOG","sql_state_code":"00000",
"message":"redo starts at 0/3000028","backend_type":"startup","query_id":"0"}}
…
{"level":"info","ts":"2025-05-
20T12:20:03.562299787Z","logger":"postgres","msg":"record","logging_pod":"recovery-db-
1","record":{"log_time":"2025-05-20 12:20:03.561
UTC","process_id":"26","session_id":"682c7373.1a","session_line_num":"5","session_start_time":"2025-05-20
12:20:03 UTC","transaction_id":"0","error_severity":"LOG","sql_state_code":"00000",
"message":"redo done at 0/30000F8 system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00
s","backend_type":"startup","query_id":"0"}}
$ kubectl get pod recovery-db-1
NAME READY STATUS RESTARTS AGE
recovery-db-1 1/1 Running 0 35s
© 2025 NTT DATA Japan Corporation 48
#3 pg_dump/pg_restore
ベースバックアップ
WAL(更新ログ)
pg_dump
pg_restore
customers.dump
© 2025 NTT DATA Japan Corporation 49
#3 正常にリストアできているかを確認
⚫ customersテーブルのレコード数を取得
⚫ 今回は1つのテーブルをリストアするだけで復旧したが、複数のテーブルをリストアしたり、
テーブル間の整合性を保ちつつリカバリーするなど、様々な復旧パターンがある。
$ psql –c "SELECT COUNT(*) FROM customers"
count
-------
1352
(1 row)
© 2025 NTT DATA Japan Corporation 50
#3 まとめ
⚫ オペミスが発生しにくい設定をしたうえで、リカバリできるようにしておくことが重要。
• 自動コミット機能をオフにして、ロールバックできるようにする(PostgreSQL限定)。
• オペミスをしたとしても、リカバリできるように手順をドキュメント化しておく。
⚫ バックアップ・リカバリの適切な手段は環境や要件によって異なる。
• それぞれの環境や要件に合わせた適切な方法を確認しておく。
• バックアップを取得するだけではなく、リカバリまで必ず確認しておく。
⚫ CloudNativePGではインプレースのPITRは不可。
• 他のトランザクションデータを消してしまったりするので、
そもそもIn-placeのリカバリは避けるべきケースが多い。
© 2025 NTT DATA Japan Corporation 51
© 2025 NTT DATA Japan Corporation
7.
まとめ
© 2025 NTT DATA Japan Corporation 52
エピローグ
⚫ 色々と対応はおわったはずですが、、、
(あらためて今回の登場人物)
藤井さん
カトウ君 こばさん
ポスグレチーム
アプリケーションチーム
依頼
問い合わせ
記載されている会社名、商品名、又はサービス名は、
各社の登録商標又は商標です。

つくって壊して直して学ぶ Database on Kubernetes (CloudNative Days Summer 2025 発表資料)

  • 1.
    © 2025 NTTDATA Japan Corporation つくって壊して直して学ぶ Database on Kubernetes 2025/5/23 株式会社NTTデータ 小林 隆浩、加藤 慎也 れ
  • 2.
    © 2025 NTTDATA Japan Corporation 2 今日話すこと ⚫ Database(PostgreSQL) on Kubernetesを構築する際に気にするべきポイントや、 実際の運用で発生するかも知れない障害とその対応を紹介する。 • 「壊して」というより「壊れて学ぶ」のやり方 ⚫ Operatorはここ数年で進化したが、やはりDBには固有の運用があり、理解が難しい。 • 例えば、バックアップやリストア • 急なDBクラスターの停止、など ⚫ Kubernetesのストレージ周りの機能を使いながら、Database on Kubernetesを運用する際に そうした機能をどう活かすかについても、一緒に学んでいこう。
  • 3.
    © 2025 NTTDATA Japan Corporation 3 アジェンダ 1. はじまり - DB on Kubernetesは突然に - 2. つくって学ぶDatabase on Kubernetes 3. 壊して直して学ぶDatabase on Kubernetes 4. 問い合わせ#1 「晴れ時々エラー!?」 5. 問い合わせ#2 「生き返らないクラスター!?」 6. 問い合わせ#3 「消えないで!テーブル!?」 7. まとめ
  • 4.
    © 2025 NTTDATA Japan Corporation 4 © 2025 NTT DATA Japan Corporation 1. はじまり
  • 5.
    © 2025 NTTDATA Japan Corporation 5 Database on Kubernetesは突然に ⚫ カトウ君に上司の藤井さんから依頼が届いているようです! (今回の登場人物) 藤井さん カトウ君 こばさん ポスグレチーム アプリケーションチーム 依頼 問い合わせ
  • 6.
    © 2025 NTTDATA Japan Corporation 6 データベース要件の確認 制定日:2024/8/1 0 DB種別 ■ PostgreSQL □ MySQL □ Oracle(ライセンスは持ち込みのみ) ※必須 1 インスタンス数 □ 1 (冗長性なし。開発環境での利用を想定) ※必須 □ 2 (冗長性あり。非同期を前提とするため、ラグ・データ損失を許容) ■ 3 (冗長性あり。同期を前提とするため、データ損失はゼロ) 2 バックアップ □ コールドバックアップ ※必須 □ オンラインバックアップ ■ オンラインバックアップ+アーカイブログ (PITRに対応可能) 3 保持期間 30 日間 ※必須 4 申請日 西暦 2025 年 4 月 1 日 ※必須 5 申請承認者 ※必須 金融第一事業部 部長 xxxxx 6 記入者 事業部等・担当名 金融第一事業部 ※必須 氏名 yyyyy ※必須 7 連絡先 事業部等・担当名 ■ 記入者と同じ場合はこちらをチェック 2024.8版 DBクラスター 作成申請書 担当・グループ名 役職 氏名 担当・グループ名
  • 7.
    © 2025 NTTDATA Japan Corporation 7 想定するPostgreSQLの構成 ⚫ 3インスタンスで同期レプリケーションを構成し、バックアップとアーカイブを取得する。 プライマリ スタンバイ① スタンバイ② Data WAL アーカ イブ WAL Data WAL Data 更新 参照 WALをスタンバイに転送 ①、②のうち1台に、同 期レプリケーションが完了 すればOK 定期的にWALをアーカイブ バック アップ
  • 8.
    © 2025 NTTDATA Japan Corporation 8 (参考)RDSのMulti-AZ DB Cluster ⚫ 3インスタンスの構成。 ⚫ それぞれのインスタンスが、別AZ に配置される。 ⚫ Write以外のインスタンスでも、 読み取りクエリの処理が可能。 但し、更新ラグが発生する。 ⚫ エンドポイントは下記の3種類。 • Read/Write • Readのみ • 個別インスタンス https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html#multi-az-db-clusters-concepts-overview
  • 9.
    © 2025 NTTDATA Japan Corporation 9 © 2025 NTT DATA Japan Corporation 2. つくって学ぶ Database on Kubernetes
  • 10.
    © 2025 NTTDATA Japan Corporation 10 KubernetesにおけるPostgreSQL Operatorとは ⚫ Kubernetes上でのデータベース運用を補助する機能が実装されている。 • レプリケーションを使った高可用性構成、障害時切り替え等をYAMLで簡単に設定できる。 • バックアップ/リストアも設定可能で、クラウドストレージと連携できる。 PostgreSQL Operator プライマリ スタンバイ スタンバイ プライマリ向けService
  • 11.
    © 2025 NTTDATA Japan Corporation 11 PostgreSQL Operatorの比較 ⚫ PostgreSQL向けにも複数のOperatorが存在。今回はCloudNativePGを利用する。 名称 開発主体 ライセンス 備考 PGO Crunchy Data Apache 2.0 * • 古参Operatorの1つ。機能は十分揃っている。 • 従来のPostgreSQL向けOSSを組み合わせた構成。 • コンテナイメージの商用利用が実質できない。 postgres-operator Zalando MIT • 古参Operatorの1つ。機能は十分揃っている。 • 従来のPostgreSQL向けOSSを組み合わせた構成。 • Kubernetesに詳しいエンジニアが利用しやすい。 CloudNativePG EDB Apache 2.0 • PostgreSQL開発で有名なEDBによるOperator。 • EDBが提供されているマネージドサービス内部でも利用されている。 • 2025年、CNCF Sandbox Projectに。 StackGres OnGres AGPL 3 • 充実した管理UIを提供。 • ライセンスがネックとなる可能性あり。 Percona Operator for PostgreSQL Percona Apache 2.0 • MySQLやPostgreSQLの開発で有名なPerconaのOperator。 • PGOをフォークして開発。完全OSSでの利用が可能。 • 比較的新しいOperator。
  • 12.
    © 2025 NTTDATA Japan Corporation 12 PostgreSQL on Kubernetesのシステム構成 ⚫ GKE上でCloudNativePGを用いて、以下の構成のPostgreSQL on Kubernetesを構築する。 Snapshot Snapshot Snapshot RW R RO P S S WALをGCSにアーカイブ
  • 13.
    © 2025 NTTDATA Japan Corporation 13 (例)PostgreSQLクラスター用のYAML ⚫ 3インスタンス ⚫ 同期レプリケーションの設定 ⚫ データストレージ ⚫ WAL用のストレージ ⚫ バックアップ設定
  • 14.
    © 2025 NTTDATA Japan Corporation 14 © 2025 NTT DATA Japan Corporation 3. 壊して直して学ぶ Database on Kubernetes
  • 15.
    © 2025 NTTDATA Japan Corporation 15 ①壊して直して学ぶ:Podの障害 Snapshot Snapshot Snapshot RW R RO P S S Primary Podの障害
  • 16.
    © 2025 NTTDATA Japan Corporation 16 ①Primary Podの疑似障害 ⚫ クラスタの状態を確認 ⚫ Primary Podを削除 $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-1 0/6055A58 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-2 0/6055A58 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn test-db-3 0/6055A58 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm $ kubectl delete pod test-db-1 pod "test-db-1" deleted
  • 17.
    © 2025 NTTDATA Japan Corporation 17 ①Primary Pod障害の確認と復旧 ⚫ CloudNativePGのログ ⚫ クラスタの状態を確認 $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-2 0/70066E0 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn test-db-1 0/70066E0 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-3 0/70066E0 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm {"level":"info","ts":"2025-05-19T00:54:27.598548554Z","msg":"Current primary isn't healthy, initiating a failover","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluste r":{"name":"test-db","namespace":"default"},"namespace":"default","name":"test- db","reconcileID":"a90e0a46-6bf1-4f36-9dca-b83f6bb5567e"} {"level":"info","ts":"2025-05-19T00:54:27.740028855Z","msg":"Failing over", "controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name" :"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"a90e0a46-6bf1- 4f36-9dca-b83f6bb5567e","newPrimary":"test-db-2"}
  • 18.
    © 2025 NTTDATA Japan Corporation 18 ②壊して直して学ぶ:Podの障害 Snapshot Snapshot Snapshot RW R RO P S S Standby Podの障害
  • 19.
    © 2025 NTTDATA Japan Corporation 19 ②Standby Podの疑似障害 ⚫ クラスタの状態を確認 ⚫ Standby Podを削除 $ kubectl delete pod test-db-1 pod "test-db-1" deleted $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
  • 20.
    © 2025 NTTDATA Japan Corporation 20 ②Standby Pod障害の確認と復旧 ⚫ CloudNativePGのログ ⚫ クラスタの状態を確認 {“level”:“info”,"ts":"2025-05-19T01:06:20.510661896Z","msg":"Creating new Pod to reattach a PVC", "controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name" :"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"9812324d-b86d- 4d21-a43d-39fb6ac7f77b","pod":"test-db-1","pvc":"test-db-1"} {"level":"info","ts":"2025-05-19T01:06:31.80588422Z","msg":"Setting replica label", "controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name" :"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"eb962e67-b7a2- 4ba0-9bce-29b5c4de5049","pod":"test-db-1"} {"level":"info","ts":"2025-05-19T01:06:37.768017501Z","msg":"Cluster has become healthy", "controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name" :"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"c47b81a5-dc5b- 4c9c-9673-edfbd7dfac6e"} $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
  • 21.
    © 2025 NTTDATA Japan Corporation 21 ⚫ CloudNativePGはデフォルトでノード障害に耐えられる設定となっている。 ゾーン 障害に備えたPodの配置戦略(podAntiAffinity) ノード P S S ゾーン ノード P ゾーン S S ノード P S S ノード障害で全滅 ノード障害に耐性 ゾーン障害に耐性 enablePodAntiAffinity:true topologyKey:kubernetes.io/hostname enablePodAntiAffinity:false enablePodAntiAffinity:true topologyKey:topology.kubernetes.io/zone
  • 22.
    © 2025 NTTDATA Japan Corporation 22 ⚫ 特定のラベルをもつノードにスケジューリングする。 ⚫ データベースは特定HWが設定されたノードにスケジューリングしたい場合などに有用。 • DB高速化のためにメモリ増強、高速SSDを搭載など • 今後はGPU搭載なども要件として登場するかもしれない 性能も考慮したPodの配置戦略(nodeSelector) nttdata.com/role: db nttdata.com/role: app
  • 23.
    © 2025 NTTDATA Japan Corporation 23 CloudNativePGでの設定方法 apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: pgcluster-prod spec: affinity: enablePodAntiAffinity: true topologyKey: kubernetes.io/hostname podAntiAffinityType: required nodeSelector: nttdata.com/role: db ⚫ podAntiAffinityを有効化 ⚫ ホスト名で分散 ⚫ 条件を満たすことが必須 ⚫ データベース用ノードに ⚫ GKEノードプールに ラベルを設定済み
  • 24.
    © 2025 NTTDATA Japan Corporation 24 ③壊して直して学ぶ:Nodeの障害 Snapshot Snapshot Snapshot RW R RO P S S Primary Podが存在するノードの障害
  • 25.
    © 2025 NTTDATA Japan Corporation 25 ③Nodeの疑似障害 ⚫ クラスタの状態を確認 ⚫ Primary Podのあるノードを削除 $ kubectl delete node gke-cluster-bb3caaa1-2swn node "gke-cluster-kato-default-pool-bb3caaa1-2swn" deleted $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-2 0/9000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-2swn test-db-1 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-3 0/9000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm
  • 26.
    © 2025 NTTDATA Japan Corporation 26 ③Node障害の確認と復旧 ⚫ CloudNativePGのログ ⚫ クラスタの状態を確認 {"level":"info","ts":"2025-05-19T01:33:40.453415481Z","msg":"Current primary isn't healthy, initiating a failover","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluste r":{"name":"test-db","namespace":"default"},"namespace":"default","name":"test- db","reconcileID":"3e4c576c-1e4a-4b0d-9bd0-3fd129e86716"} {"level":"info","ts":"2025-05-19T01:33:40.718655379Z","msg":"Failing over", "controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name" :"test-db","namespace":"default"},"namespace":"default","name":"test-db","reconcileID":"3e4c576c-1e4a- 4b0d-9bd0-3fd129e86716","newPrimary":"test-db-1"} $ kubectl cnpg status test-db Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- test-db-1 0/B000000 Primary OK BestEffort 1.25.1 gke-cluster-bb3caaa1-hdsv test-db-2 0/B000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-td3t test-db-3 0/B000000 Standby (sync) OK BestEffort 1.25.1 gke-cluster-bb3caaa1-zpcm z
  • 27.
    © 2025 NTTDATA Japan Corporation 27 ここまでのまとめ ⚫ PostgreSQL Operatorは複数あるので、要件に合わせて選択しましょう。 • 机上での比較だとあまり差異がわからないので、実際に使ってみることも重要 ⚫ すべての障害への対策は不可能だが、何が許容できる・できないかを整理することが重要。 • Pod障害/ノード障害/ゾーン障害/リージョン障害 • RPO/RTO ⚫ パフォーマンスの観点からデータベースPodはアプリケーションPodとは 別のノードにスケジューリングすることも考える。 • 大容量メモリ・高いIO性能/低遅延・広帯域の安定したネットワークが必要 • 他Podとのリソース競合を避ける
  • 28.
    © 2025 NTTDATA Japan Corporation 28 © 2025 NTT DATA Japan Corporation 4. #1 晴れ時々エラー
  • 29.
    © 2025 NTTDATA Japan Corporation 29 #1 エラーになったり、ならなかったり? (更新時にエラーが発生している画面) (同じ画面、同じレコードでも成功することもある) (エラー時のサーバ側ログ)
  • 30.
    © 2025 NTTDATA Japan Corporation 30 #1 アプリケーションと動作確認時の接続経路 ⚫ PoC的な位置づけで、本番時の接続と異なる経路でテストを行っていた。 APL Snapshot Snapshot Snapshot RW R RO P S S 動作確認 ?
  • 31.
    © 2025 NTTDATA Japan Corporation 31 #1 Serviceの比較 (CloudNativePGが生成したService) (外部からの接続用に作成したService)
  • 32.
    © 2025 NTTDATA Japan Corporation 32 #1 Podのラベルを確認する ⚫ プライマリを指すためのSelectorは cnpg.io/instanceRole=primary ⚫ cnpg.io/podRole=instance は全てのインスタンスを指す。 ⚫ cnpg.io/podRole=instance も「読取可能な何処かに繋がる」エンドポイントで使われている。 (プライマリPodのラベル) (スタンバイPodのラベル)
  • 33.
    © 2025 NTTDATA Japan Corporation 33 #1 まとめ ⚫ データベースのクラスターにおいて、各インスタンスの役割理解は重要。 ⚫ Database on Kubernetesでは、それらの役割はLabelで表現され、Operatorが管理する。 • カスタムエンドポイントを追加する場合には、Operatorの仕様を理解しないと、 今回のようにトラブルが発生する可能性あり。 ⚫ Read/Write、Read、ReadOnlyなどのエンドポイントは、殆どのOperatorで生成されるため、 アプリケーションはどのクエリを何処に投げるかをきちんと考えて設計する。 • 全てRead/Writeというのも良くない。 • Readを分散するために、ReadOnlyエンドポイントの活用は重要。
  • 34.
    © 2025 NTTDATA Japan Corporation 34 © 2025 NTT DATA Japan Corporation 5. #2 生き返らないクラスター
  • 35.
    © 2025 NTTDATA Japan Corporation 35 #2 PostgreSQLクラスターの状態を確認 ⚫ エラーの原因!? ⚫ プライマリが落ちて、 スタンバイも昇格していない
  • 36.
    © 2025 NTTDATA Japan Corporation 36 #2 CloudNativePGでWAL領域があふれると、 ⚫ 基本的に同じディスク構成となるため、フェイルオーバしてもそちらもあふれる。 ⚫ そのため、CloudNativePGではWALあふれでフェイルオーバしない仕様となっている。 プライマリ スタンバイ① スタンバイ② Data WAL WAL Data WAL Data この仕様がない場合、プライマリからスタンバイへフェイルオーバして、切り替わり先で障害が発生する。 それが再度フェイルオーバを引き起こし、クラスター内でぱたぱた切り替わるような状態となる。 DBではもっとも避けるべき状況の1つ。
  • 37.
    © 2025 NTTDATA Japan Corporation 37 #2 PVC/PVのResizeとは ⚫ Volume拡張では、PVに対応するストレージの拡張だけではなく、コンテナ内のファイル システムで利用できるサイズも拡張される。 Snapshot Snapshot Snapshot RW R RO P S S
  • 38.
    © 2025 NTTDATA Japan Corporation 38 #2 PVCの拡張作業 $ kubectl patch pvc production-db-2-wal -p "{¥"spec¥":{¥"resources¥":{¥"requests¥":{¥"storage¥": ¥"5Gi¥"}}}}" • PVCの確認。WAL用PVCは全て2Gi。 • kubectl patchでPVCを拡張PVCの確認。 • PVC、PVともに拡張されていることを確認。
  • 39.
    © 2025 NTTDATA Japan Corporation 39 #2 まとめ ⚫ データベースで高可用性構成を組んでも、フェイルオーバされないケースは存在する。 • (今回のような)ディスクあふれのケース • 全インスタンスに関わる致命的なパラメータの誤り ⚫ そうした際、Kubernetesリソースを変更する正しい手順を理解しておくことは重要。 • ボリューム拡張では、PVのサイズを直接編集してはいけない。 • ファイルシステムの拡張等、一連の処理が動かない可能性あり • PVCのサイズを拡張し、以降はKubernetesおよびCSIドライバーが担当。 ⚫ こんなことにならないように、そもそもディスク使用量の監視をしましょう。
  • 40.
    © 2025 NTTDATA Japan Corporation 41 © 2025 NTT DATA Japan Corporation 6. #3 消えないで!テーブル!?
  • 41.
    © 2025 NTTDATA Japan Corporation 42 ⚫ 過去の任意の時点の状態にデータベースをリカバリする機能 ⚫ ベースバックアップとWAL(更新ログ)を組み合わせて実現 #3 PITR(Point-In-Time Recovery)とは ベースバックアップ WAL(更新ログ) この時点にリカバリ ベースバックアップにWALを適用することでリカバリ
  • 42.
    © 2025 NTTDATA Japan Corporation 43 #3 CloudNativePGにおけるPITRの注意点 ⚫ ベースバックアップの保存先として、 オブジェクトストレージとVolumeSnapshot を選択できる。 ⚫ インプレースのPITRはサポートしておらず 新規クラスターとしてリカバリされる バックアップ 既存クラスター 新規クラスター バックアップ クラスター クラスター Snapshot VolumeSnapshot インプレースリカバリ 新規クラスターとしてリカバリ
  • 43.
    © 2025 NTTDATA Japan Corporation 44 #3 バックアップ設定とテーブル削除日時 ⚫ 毎日0時00分00秒にVolumeSnapshotを取得 ⚫ 2025年5月23日15時00分01秒にテーブル削除 ⚫ オブジェクトストレージにWALを保存 apiVersion: postgresql.cnpg.io/v1 kind: ScheduledBackup metadata: name: production-db-backup spec: schedule: "0 0 0 * * *" backupOwnerReference: self cluster: name: production-db 5月22日 0時00分00秒 5月23日 0時00分00秒 5月23日 15時00分01秒 Volume Snapshot Volume Snapshot テーブル 削除 backup.yaml
  • 44.
    © 2025 NTTDATA Japan Corporation 45 #3 リカバリのフロー production-db のバックアップ 削除したテーブルの ダンプファイル 1. 新規クラスター をテーブル削除 直前にPITR production-db recovery-db 2. テーブルデータを pg_dumpで抽出 3. 抽出したデータを 元のクラスターに pg_restoreで復旧 ⚫ pg_dump:PostgreSQLデータベースのバックアップを取得するツール ⚫ pg_restore:pg_dumpで作成したバックアップをリストアするツール
  • 45.
    © 2025 NTTDATA Japan Corporation 46 #3 リカバリー用DBのYAML apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: recovery-db spec: instances: 1 bootstrap: recovery: backup: name: production-db-backup recoveryTarget: targetTime: "2025-05-23 15:00:00.000000+09" recovery-db.yaml ⚫ テーブルデータを抽出する だけなので1インスタンスで作成 ⚫ bootstrapセクションに バックアップとリストアの情報を設定 ⚫ 新規クラスター名
  • 46.
    © 2025 NTTDATA Japan Corporation 47 #3 PITR実行時のログ ⚫ recovery-dbのログ ⚫ recovery-dbの状態 $ kubectl logs recovery-db-1 {"level":"info","ts":"2025-05- 20T12:20:03.561931773Z","logger":"postgres","msg":"record","logging_pod":"recovery-db- 1","record":{"log_time":"2025-05-20 12:20:03.561 UTC","process_id":"26","session_id":"682c7373.1a","session_line_num":"3","session_start_time":"2025-05-20 12:20:03 UTC","transaction_id":"0","error_severity":"LOG","sql_state_code":"00000", "message":"redo starts at 0/3000028","backend_type":"startup","query_id":"0"}} … {"level":"info","ts":"2025-05- 20T12:20:03.562299787Z","logger":"postgres","msg":"record","logging_pod":"recovery-db- 1","record":{"log_time":"2025-05-20 12:20:03.561 UTC","process_id":"26","session_id":"682c7373.1a","session_line_num":"5","session_start_time":"2025-05-20 12:20:03 UTC","transaction_id":"0","error_severity":"LOG","sql_state_code":"00000", "message":"redo done at 0/30000F8 system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s","backend_type":"startup","query_id":"0"}} $ kubectl get pod recovery-db-1 NAME READY STATUS RESTARTS AGE recovery-db-1 1/1 Running 0 35s
  • 47.
    © 2025 NTTDATA Japan Corporation 48 #3 pg_dump/pg_restore ベースバックアップ WAL(更新ログ) pg_dump pg_restore customers.dump
  • 48.
    © 2025 NTTDATA Japan Corporation 49 #3 正常にリストアできているかを確認 ⚫ customersテーブルのレコード数を取得 ⚫ 今回は1つのテーブルをリストアするだけで復旧したが、複数のテーブルをリストアしたり、 テーブル間の整合性を保ちつつリカバリーするなど、様々な復旧パターンがある。 $ psql –c "SELECT COUNT(*) FROM customers" count ------- 1352 (1 row)
  • 49.
    © 2025 NTTDATA Japan Corporation 50 #3 まとめ ⚫ オペミスが発生しにくい設定をしたうえで、リカバリできるようにしておくことが重要。 • 自動コミット機能をオフにして、ロールバックできるようにする(PostgreSQL限定)。 • オペミスをしたとしても、リカバリできるように手順をドキュメント化しておく。 ⚫ バックアップ・リカバリの適切な手段は環境や要件によって異なる。 • それぞれの環境や要件に合わせた適切な方法を確認しておく。 • バックアップを取得するだけではなく、リカバリまで必ず確認しておく。 ⚫ CloudNativePGではインプレースのPITRは不可。 • 他のトランザクションデータを消してしまったりするので、 そもそもIn-placeのリカバリは避けるべきケースが多い。
  • 50.
    © 2025 NTTDATA Japan Corporation 51 © 2025 NTT DATA Japan Corporation 7. まとめ
  • 51.
    © 2025 NTTDATA Japan Corporation 52 エピローグ ⚫ 色々と対応はおわったはずですが、、、 (あらためて今回の登場人物) 藤井さん カトウ君 こばさん ポスグレチーム アプリケーションチーム 依頼 問い合わせ
  • 52.