From 5768d9b92d929a5dcffb7392df4bbfc456b53e01 Mon Sep 17 00:00:00 2001 From: William Hearn Date: Mon, 6 Apr 2026 20:33:06 -0400 Subject: [PATCH] feat(crunchydb): Port integration with crunchyDB --- charts/drupal/conf/settings.d10.php | 12 ++ charts/drupal/conf/settings.d11.php | 12 ++ charts/drupal/conf/settings.d9.php | 12 ++ charts/drupal/templates/_helpers.tpl | 2 +- .../job/post-install-site-install.yaml | 2 + .../templates/operator/PostgresCluster.yaml | 164 ++++++++++++++++++ charts/drupal/values.yaml | 42 +++++ 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 charts/drupal/templates/operator/PostgresCluster.yaml diff --git a/charts/drupal/conf/settings.d10.php b/charts/drupal/conf/settings.d10.php index d830aaf..ec90a96 100644 --- a/charts/drupal/conf/settings.d10.php +++ b/charts/drupal/conf/settings.d10.php @@ -156,6 +156,18 @@ 'driver' => 'pgsql', 'collation' => 'utf8mb4_general_ci', ]; +{{- else if .Values.postgresOperator.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.postgresOperator.auth.database | quote }}, + 'username' => {{ .Values.postgresOperator.auth.username | quote }}, + 'password' => getenv('POSTGRES_PASSWORD') ?: '', + 'host' => '{{ .Release.Name }}-postgres-cluster-pgbouncer', + 'port' => {{ .Values.postgresOperator.port | quote }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\pgsql', + 'driver' => 'pgsql', + 'collation' => 'utf8mb4_general_ci', +]; {{- end }} /** diff --git a/charts/drupal/conf/settings.d11.php b/charts/drupal/conf/settings.d11.php index d830aaf..ec90a96 100644 --- a/charts/drupal/conf/settings.d11.php +++ b/charts/drupal/conf/settings.d11.php @@ -156,6 +156,18 @@ 'driver' => 'pgsql', 'collation' => 'utf8mb4_general_ci', ]; +{{- else if .Values.postgresOperator.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.postgresOperator.auth.database | quote }}, + 'username' => {{ .Values.postgresOperator.auth.username | quote }}, + 'password' => getenv('POSTGRES_PASSWORD') ?: '', + 'host' => '{{ .Release.Name }}-postgres-cluster-pgbouncer', + 'port' => {{ .Values.postgresOperator.port | quote }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\pgsql', + 'driver' => 'pgsql', + 'collation' => 'utf8mb4_general_ci', +]; {{- end }} /** diff --git a/charts/drupal/conf/settings.d9.php b/charts/drupal/conf/settings.d9.php index fff7d86..3d38207 100644 --- a/charts/drupal/conf/settings.d9.php +++ b/charts/drupal/conf/settings.d9.php @@ -156,6 +156,18 @@ 'driver' => 'pgsql', 'collation' => 'utf8mb4_general_ci', ]; +{{- else if .Values.postgresOperator.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.postgresOperator.auth.database | quote }}, + 'username' => {{ .Values.postgresOperator.auth.username | quote }}, + 'password' => getenv('POSTGRES_PASSWORD') ?: '', + 'host' => '{{ .Release.Name }}-postgres-cluster-pgbouncer', + 'port' => {{ .Values.postgresOperator.port | quote }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\pgsql', + 'driver' => 'pgsql', + 'collation' => 'utf8mb4_general_ci', +]; {{- end }} /** diff --git a/charts/drupal/templates/_helpers.tpl b/charts/drupal/templates/_helpers.tpl index 4e11c0a..c600eb8 100644 --- a/charts/drupal/templates/_helpers.tpl +++ b/charts/drupal/templates/_helpers.tpl @@ -86,7 +86,7 @@ Create common environment variables for Drupal secretKeyRef: name: "{{ .Release.Name }}-mysql" key: mysql-password -{{- else if .Values.postgresql.enabled }} +{{- else if or .Values.postgresql.enabled .Values.postgresOperator.enabled }} - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: diff --git a/charts/drupal/templates/job/post-install-site-install.yaml b/charts/drupal/templates/job/post-install-site-install.yaml index 794878d..8a10d48 100644 --- a/charts/drupal/templates/job/post-install-site-install.yaml +++ b/charts/drupal/templates/job/post-install-site-install.yaml @@ -175,6 +175,8 @@ spec: --db-url="mysql://{{ .Values.mysql.auth.username }}:$MYSQL_PASSWORD@{{ .Release.Name }}-mysql:{{ .Values.mysql.primary.service.ports.mysql }}/{{ .Values.mysql.auth.database }}" \ {{- else if .Values.postgresql.enabled }} --db-url="pgsql://{{ .Values.postgresql.auth.username }}:$POSTGRES_PASSWORD@{{ .Release.Name }}-postgresql:{{ .Values.postgresql.primary.service.ports.postgresql }}/{{ .Values.postgresql.auth.database }}" \ + {{- else if .Values.postgresOperator.enabled }} + --db-url="pgsql://{{ .Values.postgresOperator.auth.username }}:$POSTGRES_PASSWORD@{{ .Release.Name }}-postgres-cluster-pgbouncer:{{ .Values.postgresOperator.port }}/{{ .Values.postgresOperator.auth.database }}" \ {{- end }} --account-name={{ .Values.drupal.username }} \ --account-pass=$DRUPAL_ADMIN_PASSWORD \ diff --git a/charts/drupal/templates/operator/PostgresCluster.yaml b/charts/drupal/templates/operator/PostgresCluster.yaml new file mode 100644 index 0000000..376cc87 --- /dev/null +++ b/charts/drupal/templates/operator/PostgresCluster.yaml @@ -0,0 +1,164 @@ +{{- if .Values.postgresOperator.enabled }} +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: {{ .Release.Name }}-postgres-cluster + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + imagePullPolicy: IfNotPresent + postgresVersion: {{ .Values.postgresOperator.version }} + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + instances: + - name: {{ .Values.postgresOperator.instances.name }} + replicas: {{ .Values.postgresOperator.instances.replicas }} + {{- if .Values.postgresOperator.instances.resources }} + resources: + {{- toYaml .Values.postgresOperator.instances.resources | nindent 8 }} + {{- end }} + sidecars: + replicaCertCopy: + {{- if .Values.postgresOperator.instances.sidecars.resources }} + resources: + {{- toYaml .Values.postgresOperator.instances.sidecars.resources | nindent 12 }} + {{- end }} + dataVolumeClaimSpec: + accessModes: + - {{ .Values.postgresOperator.persistence.accessMode }} + resources: + requests: + storage: {{ .Values.postgresOperator.persistence.size }} + storageClassName: {{ .Values.postgresOperator.persistence.storageClass }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: {{ .Release.Name }}-postgres-cluster + postgres-operator.crunchydata.com/instance-set: {{ .Values.postgresOperator.instances.name }} + users: + - name: {{ .Values.postgresOperator.auth.username }} + databases: + - {{ .Values.postgresOperator.auth.database }} + options: "CREATEROLE" + - name: postgres + databases: + - {{ .Values.postgresOperator.auth.database }} + backups: + pgbackrest: + global: + repo1-retention-full: "{{ .Values.postgresOperator.retention.count }}" + repo1-retention-full-type: {{ .Values.postgresOperator.retention.type }} + manual: + repoName: repo1 + options: + - --type=full + {{- if .Values.postgresOperator.backups.restore.options }} + restore: + enabled: true + repoName: repo1 + options: + {{- toYaml .Values.postgresOperator.backups.restore.options | nindent 10 }} + {{- end }} + repos: + - name: repo1 + {{- if .Values.postgresOperator.retention.schedules }} + schedules: + {{- toYaml .Values.postgresOperator.retention.schedules | nindent 12 }} + {{- end }} + volume: + volumeClaimSpec: + accessModes: + - {{ .Values.postgresOperator.backups.persistence.accessMode }} + resources: + requests: + storage: {{ .Values.postgresOperator.backups.persistence.size }} + storageClassName: {{ .Values.postgresOperator.backups.persistence.storageClass }} + repoHost: + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + sidecars: + pgbackrest: + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + pgbackrestConfig: + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + patroni: + dynamicConfiguration: + postgresql: + pg_hba: + - host all all 0.0.0.0/0 scram-sha-256 + - host all all ::1/128 scram-sha-256 + parameters: + # https://pgtune.leopard.in.ua/ + # DB Version: 16 + # OS Type: linux + # DB Type: mixed + # Total Memory (RAM): 2 GB + # CPUs num: 2 + # Connections num: 200 + # Data Storage: ssd + max_connections: 100 + shared_buffers: 512MB + effective_cache_size: 1536MB + maintenance_work_mem: 128MB + checkpoint_completion_target: 0.9 + wal_buffers: 16MB + default_statistics_target: 100 + random_page_cost: 1.1 + effective_io_concurrency: 200 + work_mem: 8MB + huge_pages: off + min_wal_size: 1GB + max_wal_size: 4GB + proxy: + pgBouncer: + config: + global: + client_tls_sslmode: disable + replicas: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: {{ include "drupal.fullname" . }}-postgres-cluster + postgres-operator.crunchydata.com/role: pgbouncer +{{- end }} diff --git a/charts/drupal/values.yaml b/charts/drupal/values.yaml index f6a583d..56718c3 100644 --- a/charts/drupal/values.yaml +++ b/charts/drupal/values.yaml @@ -821,6 +821,48 @@ proxysql: serverVersion: "5.7.28" stackSize: 1048576 +postgresOperator: + enabled: false + version: 15 + auth: + database: drupal + username: drupal + usePasswordFiles: true + port: 5432 + instances: + name: drupal + replicas: 1 + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1000m + memory: 2048Mi + sidecars: + resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 50m + memory: 64Mi + retention: + count: 5 + type: time + schedules: + full: 0 8 * * * + incremental: 0 0,4,12,16,20 * * * + persistence: + # storageClass: + accessMode: ReadWriteOnce + size: 6Gi + backups: + persistence: + # storageClass: + accessMode: ReadWriteOnce + size: 2Gi + ## Configuration values for the Redis dependency sub-chart ## ref: https://github.com/valkey-io/valkey-helm/blob/main/README.md redis: