LabHub

ブログ

K8sでDB運用 -- CNPG、Percona、Vitess、Helmチャート完全ガイド

한국어English日本語中文

はじめに

Kubernetesでデータベースを運用することは、数年前まで議論の的でした。 「ステートレスワークロードに最適化されたK8sでなぜDBを?」という疑問が多かったのです。 しかし2026年現在、StatefulSetとOperatorエコシステムが十分に成熟し、K8s上でDBを運用することが標準的な選択肢となりました。

この記事では、主要なデータベースOperatorとHelmチャートを比較し、実践でどのツールをどの状況で使うべきかを整理します。


1. なぜK8sでDBを運用するのか

メリット

デメリット

StatefulSetの基礎

StatefulSetは、K8sで状態保持が必要なワークロード向けのコントローラーです。 通常のDeploymentとは異なり、以下を保証します。

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拡張管理を革新的に改善しました。

主な特徴

インストール

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はストリーミングレプリケーションでデータを同期します。

バックアップとリカバリ

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 Operator for MongoDB(PSMDB)

Percona Operator for PostgreSQL(PPG)

統合モニタリング: 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など)
VTOrcOrchestrator、自動フェイルオーバー担当
VTAdminWebベースのUI管理

Vitessを選ぶべき場合

注意点

Vitessは非常に強力ですが学習曲線が急です。 単純なCRUDアプリケーションには過剰な選択であり、シャーディング戦略(Vschema)設計には十分な検討が必要です。


5. 主要Helmチャート比較

Operatorなしでもデータベースをデプロイできます。 ただし、2025年以降にBitnamiのライセンス変更という重要な変化がありました。

Bitnamiライセンス変更(2025年)

2025年9月以降、ほとんどのBitnami HelmチャートOCIパッケージがBroadcom有料サブスクリプションの背後に移動しました。 代替としてChainguardがBitnamiをフォークした40以上のセキュリティ強化Helmチャートを提供しています。

Helmチャート比較表

チャートDB基本構成HAサポートバックアップ内蔵備考
bitnami/postgresqlPostgreSQLPrimary + Read ReplicaRepmgrベースXレガシー注意
bitnami/postgresql-haPostgreSQLPrimary + StandbyPgpool-II連携XHA専用チャート
bitnami/mysqlMySQLPrimary + Secondary半同期レプリケーションXInnoDB Clusterオプション
bitnami/redisRedisMaster + ReplicaSentinelベースXClusterモード別途
bitnami/mongodbMongoDBReplicaSet内蔵XSharded別途チャート
bitnami/mariadbMariaDBPrimary + SecondaryGaleraオプションXMySQL互換

Helmチャートが適切な場合


6. CNPG vs Percona vs Vitess vs Helmチャート 総合比較

機能比較表

項目CNPGPerconaVitessHelmチャート
対応DBPostgreSQLMySQL, MongoDB, PGMySQL(シャーディング)多様
ライセンスApache 2.0Apache 2.0Apache 2.0チャートにより異なる
CNCFステータスSandbox-Graduated-
HA自動フェイルオーバーOOOチャートによる
自動バックアップO(Barman)O(マルチストレージ)OX(別途構成)
PITROO部分対応X
水平シャーディングXMongoDBのみO(コア機能)X
モニタリング統合PrometheusPMM + PrometheusVTAdminチャート別メトリクス
コネクションプーリングPgBouncer内蔵ProxySQL/HAProxyVTGate内蔵別途構成
運用難易度
プロダクション適合度高(大規模)

選択ガイド


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

核心原則:

パフォーマンスチューニング

リソース制限

バックアップ戦略

3-2-1バックアップルールをK8s環境に適用します。


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) モニタリング/アラートなしで運用

最低限、以下のアラートを構成してください:

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の宣言的管理モデルと自然に統合されます。

要点まとめ:

Operatorを導入する場合は、まず開発環境で十分にテストし、障害シナリオ(Pod削除、ノードダウン、AZ障害)をシミュレーションしてからプロダクションに適用してください。

コメント

まだコメントはありません。

ログインするとコメントできます