Skip to content

Commit 2dc648d

Browse files
authored
FIX: Migrate from Bitnami Postgres to CloudNativePG (#1042)
* replacement of bitnami postgres with cloudnative-pg chart * fix: wait for CloudNativePG CRDs * fixing cluster template * fixing DB init issue * fixing cluster teamplate from cloudnative-pg * optimizing cluster template * optimizing cluster template * optimizing cluster template * optimizing cluster template * fixing connections
1 parent ddc64da commit 2dc648d

File tree

9 files changed

+496
-49
lines changed

9 files changed

+496
-49
lines changed

src/test/config/kind/common-values.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ DC_APP_REPLACEME:
8282

8383
database:
8484
type: DB_TYPE_REPLACEME
85-
url: jdbc:postgresql://postgres:5432/DC_APP_REPLACEME
85+
url: jdbc:postgresql://DC_APP_REPLACEME-db-rw:5432/DC_APP_REPLACEME
8686
driver: org.postgresql.Driver
8787
credentials:
88-
secretName: DC_APP_REPLACEME-db-creds
88+
secretName: DC_APP_REPLACEME-db-credentials
8989

9090
# nfs volume provisioner and nfs server are deployed to KinD cluster
9191
# thus we can create PVCs and expect them to be bound to PVs that provisioner will create
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# CloudNativePG Test Infrastructure
2+
3+
Configuration files for deploying PostgreSQL databases using CloudNativePG operator in test environments.
4+
5+
## Overview
6+
7+
CloudNativePG operator is used to manage PostgreSQL clusters for Data Center application testing.
8+
9+
## Files
10+
11+
### `operator-values.yaml`
12+
Configuration for the CloudNativePG operator Helm chart. This includes:
13+
- Resource limits suitable for test environments
14+
- Security context configuration
15+
- Monitoring settings (disabled for tests)
16+
- RBAC and service account settings
17+
18+
### `cluster-template.yaml`
19+
Template for creating PostgreSQL clusters. Features:
20+
- Single instance configuration for test environments
21+
- PostgreSQL 16.2 (matching previous Bitnami version)
22+
- Resource limits: 256Mi-1Gi memory, 100m-1000m CPU
23+
- Ephemeral storage (1Gi) suitable for tests
24+
- Performance optimizations for test environments (fsync disabled)
25+
- Database and user creation via bootstrap configuration
26+
27+
### `init-scripts/init-db.sql`
28+
Database initialization script that:
29+
- Creates necessary PostgreSQL extensions
30+
- Sets up proper permissions for application users
31+
- Creates health check functions
32+
- Provides initialization logging
33+
34+
## Usage
35+
36+
The CloudNativePG deployment is handled automatically by the test scripts:
37+
38+
### Local Testing (KinD)
39+
```bash
40+
# Deploy PostgreSQL cluster for Jira
41+
DC_APP=jira source src/test/scripts/kind/deploy_app.sh
42+
deploy_postgres
43+
```
44+
45+
### CI/CD Testing
46+
The GitHub Actions workflows automatically use the updated deployment scripts.
47+
48+
## Database Connection
49+
50+
Applications connect to the database using:
51+
- **Service Name**: `{app-name}-db-rw` (read-write) or `{app-name}-db-ro` (read-only)
52+
- **Port**: 5432
53+
- **Database**: Same as application name
54+
- **Credentials**: Stored in `{app-name}-db-credentials` secret
55+
56+
Example connection string for Jira:
57+
```
58+
jdbc:postgresql://jira-db-rw:5432/jira
59+
```
60+
61+
## Monitoring
62+
63+
Monitoring is disabled in test environments to reduce resource usage. For production deployments, you can enable:
64+
- Pod monitors for Prometheus integration
65+
- Grafana dashboards
66+
- Custom monitoring queries
67+
68+
## Troubleshooting
69+
70+
### Check Operator Status
71+
```bash
72+
kubectl get deployment cnpg-operator-controller-manager -n cnpg-system
73+
```
74+
75+
### Check Cluster Status
76+
```bash
77+
kubectl get cluster {app-name}-db -n atlassian
78+
kubectl describe cluster {app-name}-db -n atlassian
79+
```
80+
81+
### Check Pod Status
82+
```bash
83+
kubectl get pods -l cnpg.io/cluster={app-name}-db -n atlassian
84+
```
85+
86+
### Access Database
87+
```bash
88+
# Get primary pod name
89+
PRIMARY_POD=$(kubectl get pods -n atlassian -l cnpg.io/cluster={app-name}-db,role=primary -o jsonpath='{.items[0].metadata.name}')
90+
91+
# Connect to database
92+
kubectl exec -it ${PRIMARY_POD} -n atlassian -- psql -U {app-name} -d {app-name}
93+
```
94+
95+
## Performance Considerations
96+
97+
The test configuration includes several performance optimizations:
98+
- `fsync=off` - Disables synchronous writes (safe for ephemeral test data)
99+
- `synchronous_commit=off` - Allows asynchronous commits
100+
- `full_page_writes=off` - Reduces I/O for test workloads
101+
102+
**Warning**: These settings are only suitable for test environments with ephemeral data.
103+
104+
## Migration Notes
105+
106+
Key differences from Bitnami PostgreSQL:
107+
1. **Service Names**: Changed from `postgres` to `{app-name}-db-rw`
108+
2. **Pod Names**: Changed from `postgres-0` to `{app-name}-db-1`
109+
3. **Operator Management**: Clusters are managed by the CloudNativePG operator
110+
4. **Configuration**: Uses Kubernetes CRDs instead of Helm values
111+
5. **Monitoring**: Native Prometheus integration available
112+
113+
## Resources
114+
115+
- [CloudNativePG Documentation](https://cloudnative-pg.io/documentation/)
116+
- [CloudNativePG Helm Chart](https://github.com/cloudnative-pg/charts)
117+
- [PostgreSQL Configuration Reference](https://www.postgresql.org/docs/current/runtime-config.html)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: ${DC_APP}-db
5+
namespace: ${NAMESPACE}
6+
labels:
7+
app.kubernetes.io/name: postgresql
8+
app.kubernetes.io/instance: ${DC_APP}-db
9+
app.kubernetes.io/component: database
10+
app.kubernetes.io/part-of: ${DC_APP}
11+
spec:
12+
instances: 1
13+
imageName: ghcr.io/cloudnative-pg/postgresql:16.2
14+
15+
resources:
16+
requests:
17+
memory: "64Mi"
18+
cpu: "25m"
19+
limits:
20+
memory: "256Mi"
21+
cpu: "250m"
22+
23+
storage:
24+
size: 256Mi
25+
storageClass: standard
26+
27+
bootstrap:
28+
initdb:
29+
database: ${DC_APP}
30+
owner: ${DC_APP}
31+
secret:
32+
name: ${DC_APP}-db-credentials
33+
postInitSQL:
34+
- "ALTER USER ${DC_APP} CREATEDB;"
35+
- "ALTER USER ${DC_APP} WITH PASSWORD '${DC_APP}pwd' VALID UNTIL 'infinity';"
36+
37+
postgresql:
38+
parameters:
39+
max_connections: "100"
40+
shared_buffers: "32MB"
41+
work_mem: "1MB"
42+
maintenance_work_mem: "16MB"
43+
effective_cache_size: "128MB"
44+
fsync: "off"
45+
synchronous_commit: "off"
46+
full_page_writes: "off"
47+
# WAL configuration
48+
wal_level: "replica"
49+
max_wal_senders: "2"
50+
min_wal_size: "32MB"
51+
max_wal_size: "64MB"
52+
checkpoint_timeout: "15min"
53+
# Authentication
54+
password_encryption: "scram-sha-256"
55+
# Reduce logging
56+
log_statement: "none"
57+
log_min_duration_statement: "-1"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-- Database initialization script for CloudNativePG
2+
3+
-- Create additional extensions that might be needed by DC apps
4+
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
5+
CREATE EXTENSION IF NOT EXISTS pg_trgm;
6+
7+
-- Grant additional permissions to the application user
8+
GRANT CREATE ON SCHEMA public TO ${DC_APP};
9+
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${DC_APP};
10+
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${DC_APP};
11+
12+
-- Set default privileges for future objects
13+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ${DC_APP};
14+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${DC_APP};
15+
16+
-- Create a simple health check function
17+
CREATE OR REPLACE FUNCTION health_check() RETURNS text AS $$
18+
BEGIN
19+
RETURN 'OK';
20+
END;
21+
$$ LANGUAGE plpgsql;
22+
23+
-- Log initialization completion
24+
DO $$
25+
BEGIN
26+
RAISE NOTICE 'Database initialization completed for application: %', '${DC_APP}';
27+
END $$;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# CloudNativePG Operator configuration optimized for CI/test environments
2+
3+
replicaCount: 1
4+
5+
image:
6+
repository: ghcr.io/cloudnative-pg/cloudnative-pg
7+
pullPolicy: IfNotPresent
8+
tag: "1.27.0"
9+
10+
# Operator configuration optimized for CI
11+
config:
12+
create: true
13+
name: cnpg-controller-manager-config
14+
secret: false
15+
clusterWide: true
16+
data:
17+
INHERITED_ANNOTATIONS: "categories"
18+
INHERITED_LABELS: "environment,workload,app"
19+
# Reduce concurrent reconciles for CI
20+
maxConcurrentReconciles: 3
21+
22+
# Disable monitoring for CI
23+
monitoring:
24+
podMonitorEnabled: false
25+
grafanaDashboard:
26+
create: false
27+
28+
# Minimal resource limits for CI
29+
resources:
30+
limits:
31+
cpu: 100m
32+
memory: 128Mi
33+
requests:
34+
cpu: 50m
35+
memory: 64Mi
36+
37+
# Security context
38+
containerSecurityContext:
39+
allowPrivilegeEscalation: false
40+
readOnlyRootFilesystem: true
41+
runAsUser: 10001
42+
runAsGroup: 10001
43+
seccompProfile:
44+
type: RuntimeDefault
45+
capabilities:
46+
drop:
47+
- "ALL"
48+
49+
podSecurityContext:
50+
runAsNonRoot: true
51+
seccompProfile:
52+
type: RuntimeDefault
53+
54+
# Service account
55+
serviceAccount:
56+
create: true
57+
58+
# RBAC
59+
rbac:
60+
create: true
61+
aggregateClusterRoles: false
62+
63+
# CRDs
64+
crds:
65+
create: true
66+
67+
# Webhook configuration with faster probes
68+
webhook:
69+
port: 9443
70+
mutating:
71+
create: true
72+
failurePolicy: Fail
73+
validating:
74+
create: true
75+
failurePolicy: Fail
76+
livenessProbe:
77+
initialDelaySeconds: 1
78+
readinessProbe:
79+
initialDelaySeconds: 1
80+
startupProbe:
81+
failureThreshold: 3
82+
periodSeconds: 2

src/test/infrastructure/postgres/postgres-values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# This file contains overrides for the bitnami/postgresql helm chart, suitable for deployment into the KITT clusters.
1+
# DEPRECATED: This file is no longer used. CloudNativePG is now used instead of Bitnami PostgreSQL.
2+
# See src/test/infrastructure/cloudnativepg/ for the new configuration files.
23

34
primary:
45
podAnnotations:
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package test;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.TestInfo;
6+
import test.helm.Helm;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
/**
11+
* Tests for CloudNativePG integration and database connectivity
12+
* These tests verify that the database configuration is compatible with CloudNativePG
13+
*/
14+
class CloudNativePGTest {
15+
private Helm helm;
16+
17+
@BeforeEach
18+
void initHelm(TestInfo testInfo) {
19+
helm = new Helm(testInfo);
20+
}
21+
22+
@Test
23+
void test_cloudnativepg_service_name_format() {
24+
// Test that the database URL format is compatible with CloudNativePG service naming
25+
// CloudNativePG creates services with pattern: {cluster-name}-rw for read-write
26+
// and {cluster-name}-ro for read-only
27+
28+
String clusterName = "jira-db";
29+
String expectedRwService = clusterName + "-rw";
30+
String expectedRoService = clusterName + "-ro";
31+
32+
assertThat(expectedRwService).isEqualTo("jira-db-rw");
33+
assertThat(expectedRoService).isEqualTo("jira-db-ro");
34+
}
35+
36+
@Test
37+
void test_postgresql_connection_string_format() {
38+
// Test that the JDBC URL format is correct for PostgreSQL
39+
String host = "jira-db-rw";
40+
String port = "5432";
41+
String database = "jira";
42+
String expectedUrl = String.format("jdbc:postgresql://%s:%s/%s", host, port, database);
43+
44+
assertThat(expectedUrl).isEqualTo("jdbc:postgresql://jira-db-rw:5432/jira");
45+
}
46+
47+
@Test
48+
void test_database_credentials_secret_format() {
49+
// Test that the secret format is compatible with CloudNativePG expectations
50+
String appName = "jira";
51+
String expectedSecretName = appName + "-db-credentials";
52+
53+
assertThat(expectedSecretName).isEqualTo("jira-db-credentials");
54+
}
55+
56+
@Test
57+
void test_cluster_naming_convention() {
58+
// Test that cluster names follow the expected pattern
59+
String appName = "confluence";
60+
String expectedClusterName = appName + "-db";
61+
62+
assertThat(expectedClusterName).isEqualTo("confluence-db");
63+
}
64+
}

0 commit comments

Comments
 (0)