- Authors

- Name
- Youngju Kim
- @fjvbn20031
はじめに
Kubernetesでデータベースを運用することは、数年前まで議論の的でした。 「ステートレスワークロードに最適化されたK8sでなぜDBを?」という疑問が多かったのです。 しかし2026年現在、StatefulSetとOperatorエコシステムが十分に成熟し、K8s上でDBを運用することが標準的な選択肢となりました。
この記事では、主要なデータベースOperatorとHelmチャートを比較し、実践でどのツールをどの状況で使うべきかを整理します。
1. なぜK8sでDBを運用するのか
メリット
- 一貫したデプロイパイプライン: アプリケーションとDBを同じGitOpsワークフローで管理
- リソース効率性: ノードリソースをアプリケーションとDBが共有し、自動スケジューリングで活用度を最大化
- 自動復旧: Pod障害時の自動再起動、ノード障害時の自動再スケジューリング
- 環境の一貫性: 開発/ステージング/プロダクションで同一のDB構成を宣言的にデプロイ
- コスト削減: マネージドDBサービス(RDS、Cloud SQL)と比較してライセンスとインフラコストの削減が可能
デメリット
- 運用の複雑さ: ストレージ、ネットワーク、バックアップなど直接管理すべき領域が多い
- パフォーマンスオーバーヘッド: コンテナネットワーク、ストレージレイヤー追加によるレイテンシ
- 専門性の要求: K8sとDB両方に対する深い理解が必要
- データ喪失リスク: 不正なPV/PVC設定やアップグレードミスによるデータ損失の可能性
StatefulSetの基礎
StatefulSetは、K8sで状態保持が必要なワークロード向けのコントローラーです。 通常のDeploymentとは異なり、以下を保証します。
- 安定したネットワークID: 各Podが固有のホスト名(例: postgres-0、postgres-1)を持ち維持
- 順序保証デプロイ/スケーリング: Podが0から順番に作成され、逆順で終了
- 永続ストレージ: volumeClaimTemplatesを通じて各Podに固有のPVCがバインド
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ['ReadWriteOnce']
storageClassName: gp3
resources:
requests:
storage: 50Gi
しかし、StatefulSetだけではHA、自動フェイルオーバー、バックアップ/リカバリ、モニタリングなどを実装するのは困難です。 この部分を解決するのがOperatorパターンです。
2. CloudNativePG(CNPG)-- PostgreSQL専用Operator
概要
CloudNativePG(CNPG)は、EDB(EnterpriseDB)が開発を開始し、現在はCNCF Sandboxプロジェクトとして管理されるPostgreSQL専用Kubernetes Operatorです。 2026年4月時点の最新バージョンは1.29で、Image CatalogとartifactsエコシステムによるPostgreSQL拡張管理を革新的に改善しました。
主な特徴
- ネイティブK8s設計: Patroniのような外部HAツールなしでK8sのリーダー選出メカニズムを直接使用
- 宣言的DB管理: Database CRDでPostgreSQLデータベースのライフサイクル管理
- 論理的レプリケーション: Publication / Subscription CRDによるオンラインマイグレーションとメジャーバージョンアップグレード対応
- CNPG-Iプラグインフレームワーク: 外部プラグインで機能拡張可能
- PITRサポート: WALアーカイビングベースのPoint-In-Time Recovery
- 並列リコンサイラー: クラスター管理効率を高める並列処理
インストール
Helmを使ったインストールが最も簡単です。
# Helmリポジトリ追加
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update
# Operatorインストール
helm upgrade --install cnpg \
--namespace cnpg-system \
--create-namespace \
cnpg/cloudnative-pg
またはマニフェストで直接インストールすることもできます。
kubectl apply --server-side -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.29/releases/cnpg-1.29.0.yaml
HAアーキテクチャ
CNPGはPrimary 1台 + Standby N台の構成です。 PrimaryがWriteを担当し、Standbyはストリーミングレプリケーションでデータを同期します。
- Primary障害時にStandbyの1つが自動的にPromote
- Switchover(計画的な切り替え)とFailover(障害時の切り替え)の両方をサポート
- 同期レプリケーションによるデータ耐久性保証オプション(dataDurability)
バックアップとリカバリ
CNPGはBarmanベースの継続的バックアップを内蔵しています。
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: prod-pg
spec:
instances: 3
storage:
size: 100Gi
storageClass: gp3
backup:
barmanObjectStore:
destinationPath: s3://my-backup-bucket/prod-pg/
s3Credentials:
accessKeyId:
name: aws-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: aws-creds
key: SECRET_ACCESS_KEY
wal:
compression: gzip
retentionPolicy: '30d'
ScheduledBackupで定期バックアップを予約できます。
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: prod-pg-daily
spec:
schedule: '0 2 * * *'
cluster:
name: prod-pg
backupOwnerReference: self
3. Percona Operator -- マルチDB対応
概要
Perconaは、MySQL、MongoDB、PostgreSQLの3つのデータベースに対してそれぞれ専用のKubernetes Operatorを提供しています。 Apache 2.0ライセンスで完全オープンソースであり、エンタープライズ級の機能を無料で使用できます。
対応DB別の特徴
Percona Operator for MySQL(PXC)
- Percona XtraDB ClusterベースのマルチPrimaryアーキテクチャ
- Galera同期レプリケーションで全ノードで読み書き可能
- ProxySQLまたはHAProxyによる自動ルーティング
- 2026年GAリリースでGroup Replicationオプション追加
Percona Operator for MongoDB(PSMDB)
- ReplicaSetおよびSharded Clusterサポート
- PVCスナップショットベースのバックアップサポート(2025年追加)
- MongoDB 8.0公式サポート
- IAM Role for Service Accountによるクラウドストレージ認証
Percona Operator for PostgreSQL(PPG)
- PatroniベースのHA構成
- pg_tde(透過的データ暗号化)ネイティブサポート(2026年)
- ゼロダウンタイムメジャーバージョンアップグレードロードマップ進行中
統合モニタリング: PMM
Percona Monitoring and Management(PMM)は、MySQL、MongoDB、PostgreSQL全体を1つのダッシュボードでモニタリングできるツールです。
apiVersion: pxc.percona.com/v1
kind: PerconaXtraDBCluster
metadata:
name: prod-mysql
spec:
crVersion: '1.15.0'
pxc:
size: 3
image: percona/percona-xtradb-cluster:8.0
resources:
requests:
memory: 2Gi
cpu: '1'
volumeSpec:
persistentVolumeClaim:
storageClassName: gp3
resources:
requests:
storage: 100Gi
haproxy:
enabled: true
size: 2
pmm:
enabled: true
serverHost: monitoring-service
backup:
schedule:
- name: daily-backup
schedule: '0 3 * * *'
keep: 7
storageName: s3-backup
storages:
s3-backup:
type: s3
s3:
bucket: my-backup-bucket
credentialsSecret: aws-creds
region: ap-northeast-2
マルチクラスターサポート
Percona Operatorはクロスリージョンレプリケーションをサポートし、複数のK8sクラスター間でデータを同期できます。 これにより災害復旧(DR)構成が可能になります。
4. Vitess -- MySQL水平シャーディング
概要
VitessはYouTubeで大規模MySQLワークロードを処理するために開発され、現在CNCF Graduatedプロジェクトです。 MySQL互換のインターフェースを提供しながら、透過的シャーディング、コネクションプーリング、オンラインリシャーディングをサポートします。
PlanetScaleはVitessを商用化した代表的なDBaaSサービスです。
アーキテクチャ構成要素
| 構成要素 | 役割 |
|---|---|
| VTGate | クエリルーター、アプリケーションが接続するエンドポイント |
| VTTablet | 各MySQLインスタンスをラップするプロキシ |
| Topology Service | クラスターメタデータ保存(etcdなど) |
| VTOrc | Orchestrator、自動フェイルオーバー担当 |
| VTAdmin | WebベースのUI管理 |
Vitessを選ぶべき場合
- 単一MySQLインスタンスでは処理しきれない大規模ライトトラフィック
- 数十億行以上の大容量テーブルシャーディングが必要な場合
- オンラインスキーマ変更(Online DDL)が頻繁な環境
- MySQL互換性を維持しつつ水平スケーリングが必要な場合
注意点
Vitessは非常に強力ですが学習曲線が急です。 単純なCRUDアプリケーションには過剰な選択であり、シャーディング戦略(Vschema)設計には十分な検討が必要です。
5. 主要Helmチャート比較
Operatorなしでもデータベースをデプロイできます。 ただし、2025年以降にBitnamiのライセンス変更という重要な変化がありました。
Bitnamiライセンス変更(2025年)
2025年9月以降、ほとんどのBitnami HelmチャートOCIパッケージがBroadcom有料サブスクリプションの背後に移動しました。 代替としてChainguardがBitnamiをフォークした40以上のセキュリティ強化Helmチャートを提供しています。
Helmチャート比較表
| チャート | DB | 基本構成 | HAサポート | バックアップ内蔵 | 備考 |
|---|---|---|---|---|---|
| bitnami/postgresql | PostgreSQL | Primary + Read Replica | Repmgrベース | X | レガシー注意 |
| bitnami/postgresql-ha | PostgreSQL | Primary + Standby | Pgpool-II連携 | X | HA専用チャート |
| bitnami/mysql | MySQL | Primary + Secondary | 半同期レプリケーション | X | InnoDB Clusterオプション |
| bitnami/redis | Redis | Master + Replica | Sentinelベース | X | Clusterモード別途 |
| bitnami/mongodb | MongoDB | ReplicaSet | 内蔵 | X | Sharded別途チャート |
| bitnami/mariadb | MariaDB | Primary + Secondary | Galeraオプション | X | MySQL互換 |
Helmチャートが適切な場合
- 開発/テスト環境: 素早くDBを立ち上げたいとき
- シンプルな構成: HAが必須でない小規模サービス
- 学習目的: K8sでのDB運用の基礎を学ぶとき
- カスタム設定が多い場合: values.yamlで細かいチューニングが必要なとき
6. CNPG vs Percona vs Vitess vs Helmチャート 総合比較
機能比較表
| 項目 | CNPG | Percona | Vitess | Helmチャート |
|---|---|---|---|---|
| 対応DB | PostgreSQL | MySQL, MongoDB, PG | MySQL(シャーディング) | 多様 |
| ライセンス | Apache 2.0 | Apache 2.0 | Apache 2.0 | チャートにより異なる |
| CNCFステータス | Sandbox | - | Graduated | - |
| HA自動フェイルオーバー | O | O | O | チャートによる |
| 自動バックアップ | O(Barman) | O(マルチストレージ) | O | X(別途構成) |
| PITR | O | O | 部分対応 | X |
| 水平シャーディング | X | MongoDBのみ | O(コア機能) | X |
| モニタリング統合 | Prometheus | PMM + Prometheus | VTAdmin | チャート別メトリクス |
| コネクションプーリング | PgBouncer内蔵 | ProxySQL/HAProxy | VTGate内蔵 | 別途構成 |
| 運用難易度 | 中 | 中 | 高 | 低 |
| プロダクション適合度 | 高 | 高 | 高(大規模) | 中 |
選択ガイド
- PostgreSQLをK8sで運用: CNPGが最優先。K8sネイティブ設計と活発なコミュニティ
- MySQL/MongoDB運用: Percona Operator。統合モニタリング(PMM)が強み
- 大規模MySQLシャーディング: Vitess。数十億行以上の大容量データ処理
- 開発/テスト環境: Helmチャート。素早いデプロイとシンプルな構成
- マルチDB環境統合管理: Percona。MySQL + MongoDB + PostgreSQLを1つの運用モデルで
7. 運用上の注意点
ストレージ(PV/PVC)
ストレージはK8s DB運用で最も重要な要素です。
# 推奨StorageClass例(AWS EBS gp3)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3-db
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: '5000'
throughput: '250'
encrypted: 'true'
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Retain
核心原則:
- volumeBindingMode: WaitForFirstConsumer -- PodがスケジュールされたAZでボリュームを作成
- reclaimPolicy: Retain -- PVC削除時もデータを保存
- allowVolumeExpansion: true -- オンラインボリューム拡張を許可
- WALとDataボリュームの分離 -- シーケンシャルライト(WAL)とランダムアクセス(Data)を分離しパフォーマンス向上
パフォーマンスチューニング
- Guaranteed QoS: requestsとlimitsを同一に設定してCPUスロットリングを防止
- トポロジ対応スケジューリング: nodeAffinityでDB Podを高性能ノードに配置
- アンチアフィニティ: DB Podが異なるノードに分散するよう設定
リソース制限
- DB Podには必ずresources.requestsとlimitsを設定
- メモリlimits超過時OOMKill発生 -- DBプロセスが強制終了
- PostgreSQLのshared_buffersはコンテナメモリの25%程度に設定
- MySQLのinnodb_buffer_pool_sizeはコンテナメモリの50~70%に設定
バックアップ戦略
3-2-1バックアップルールをK8s環境に適用します。
- 3つのコピー: Primaryデータ + WALアーカイブ + 物理バックアップ
- 2つの異なるメディア: ローカルPV + Object Storage(S3/GCS)
- 1つのオフサイト: 別リージョンのバケットに複製
8. 実践例: CNPGでPostgreSQL HAクラスター構築
実際のプロダクション環境で使用できるCNPGクラスターの完全なYAMLです。
Step 1: NamespaceとSecret作成
kubectl create namespace database
kubectl create secret generic pg-superuser \
--namespace database \
--from-literal=username=postgres \
--from-literal=password=CHANGE_ME_TO_STRONG_PASSWORD
kubectl create secret generic aws-creds \
--namespace database \
--from-literal=ACCESS_KEY_ID=your-access-key \
--from-literal=SECRET_ACCESS_KEY=your-secret-key
Step 2: PostgreSQLクラスター定義
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: prod-pg
namespace: database
spec:
description: 'Production PostgreSQL HA Cluster'
imageName: ghcr.io/cloudnative-pg/postgresql:16.4
instances: 3
startDelay: 30
stopDelay: 30
primaryUpdateStrategy: unsupervised
postgresql:
parameters:
shared_buffers: '2GB'
effective_cache_size: '6GB'
work_mem: '64MB'
maintenance_work_mem: '512MB'
max_connections: '200'
pg_hba:
- host all all 10.0.0.0/8 scram-sha-256
bootstrap:
initdb:
database: appdb
owner: appuser
secret:
name: pg-superuser
storage:
size: 100Gi
storageClass: gp3-db
walStorage:
size: 30Gi
storageClass: gp3-db
resources:
requests:
memory: 8Gi
cpu: '4'
limits:
memory: 8Gi
cpu: '4'
affinity:
enablePodAntiAffinity: true
topologyKey: kubernetes.io/hostname
monitoring:
enablePodMonitor: true
backup:
barmanObjectStore:
destinationPath: s3://my-backup-bucket/prod-pg/
s3Credentials:
accessKeyId:
name: aws-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: aws-creds
key: SECRET_ACCESS_KEY
wal:
compression: gzip
maxParallel: 4
data:
compression: gzip
jobs: 4
retentionPolicy: '30d'
nodeMaintenanceWindow:
inProgress: false
reusePVC: true
Step 5: デプロイと確認
kubectl apply -f cluster.yaml
kubectl apply -f scheduled-backup.yaml
kubectl apply -f pooler.yaml
# クラスターステータス確認
kubectl get cluster -n database
# Podステータス確認
kubectl get pods -n database
# クラスター詳細情報
kubectl describe cluster prod-pg -n database
# Primaryへの接続テスト
kubectl exec -it prod-pg-1 -n database -- psql -U postgres -d appdb
9. アンチパターン -- K8s DB運用で避けるべきミス
1) DeploymentでDBをデプロイ
Deploymentはステートレスワークロード用です。 DBにDeploymentを使うと、Pod再起動時にデータが失われたり、複数のPodが同じデータディレクトリにアクセスする問題が発生します。 必ずStatefulSetまたはOperator CRDを使用してください。
2) PVCなしでemptyDirを使用
emptyDirはPod削除時にデータも一緒に消えます。 テスト環境でもDBデータにはPVCを使う習慣をつけましょう。
3) バックアップなしで運用
OperatorがHAを提供していても、バックアップは別途必ず構成する必要があります。 HAはインフラ障害に対する保護で、バックアップは論理的エラー(誤ったDELETE文など)に対する保護です。
4) リソース制限未設定
DB Podにlimitsを設定しないと、他のPodのリソースを食いつぶしたり、予測不能なタイミングでOOMKillが発生する可能性があります。
5) reclaimPolicy: Delete の使用
デフォルトのreclaimPolicyがDeleteのStorageClassを使うと、PVC削除時にPV(実データ)も一緒に削除されます。 DB用StorageClassは必ずRetainに設定してください。
6) 単一AZに全DB Podを配置
Pod Anti-Affinityなしでデプロイすると、全DB Podが同じノードやAZに配置される可能性があります。
7) モニタリング/アラートなしで運用
最低限、以下のアラートを構成してください:
- ディスク使用率80%超過
- レプリケーション遅延10秒以上
- Pod再起動回数の増加
- バックアップ失敗検知
8) DBアップグレード時のローリングアップデート未検証
PostgreSQL、MySQLなどのメジャーバージョンアップグレードは、必ず別クラスターでテスト後に実施してください。
9) Secretを平文で管理
DBパスワードをYAMLにハードコーディングしないでください。 External Secrets OperatorやSealed Secretsを使って安全に管理しましょう。
# External Secrets例
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: pg-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secretsmanager
kind: SecretStore
target:
name: pg-superuser
data:
- secretKey: username
remoteRef:
key: prod/database/credentials
property: username
- secretKey: password
remoteRef:
key: prod/database/credentials
property: password
まとめ
K8sでDBを運用することは、もはや実験的な選択ではありません。 CNPG、Percona、Vitessのような成熟したOperatorが複雑な運用作業を自動化し、K8sの宣言的管理モデルと自然に統合されます。
要点まとめ:
- PostgreSQLをK8sで運用するならCloudNativePGが最善の選択
- MySQL/MongoDB/PostgreSQLを統合管理するならPercona Operator
- 大規模MySQLシャーディングが必要ならVitess
- 開発/テスト環境ではHelmチャートが依然として便利
- どのツールを選択してもストレージ、バックアップ、モニタリングは必ず対応すること
Operatorを導入する場合は、まず開発環境で十分にテストし、障害シナリオ(Pod削除、ノードダウン、AZ障害)をシミュレーションしてからプロダクションに適用してください。