cnpg-database-manager¶
Multi-database and multi-tenant management for CloudNativePG clusters with automatic secret generation and isolation
Homepage: https://github.com/encircle360-oss/helm-charts/tree/main/charts/cnpg-database-manager
⚠️ UNDER CONSTRUCTION This chart is currently under active development and has not been battle-tested in production environments. NOT PRODUCTION READY - Use at your own risk and thoroughly test in non-production environments first.
Why This Chart?¶
The official CloudNativePG cluster
chart only supports single database per deployment. This chart fills the gap by providing:
- Multi-Database Management: Deploy multiple databases in one PostgreSQL cluster
- Automatic Secret Generation: Each database gets isolated credentials
- Secret Replication: Optional secret distribution to application namespaces
- Multi-Tenant Ready: Perfect for consolidating multiple lightweight databases
Use this chart when you want to consolidate multiple applications into one PostgreSQL cluster while maintaining security isolation.
Prerequisites¶
- Kubernetes 1.24+
- Helm 3.8+
- CloudNativePG operator installed (v1.25+)
Installing the Chart¶
To install the chart with the release name my-databases
:
helm repo add encircle360-oss https://encircle360-oss.github.io/helm-charts/
helm repo update
helm install my-databases encircle360-oss/cnpg-database-manager
Uninstalling the Chart¶
To uninstall/delete the my-databases
deployment:
Configuration¶
Basic Example - Single Cluster with Multiple Databases¶
clusters:
main:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 50Gi
storageClass: standard
databases:
- name: keycloak
owner: keycloak
- name: paperless
owner: paperless
- name: n8n
owner: n8n
This creates: - One PostgreSQL cluster named main
with 3 instances - Three separate databases with isolated credentials - Automatic secret generation for each database
Multi-Cluster Setup¶
clusters:
production:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 100Gi
databases:
- name: api-prod
owner: api
- name: web-prod
owner: web
staging:
enabled: true
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 20Gi
databases:
- name: api-staging
owner: api
- name: web-staging
owner: web
Backup Configuration¶
clusters:
main:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 50Gi
backup:
enabled: true
schedule: "0 0 * * *"
retentionPolicy: "30d"
s3:
bucket: my-postgres-backups
region: eu-central-1
path: /cluster-main
credentials:
existingSecret: s3-credentials
databases:
- name: production-db
owner: app
Monitoring with Prometheus¶
clusters:
main:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 50Gi
monitoring:
enabled: true
podMonitor:
enabled: true
databases:
- name: app-db
owner: app
Secret Replication to Application Namespaces¶
clusters:
main:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 50Gi
databases:
- name: keycloak
owner: keycloak
secretNamespace: keycloak-ns
- name: paperless
owner: paperless
secretNamespace: paperless-ns
This automatically replicates database secrets to the application namespaces.
Advanced PostgreSQL Configuration¶
clusters:
main:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 100Gi
storageClass: fast-ssd
resources:
requests:
memory: "4Gi"
cpu: "2000m"
limits:
memory: "8Gi"
cpu: "4000m"
postgresql:
parameters:
max_connections: "300"
shared_buffers: "2GB"
effective_cache_size: "6GB"
maintenance_work_mem: "512MB"
checkpoint_completion_target: "0.9"
wal_buffers: "16MB"
default_statistics_target: "100"
random_page_cost: "1.1"
effective_io_concurrency: "200"
work_mem: "6990kB"
min_wal_size: "1GB"
max_wal_size: "4GB"
databases:
- name: highload-app
owner: app
Maintainers¶
Name | Url | |
---|---|---|
encircle360-oss | oss@encircle360.com |
Source Code¶
Values¶
Key | Type | Default | Description |
---|---|---|---|
clusters | object | {} (no clusters deployed by default) | PostgreSQL cluster configurations. Each key represents a cluster name. |
Configuration Parameters¶
The chart uses a dynamic configuration structure where each PostgreSQL cluster is defined under the clusters
key. Below are the detailed configuration options:
Cluster Configuration¶
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
clusters.<name>.enabled | bool | Yes | - | Enable or disable this cluster |
clusters.<name>.instances | int | Yes | - | Number of PostgreSQL instances (replicas) |
clusters.<name>.imageName | string | Yes | - | PostgreSQL container image with tag |
clusters.<name>.storage.size | string | Yes | - | Size of persistent volume (e.g., 50Gi ) |
clusters.<name>.storage.storageClass | string | No | - | Storage class name |
clusters.<name>.resources.requests.memory | string | No | - | Memory request (e.g., 2Gi ) |
clusters.<name>.resources.requests.cpu | string | No | - | CPU request (e.g., 1000m ) |
clusters.<name>.resources.limits.memory | string | No | - | Memory limit (e.g., 4Gi ) |
clusters.<name>.resources.limits.cpu | string | No | - | CPU limit (e.g., 2000m ) |
clusters.<name>.maxConnections | string | No | "200" | Maximum number of connections |
clusters.<name>.sharedBuffers | string | No | "256MB" | Shared memory buffers |
clusters.<name>.effectiveCacheSize | string | No | "1GB" | Effective cache size |
clusters.<name>.maintenanceWorkMem | string | No | "64MB" | Maintenance work memory |
clusters.<name>.checkpointCompletionTarget | string | No | "0.9" | Checkpoint completion target |
clusters.<name>.walBuffers | string | No | "16MB" | WAL buffers |
clusters.<name>.defaultStatisticsTarget | string | No | "100" | Default statistics target |
clusters.<name>.randomPageCost | string | No | "1.1" | Random page cost |
clusters.<name>.effectiveIoConcurrency | string | No | "200" | Effective I/O concurrency |
clusters.<name>.workMem | string | No | "4MB" | Work memory per operation |
clusters.<name>.minWalSize | string | No | "1GB" | Minimum WAL size |
clusters.<name>.maxWalSize | string | No | "4GB" | Maximum WAL size |
clusters.<name>.parameters | object | No | {} | Additional custom PostgreSQL parameters |
clusters.<name>.monitoring.enabled | bool | No | false | Enable Prometheus monitoring |
clusters.<name>.backup.enabled | bool | No | false | Enable automated backups |
clusters.<name>.backup.schedule | string | No | "0 0 0 * * *" | Backup schedule (cron format) |
clusters.<name>.backup.retentionPolicy | string | No | "30d" | Backup retention policy |
clusters.<name>.backup.s3.bucket | string | Yes (if S3) | - | S3 bucket name for backups |
clusters.<name>.backup.s3.endpoint | string | Yes (if S3) | - | S3 endpoint URL |
clusters.<name>.backup.s3.region | string | No | - | S3 region |
clusters.<name>.backup.s3.accessKeyId | string | Yes (if S3) | - | S3 access key ID |
clusters.<name>.backup.s3.secretAccessKey | string | Yes (if S3) | - | S3 secret access key |
clusters.<name>.backup.s3.credentials.existingSecret | string | No | - | Existing secret (alternative to accessKeyId/secretAccessKey) |
clusters.<name>.initdb.postInitSQL | array | No | [] | Custom SQL statements after init |
Database Configuration¶
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
clusters.<name>.databases[].name | string | Yes | - | Database name |
clusters.<name>.databases[].owner | string | Yes | - | Database owner/user name |
clusters.<name>.databases[].targetNamespace | string | No | - | Target namespace for secret replication |
clusters.<name>.databases[].existingSecret | string | No | - | Use existing secret for credentials |
clusters.<name>.databases[].encoding | string | No | "UTF8" | Database encoding |
clusters.<name>.databases[].locale | string | No | "C" | Database locale |
How It Works¶
Database and User Creation¶
For each database defined in clusters.<name>.databases[]
:
- Database Resource: A CloudNativePG
Database
resource is created - User/Owner: A PostgreSQL user is automatically created with the
owner
name - Secret Generation: A Kubernetes Secret is created with connection details:
username
: The database ownerpassword
: Auto-generated secure passworddbname
: Database namehost
: Cluster service endpointport
: PostgreSQL port (5432)jdbc-url
: JDBC connection stringuri
: PostgreSQL URI connection string
Secret Naming¶
Secrets follow the naming pattern: <cluster-name>-<database-name>-app
Example: For cluster main
and database keycloak
, the secret is main-keycloak-app
Secret Replication¶
If secretNamespace
is specified for a database, the secret is automatically replicated to that namespace using Kubernetes secret reflection or a custom replication mechanism.
Use Cases¶
Microservices Consolidation¶
Instead of running separate PostgreSQL instances for each microservice:
clusters:
microservices:
enabled: true
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 100Gi
databases:
- name: auth-service
owner: auth
secretNamespace: auth
- name: user-service
owner: users
secretNamespace: users
- name: order-service
owner: orders
secretNamespace: orders
- name: payment-service
owner: payments
secretNamespace: payments
Multi-Tenant SaaS¶
Isolate tenant databases while sharing infrastructure:
clusters:
saas-prod:
enabled: true
instances: 5
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
storage:
size: 500Gi
databases:
- name: tenant-acme
owner: tenant_acme
- name: tenant-widgets
owner: tenant_widgets
- name: tenant-global
owner: tenant_global
Development/Staging/Production¶
Manage all environments from one chart:
clusters:
dev:
enabled: true
instances: 1
storage:
size: 10Gi
databases:
- name: app-dev
owner: dev
staging:
enabled: true
instances: 2
storage:
size: 50Gi
databases:
- name: app-staging
owner: staging
prod:
enabled: true
instances: 3
storage:
size: 200Gi
backup:
enabled: true
databases:
- name: app-prod
owner: prod
Troubleshooting¶
Check Cluster Status¶
Check Database Creation¶
View Generated Secrets¶
Check Operator Logs¶
Comparison with Official Charts¶
Feature | Official cluster Chart | This Chart |
---|---|---|
Cluster Management | ✅ | ✅ |
Multiple Databases | ❌ (one per deployment) | ✅ (many per cluster) |
Automatic Secrets | ❌ | ✅ |
Secret Replication | ❌ | ✅ |
Multi-Cluster | ❌ | ✅ |
Backup Configuration | ✅ | ✅ |
Monitoring | ✅ | ✅ |
Support & Professional Services¶
Community Support¶
For issues and questions about this Helm chart: - Open an issue in GitHub Issues - Start a discussion in GitHub Discussions
For CloudNativePG specific issues: - Visit the CloudNativePG GitHub repository - Check the CloudNativePG documentation
Professional Support¶
For professional support, consulting, custom development, or enterprise solutions, contact hello@encircle360.com
Disclaimer¶
⚠️ This chart is under active development and NOT production-ready.
This Helm chart is provided "AS IS" without warranty of any kind. encircle360 GmbH and the contributors: - Make no warranties about the completeness, reliability, or accuracy of this chart - Are not liable for any damages arising from the use of this chart - Strongly recommend thorough testing in non-production environments only - Do not recommend this chart for production use at this time
Use this chart at your own risk. For production-ready PostgreSQL solutions with SLA requirements, contact our professional support services at hello@encircle360.com
License¶
This chart is licensed under the Apache License 2.0. See LICENSE for details.
Default Values¶
For a complete list of configuration options, see the values.yaml file.