A production-ready PostgreSQL cluster for Kubernetes built with CloudNativePG. This project provides a complete database platform with high availability, automated secrets management, S3-compatible backups, and comprehensive monitoring.
Support the project:
| Application | Description |
|---|---|
| CloudNativePG | PostgreSQL operator for Kubernetes with HA, backups, and rolling updates |
| PostgreSQL 16.3 | 3-node cluster with replication and failover |
| PgBouncer | Connection pooler with session mode (1000 max connections) |
| Application | Description |
|---|---|
| OpenBao | Vault-compatible secrets backend with Raft consensus |
| External Secrets Operator | Kubernetes-native secret synchronization |
| Secrets Store CSI Driver | Mount secrets as volumes in pods |
| Application | Description |
|---|---|
| RustFS | S3-compatible object storage for backups |
| Barman Cloud | PostgreSQL backup and recovery via CNPG plugin |
| Application | Description |
|---|---|
| Pigsty pg_exporter | Comprehensive PostgreSQL metrics exporter |
| VictoriaMetrics | Time-series database for metrics storage |
For detailed setup instructions, configuration examples, and deployment strategies:
Supercharge Postgres on K8s: A CNPG + PostgreSQL + Pigsty + Observability Guide
┌─────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
┌──────────────┐ │ ┌─────────────────┐ ┌─────────────────────────┐ │
│ Client │──────────────┼──│ PgBouncer │──────│ PostgreSQL Cluster │ │
│ Application │ │ │ (2 replicas) │ │ (3 nodes: 1 primary, │ │
└──────────────┘ │ └─────────────────┘ │ 2 replicas) │ │
│ └───────────┬─────────────┘ │
│ │ │
│ ┌─────────────────┐ │ │
│ │ OpenBao │ Credentials │ Backups │
│ │ (3 replicas) │◄─────────────────┤ │
│ │ Raft HA │ │ │
│ └────────┬────────┘ ▼ │
│ │ ┌─────────────────┐ │
│ │ │ RustFS │ │
│ ▼ │ (S3 Storage) │ │
│ ┌─────────────────┐ │ 40Gi │ │
│ │ External Secrets│ └─────────────────┘ │
│ │ Operator │ │
│ └─────────────────┘ ┌─────────────────┐
│ │ Pigsty Exporter│
│ Metrics ────────────────────│ (Monitoring) │
│ └────────┬────────┘
│ │ │
└────────────────────────────────────────────────┼────────┘
│
▼
┌─────────────────┐
│ VictoriaMetrics │
│ (Metrics DB) │
└─────────────────┘
- Kubernetes cluster (1.25+)
- CloudNativePG Operator
- External Secrets Operator
- Secrets Store CSI Driver
- VictoriaMetrics Operator (for monitoring)
- Storage class:
openebs-lvmor equivalent
# Add Helm repository
helm repo add openbao https://openbao.github.io/openbao-helm
helm repo update
# Install OpenBao
helm install openbao openbao/openbao \
--namespace openbao \
--create-namespace \
-f openbao/values.yml
# Initialize and unseal (follow OpenBao documentation)
kubectl exec -n openbao openbao-0 -- bao operator init
kubectl exec -n openbao openbao-0 -- bao operator unseal <key># Enable Kubernetes auth
kubectl exec -n openbao openbao-0 -- bao auth enable kubernetes
# Configure the auth method (see external-secret-operator/k8s-role.md for details)
kubectl exec -n openbao openbao-0 -- bao write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443"
# Create policy for External Secrets Operator
kubectl exec -n openbao openbao-0 -- bao policy write eso-policy - <<EOF
path "secrets/*" {
capabilities = ["read", "list"]
}
EOF
# Create role
kubectl exec -n openbao openbao-0 -- bao write auth/kubernetes/role/openbao-readonly \
bound_service_account_names=openbao-sa \
bound_service_account_namespaces=postgres \
policies=eso-policy \
ttl=1h# Create namespace and deploy
kubectl apply -f rustfs/rustfs-stack.yml
# Verify deployment
kubectl get pods -n rustfs# Create namespace
kubectl create namespace postgres
# Apply secret store and generators
kubectl apply -f external-secret-operator/secret-store.yml
kubectl apply -f external-secret-operator/password-generator.yml
kubectl apply -f external-secret-operator/es-superuser.yml
kubectl apply -f external-secret-operator/es-application.yml
kubectl apply -f external-secret-operator/push-secret.yml# Apply CNPG resources
kubectl apply -f cnpg/object-store.yml
kubectl apply -f cnpg/es-object-store.yml
kubectl apply -f cnpg/cluster.yml
kubectl apply -f cnpg/connection-pooler.yml
# Verify cluster status
kubectl get cluster -n postgres
kubectl get pods -n postgres# Apply Pigsty exporter and monitoring rules
kubectl apply -f pigsty-exporter/es-exporter-cred.yml
kubectl apply -f pigsty-exporter/exporter.yml
kubectl apply -f pigsty-exporter/pod-monitor.yml
kubectl apply -f pigsty-exporter/vmservicescrape.yml
kubectl apply -f pigsty-exporter/vmrule.yml# Get connection credentials
kubectl get secret cluster-app-user -n postgres -o jsonpath='{.data.password}' | base64 -d
# Connect via pgbouncer (LoadBalancer)
kubectl get svc -n postgres psql-cluster-pooler
# Port forward for local access
kubectl port-forward svc/psql-cluster-pooler -n postgres 5432:5432
psql -h localhost -U app -d appThe cluster is configured in cnpg/cluster.yml:
# Key settings
instances: 3
postgresql:
parameters:
max_connections: "200"
shared_buffers: "256MB"
effective_cache_size: "768MB"
wal_buffers: "8MB"
min_wal_size: "1GB"
max_wal_size: "2GB"Resources per instance:
- Memory: 384Mi - 1Gi
- CPU: 200m - 2 cores
- Storage: 5Gi (OpenEBS LVM)
PgBouncer is configured in cnpg/connection-pooler.yml:
instances: 2
type: rw # Read-write connections
poolMode: session # Session pooling mode
parameters:
max_client_conn: "1000"
default_pool_size: "10"Backups are configured in cnpg/object-store.yml:
retentionPolicy: "30d"
barmanObjectStore:
destinationPath: s3://ar-cnpg-backup/hl-cnpg-cluster/
endpointURL: http://rustfs-service.rustfs.svc:7000
wal:
compression: gzip
data:
compression: gzipManual backup:
kubectl apply -f cnpg/backup.yml
kubectl get backup -n postgresExternal Secrets Operator handles credential rotation:
- Superuser credentials: Auto-generated, 24h refresh
- Application credentials: Auto-generated, 24h refresh
- Backup credentials: Synced from OpenBao vault
Configure the secret store in external-secret-operator/secret-store.yml:
provider:
vault:
server: "http://openbao.openbao.svc:8200"
path: "secrets"
version: "v2"cnpg-postgres-stack/
├── cnpg/ # PostgreSQL cluster configurations
│ ├── cluster.yml # 3-node PostgreSQL cluster definition
│ ├── connection-pooler.yml # PgBouncer pooler configuration
│ ├── backup.yml # On-demand backup resource
│ ├── object-store.yml # S3 backup destination config
│ └── es-object-store.yml # External secret for backup creds
├── external-secret-operator/ # Secret management
│ ├── secret-store.yml # OpenBao connection config
│ ├── password-generator.yml # Automatic password generation
│ ├── es-superuser.yml # PostgreSQL superuser secret
│ ├── es-application.yml # Application user secret
│ ├── push-secret.yml # Sync secrets back to vault
│ └── k8s-role.md # Kubernetes auth setup guide
├── openbao/ # Secrets backend
│ ├── Chart.yml # Helm chart definition
│ └── values.yml # OpenBao Helm values (3-node HA)
├── pigsty-exporter/ # Monitoring stack
│ ├── exporter.yml # pg_exporter deployment
│ ├── pg_exporter.yml # Metrics collector config
│ ├── vmrule.yml # Recording & alerting rules
│ ├── pod-monitor.yml # Prometheus PodMonitor
│ ├── vmservicescrape.yml # VictoriaMetrics scrape config
│ └── es-exporter-cred.yml # Exporter credentials secret
├── rustfs/ # S3-compatible storage
│ └── rustfs-stack.yml # Complete RustFS deployment
├── LICENSE # MIT License
└── README.md # This file
| Component | Storage | Class |
|---|---|---|
| PostgreSQL (per instance) | 5Gi × 3 | openebs-lvm |
| OpenBao data (per instance) | 2Gi × 3 | openebs-lvm |
| OpenBao audit (per instance) | 1Gi × 3 | openebs-lvm |
| RustFS | 40Gi | openebs-lvm |
| Total | ~64Gi |
The Pigsty exporter provides comprehensive PostgreSQL metrics:
- Connection statistics and pooler metrics
- Replication lag and streaming status
- Query performance (pg_stat_statements)
- Table and index bloat detection
- WAL archiving status
- Lock contention monitoring
- Background worker statistics
Access metrics:
# Port forward to exporter
kubectl port-forward svc/pg-exporter -n postgres 9630:9630
# View metrics
curl http://localhost:9630/metricsVictoriaMetrics integration:
- Recording rules aggregate metrics for dashboards
- Alert rules monitor database health
- ServiceScrape configured for 30s intervals
Contributions are welcome. If you find a bug or have an improvement:
- Fork the repository
- Create a feature branch
- Submit a pull request
Please open an issue first to discuss significant changes.
This project is licensed under the MIT License - see the LICENSE file for details.
This project is intended for educational purposes and development environments.
The default configuration uses trust-based authentication which is not suitable for production. Before deploying to production:
- Change
pg_hbaauthentication fromtrusttoscram-sha-256 - Enable TLS for all connections
- Review and harden OpenBao seal configuration
- Implement proper network policies
- Configure appropriate resource limits for your workload
Users are solely responsible for ensuring their deployment meets security requirements for their environment.
