diff --git a/ai-telemetry/base/externalsecrets/kustomization.yaml b/ai-telemetry/base/externalsecrets/kustomization.yaml index d4fc04ad..89620296 100644 --- a/ai-telemetry/base/externalsecrets/kustomization.yaml +++ b/ai-telemetry/base/externalsecrets/kustomization.yaml @@ -3,3 +3,5 @@ kind: Kustomization resources: - solr-secret.yaml + - postgresql-ha-secret.yaml + - postgresql-ha-pgpool-secret.yaml diff --git a/ai-telemetry/base/externalsecrets/postgresql-ha-pgpool-secret.yaml b/ai-telemetry/base/externalsecrets/postgresql-ha-pgpool-secret.yaml new file mode 100644 index 00000000..ee634332 --- /dev/null +++ b/ai-telemetry/base/externalsecrets/postgresql-ha-pgpool-secret.yaml @@ -0,0 +1,15 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: postgresql-ha-pgpool-secret + namespace: postgresql-ha +spec: + refreshInterval: 15s + secretStoreRef: + name: nerc-cluster-secrets + kind: ClusterSecretStore + target: + name: postgresql-ha-pgpool + dataFrom: + - extract: + key: $ENV/$CLUSTER/ai-telemetry/postgresql-ha-pgpool diff --git a/ai-telemetry/base/externalsecrets/postgresql-ha-secret.yaml b/ai-telemetry/base/externalsecrets/postgresql-ha-secret.yaml new file mode 100644 index 00000000..2f8beccf --- /dev/null +++ b/ai-telemetry/base/externalsecrets/postgresql-ha-secret.yaml @@ -0,0 +1,15 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: postgresql-ha-secret + namespace: postgresql-ha +spec: + refreshInterval: 15s + secretStoreRef: + name: nerc-cluster-secrets + kind: ClusterSecretStore + target: + name: postgresql-ha-secret + dataFrom: + - extract: + key: $ENV/$CLUSTER/ai-telemetry/postgresql-ha diff --git a/ai-telemetry/base/kustomization.yaml b/ai-telemetry/base/kustomization.yaml index 07e19c6a..4de304cf 100644 --- a/ai-telemetry/base/kustomization.yaml +++ b/ai-telemetry/base/kustomization.yaml @@ -4,3 +4,4 @@ resources: - externalsecrets - zookeeper - solr +- postgresql-ha diff --git a/ai-telemetry/base/postgresql-ha/configmap.yaml b/ai-telemetry/base/postgresql-ha/configmap.yaml new file mode 100644 index 00000000..a737ace8 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/configmap.yaml @@ -0,0 +1,129 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgresql-ha-postgresql-hooks-scripts + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql +data: + pre-stop.sh: |- + #!/bin/bash + set -o errexit + set -o pipefail + set -o nounset + + # Debug section + exec 3>&1 + exec 4>&2 + + # Process input parameters + MIN_DELAY_AFTER_PG_STOP_SECONDS=$1 + + # Load Libraries + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/librepmgr.sh + + # Load PostgreSQL & repmgr environment variables + . /opt/bitnami/scripts/postgresql-env.sh + + # Auxiliary functions + is_new_primary_ready() { + return_value=1 + currenty_primary_node="$(repmgr_get_primary_node)" + currenty_primary_host="$(echo $currenty_primary_node | awk '{print $1}')" + + info "$currenty_primary_host != $REPMGR_NODE_NETWORK_NAME" + if [[ $(echo $currenty_primary_node | wc -w) -eq 2 ]] && [[ "$currenty_primary_host" != "$REPMGR_NODE_NETWORK_NAME" ]]; then + info "New primary detected, leaving the cluster..." + return_value=0 + else + info "Waiting for a new primary to be available..." + fi + return $return_value + } + + export MODULE="pre-stop-hook" + + if [[ "${BITNAMI_DEBUG}" == "true" ]]; then + info "Bash debug is on" + else + info "Bash debug is off" + exec 1>/dev/null + exec 2>/dev/null + fi + + postgresql_enable_nss_wrapper + + # Prepare env vars for managing roles + readarray -t primary_node < <(repmgr_get_upstream_node) + primary_host="${primary_node[0]}" + + # Stop postgresql for graceful exit. + PG_STOP_TIME=$EPOCHSECONDS + postgresql_stop + + if [[ -z "$primary_host" ]] || [[ "$primary_host" == "$REPMGR_NODE_NETWORK_NAME" ]]; then + info "Primary node need to wait for a new primary node before leaving the cluster" + retry_while is_new_primary_ready 10 5 + else + info "Standby node doesn't need to wait for a new primary switchover. Leaving the cluster" + fi + + # Make sure pre-stop hook waits at least 25 seconds after stop of PG to make sure PGPOOL detects node is down. + # default terminationGracePeriodSeconds=30 seconds + PG_STOP_DURATION=$(($EPOCHSECONDS - $PG_STOP_TIME)) + if (( $PG_STOP_DURATION < $MIN_DELAY_AFTER_PG_STOP_SECONDS )); then + WAIT_TO_PG_POOL_TIME=$(($MIN_DELAY_AFTER_PG_STOP_SECONDS - $PG_STOP_DURATION)) + info "PG stopped including primary switchover in $PG_STOP_DURATION. Waiting additional $WAIT_TO_PG_POOL_TIME seconds for PG pool" + sleep $WAIT_TO_PG_POOL_TIME + fi + + readiness-probe.sh: |- + #!/bin/bash + set -o errexit + set -o pipefail + set -o nounset + + # Debug section + exec 3>&1 + exec 4>&2 + + # Load Libraries + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libpostgresql.sh + + # Load PostgreSQL & repmgr environment variables + . /opt/bitnami/scripts/postgresql-env.sh + + # Process input parameters + MIN_DELAY_AFTER_POD_READY_FIRST_TIME=$1 + TMP_FIRST_READY_FILE_TS="/tmp/ts-first-ready.mark" + TMP_DELAY_APPLIED_FILE="/tmp/delay-applied.mark" + + DB_CHECK_RESULT=$(echo "SELECT 1" | postgresql_execute_print_output "$POSTGRESQL_DATABASE" "$POSTGRESQL_USERNAME" "$POSTGRESQL_PASSWORD" "-h 127.0.0.1 -tA" || echo "command failed") + if [[ "$DB_CHECK_RESULT" == "1" ]]; then + if [[ ! -f "$TMP_DELAY_APPLIED_FILE" ]]; then + # DB up, but initial readiness delay not applied + if [[ -f "$TMP_FIRST_READY_FILE_TS" ]]; then + # calculate delay from the first readiness success + FIRST_READY_TS=$(cat $TMP_FIRST_READY_FILE_TS) + CURRENT_DELAY_SECONDS=$(($EPOCHSECONDS - $FIRST_READY_TS)) + if (( $CURRENT_DELAY_SECONDS > $MIN_DELAY_AFTER_POD_READY_FIRST_TIME )); then + # minimal delay of the first readiness state passed - report success and mark delay as applied + touch "$TMP_DELAY_APPLIED_FILE" + else + # minimal delay of the first readiness state not reached yet - report failure + exit 1 + fi + else + # first ever readiness test success - store timestamp and report failure + echo $EPOCHSECONDS > $TMP_FIRST_READY_FILE_TS + exit 1 + fi + fi + else + # DB test failed - report failure + exit 1 + fi diff --git a/ai-telemetry/base/postgresql-ha/deployment.yaml b/ai-telemetry/base/postgresql-ha/deployment.yaml new file mode 100644 index 00000000..5f6c3073 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/deployment.yaml @@ -0,0 +1,143 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgresql-ha-pgpool + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool + template: + metadata: + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool + spec: + automountServiceAccountToken: false + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool + topologyKey: kubernetes.io/hostname + weight: 1 + serviceAccountName: postgresql-ha + # Auxiliary vars to populate environment variables + containers: + - name: pgpool + image: docker.io/bitnami/pgpool:4.5.4-debian-12-r2 + imagePullPolicy: "IfNotPresent" + env: + - name: BITNAMI_DEBUG + value: "false" + - name: PGPOOL_BACKEND_NODES + value: 0:postgresql-ha-postgresql-0.postgresql-ha-postgresql-headless:5432,1:postgresql-ha-postgresql-1.postgresql-ha-postgresql-headless:5432,2:postgresql-ha-postgresql-2.postgresql-ha-postgresql-headless:5432, + - name: PGPOOL_SR_CHECK_USER + value: "repmgr" + - name: PGPOOL_SR_CHECK_PASSWORD + valueFrom: + secretKeyRef: + name: postgresql-ha-secret + key: repmgr-password + - name: PGPOOL_SR_CHECK_DATABASE + value: "postgres" + - name: PGPOOL_ENABLE_LDAP + value: "no" + - name: PGPOOL_POSTGRES_USERNAME + value: "postgres" + - name: PGPOOL_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgresql-ha-secret + key: password + - name: PGPOOL_ADMIN_USERNAME + value: "admin" + - name: PGPOOL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: postgresql-ha-pgpool + key: admin-password + - name: PGPOOL_AUTHENTICATION_METHOD + value: "scram-sha-256" + - name: PGPOOL_ENABLE_LOAD_BALANCING + value: "yes" + - name: PGPOOL_DISABLE_LOAD_BALANCE_ON_WRITE + value: "transaction" + - name: PGPOOL_ENABLE_LOG_CONNECTIONS + value: "no" + - name: PGPOOL_ENABLE_LOG_HOSTNAME + value: "yes" + - name: PGPOOL_ENABLE_LOG_PER_NODE_STATEMENT + value: "no" + - name: PGPOOL_RESERVED_CONNECTIONS + value: '1' + - name: PGPOOL_CHILD_LIFE_TIME + value: "" + - name: PGPOOL_ENABLE_TLS + value: "no" + - name: PGPOOL_HEALTH_CHECK_PSQL_TIMEOUT + value: "6" + envFrom: + ports: + - name: postgresql + containerPort: 5432 + protocol: TCP + livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + exec: + command: + - /opt/bitnami/scripts/pgpool/healthcheck.sh + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + exec: + command: + - bash + - -ec + - 'PGPASSWORD=$PGPOOL_POSTGRES_PASSWORD psql -U "postgres" -d "postgres" -h /opt/bitnami/pgpool/tmp -tA -c "SELECT 1" >/dev/null' + resources: + limits: + cpu: 1 + ephemeral-storage: 2Gi + memory: 1Gi + requests: + cpu: 500m + ephemeral-storage: 100Mi + memory: 100Mi + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/etc + subPath: app-etc-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/pgpool/logs + subPath: app-logs-dir + volumes: + - name: empty-dir + emptyDir: {} diff --git a/ai-telemetry/base/postgresql-ha/kustomization.yaml b/ai-telemetry/base/postgresql-ha/kustomization.yaml new file mode 100644 index 00000000..b0211882 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/kustomization.yaml @@ -0,0 +1,16 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: postgresql-ha +resources: +- configmap.yaml +- deployment.yaml +- networkpolicy-pgpool.yaml +- networkpolicy.yaml +- pdb-pgpool.yaml +- pdb-witness.yaml +- pdb.yaml +- service-headless.yaml +- service-pgpool.yaml +- service.yaml +- serviceaccount.yaml +- statefulset.yaml diff --git a/ai-telemetry/base/postgresql-ha/networkpolicy-pgpool.yaml b/ai-telemetry/base/postgresql-ha/networkpolicy-pgpool.yaml new file mode 100644 index 00000000..0600685d --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/networkpolicy-pgpool.yaml @@ -0,0 +1,23 @@ +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: postgresql-ha-pgpool + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool + role: data +spec: + podSelector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool + policyTypes: + - Ingress + - Egress + egress: + - {} + ingress: + - ports: + - port: 5432 diff --git a/ai-telemetry/base/postgresql-ha/networkpolicy.yaml b/ai-telemetry/base/postgresql-ha/networkpolicy.yaml new file mode 100644 index 00000000..8024b932 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/networkpolicy.yaml @@ -0,0 +1,23 @@ +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: postgresql-ha-postgresql + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data +spec: + podSelector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + policyTypes: + - Ingress + - Egress + egress: + - {} + ingress: + - ports: + - port: 5432 diff --git a/ai-telemetry/base/postgresql-ha/pdb-pgpool.yaml b/ai-telemetry/base/postgresql-ha/pdb-pgpool.yaml new file mode 100644 index 00000000..06163b7f --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/pdb-pgpool.yaml @@ -0,0 +1,15 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: postgresql-ha-pgpool + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool diff --git a/ai-telemetry/base/postgresql-ha/pdb-witness.yaml b/ai-telemetry/base/postgresql-ha/pdb-witness.yaml new file mode 100644 index 00000000..036c2883 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/pdb-witness.yaml @@ -0,0 +1,17 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: postgresql-ha-postgresql-witness + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: witness +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: witness diff --git a/ai-telemetry/base/postgresql-ha/pdb.yaml b/ai-telemetry/base/postgresql-ha/pdb.yaml new file mode 100644 index 00000000..73cd0d5c --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/pdb.yaml @@ -0,0 +1,15 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: postgresql-ha-postgresql + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql diff --git a/ai-telemetry/base/postgresql-ha/service-headless.yaml b/ai-telemetry/base/postgresql-ha/service-headless.yaml new file mode 100644 index 00000000..5c2a42af --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/service-headless.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql-ha-postgresql-headless + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: false + ports: + - name: "postgresql" + port: 5432 + targetPort: postgresql + protocol: TCP + selector: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data diff --git a/ai-telemetry/base/postgresql-ha/service-pgpool.yaml b/ai-telemetry/base/postgresql-ha/service-pgpool.yaml new file mode 100644 index 00000000..51496041 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/service-pgpool.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql-ha-pgpool + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool +spec: + type: ClusterIP + sessionAffinity: None + ports: + - name: "postgresql" + port: 5432 + targetPort: postgresql + protocol: TCP + selector: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: pgpool diff --git a/ai-telemetry/base/postgresql-ha/service.yaml b/ai-telemetry/base/postgresql-ha/service.yaml new file mode 100644 index 00000000..2f320cd5 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql-ha-postgresql + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql +spec: + type: ClusterIP + ports: + - name: "postgresql" + port: 5432 + targetPort: postgresql + protocol: TCP + selector: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data diff --git a/ai-telemetry/base/postgresql-ha/serviceaccount.yaml b/ai-telemetry/base/postgresql-ha/serviceaccount.yaml new file mode 100644 index 00000000..89e653c7 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/serviceaccount.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: postgresql-ha + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha +automountServiceAccountToken: false diff --git a/ai-telemetry/base/postgresql-ha/statefulset.yaml b/ai-telemetry/base/postgresql-ha/statefulset.yaml new file mode 100644 index 00000000..a6af7234 --- /dev/null +++ b/ai-telemetry/base/postgresql-ha/statefulset.yaml @@ -0,0 +1,225 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgresql-ha-postgresql + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data +spec: + replicas: 3 + podManagementPolicy: "Parallel" + serviceName: postgresql-ha-postgresql-headless + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data + template: + metadata: + labels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + role: data + spec: + automountServiceAccountToken: false + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: postgresql-ha + app.kubernetes.io/name: postgresql-ha + app.kubernetes.io/component: postgresql + topologyKey: kubernetes.io/hostname + weight: 1 + serviceAccountName: postgresql-ha + hostNetwork: false + hostIPC: false + containers: + - name: postgresql + image: docker.io/bitnami/postgresql-repmgr:16.4.0-debian-12-r27 + imagePullPolicy: "IfNotPresent" + lifecycle: + preStop: + exec: + command: + - /pre-stop.sh + - "25" + # Auxiliary vars to populate environment variables + env: + - name: BITNAMI_DEBUG + value: "false" + # PostgreSQL configuration + - name: POSTGRESQL_VOLUME_DIR + value: "/bitnami/postgresql" + - name: PGDATA + value: "/bitnami/postgresql/data" + - name: POSTGRES_USER + value: "postgres" + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgresql-ha-secret + key: password + - name: POSTGRES_DB + value: "postgres" + - name: POSTGRESQL_LOG_HOSTNAME + value: "true" + - name: POSTGRESQL_LOG_CONNECTIONS + value: "false" + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: "false" + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: "off" + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: "error" + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: "pgaudit, repmgr" + - name: POSTGRESQL_ENABLE_TLS + value: "no" + - name: POSTGRESQL_PORT_NUMBER + value: "5432" + # Repmgr configuration + - name: REPMGR_PORT_NUMBER + value: "5432" + - name: REPMGR_PRIMARY_PORT + value: "5432" + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: REPMGR_UPGRADE_EXTENSION + value: "no" + - name: REPMGR_PGHBA_TRUST_ALL + value: "no" + - name: REPMGR_MOUNTED_CONF_DIR + value: "/bitnami/repmgr/conf" + - name: REPMGR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: REPMGR_PARTNER_NODES + value: postgresql-ha-postgresql-0.postgresql-ha-postgresql-headless.$(REPMGR_NAMESPACE).svc.cluster.local,postgresql-ha-postgresql-1.postgresql-ha-postgresql-headless.$(REPMGR_NAMESPACE).svc.cluster.local,postgresql-ha-postgresql-2.postgresql-ha-postgresql-headless.$(REPMGR_NAMESPACE).svc.cluster.local, + - name: REPMGR_PRIMARY_HOST + value: "postgresql-ha-postgresql-0.postgresql-ha-postgresql-headless.$(REPMGR_NAMESPACE).svc.cluster.local" + - name: REPMGR_NODE_NAME + value: "$(MY_POD_NAME)" + - name: REPMGR_NODE_NETWORK_NAME + value: "$(MY_POD_NAME).postgresql-ha-postgresql-headless.$(REPMGR_NAMESPACE).svc.cluster.local" + - name: REPMGR_NODE_TYPE + value: "data" + - name: REPMGR_LOG_LEVEL + value: "NOTICE" + - name: REPMGR_CONNECT_TIMEOUT + value: "5" + - name: REPMGR_RECONNECT_ATTEMPTS + value: "2" + - name: REPMGR_RECONNECT_INTERVAL + value: "3" + - name: REPMGR_USERNAME + value: "repmgr" + - name: REPMGR_PASSWORD + valueFrom: + secretKeyRef: + name: postgresql-ha-secret + key: repmgr-password + - name: REPMGR_DATABASE + value: "repmgr" + - name: REPMGR_FENCE_OLD_PRIMARY + value: "no" + - name: REPMGR_CHILD_NODES_CHECK_INTERVAL + value: "5" + - name: REPMGR_CHILD_NODES_CONNECTED_MIN_COUNT + value: "1" + - name: REPMGR_CHILD_NODES_DISCONNECT_TIMEOUT + value: "30" + envFrom: + ports: + - name: postgresql + containerPort: 5432 + protocol: TCP + livenessProbe: + failureThreshold: 6 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + exec: + command: + - bash + - -ec + - 'ps waux | grep "data standby clone" | grep -v grep || PGPASSWORD=$POSTGRES_PASSWORD psql -w -U "postgres" -d "postgres" -h 127.0.0.1 -p 5432 -c "SELECT 1"' + readinessProbe: + failureThreshold: 6 + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + exec: + command: + - bash + - -ec + - | + exec pg_isready -U "postgres" -h 127.0.0.1 -p 5432 + [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] + resources: + limits: + cpu: 1 + ephemeral-storage: 2Gi + memory: 2Gi + requests: + cpu: 500m + ephemeral-storage: 100Mi + memory: 500Mi + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/postgresql/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/conf + subPath: repmgr-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/tmp + subPath: repmgr-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/repmgr/logs + subPath: repmgr-logs-dir + - name: data + mountPath: /bitnami/postgresql + - name: hooks-scripts + mountPath: /pre-stop.sh + subPath: pre-stop.sh + - name: hooks-scripts + mountPath: /readiness-probe.sh + subPath: readiness-probe.sh + volumes: + - name: empty-dir + emptyDir: {} + - name: hooks-scripts + configMap: + name: postgresql-ha-postgresql-hooks-scripts + defaultMode: 0755 + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + spec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: "50Gi" diff --git a/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-externalsecret.yaml b/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-externalsecret.yaml new file mode 100644 index 00000000..136a8fcd --- /dev/null +++ b/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-externalsecret.yaml @@ -0,0 +1,9 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: postgresql-ha-secret + namespace: postgresql-ha +spec: + dataFrom: + - extract: + key: nerc/nerc-ocp-obs/ai-telemetry/postgresql-ha diff --git a/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-pgpool-externalsecret.yaml b/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-pgpool-externalsecret.yaml new file mode 100644 index 00000000..3f781dec --- /dev/null +++ b/ai-telemetry/overlays/nerc-ocp-obs/externalsecrets/postgresql-ha-pgpool-externalsecret.yaml @@ -0,0 +1,9 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: postgresql-ha-pgpool-secret + namespace: postgresql-ha +spec: + dataFrom: + - extract: + key: nerc/nerc-ocp-obs/ai-telemetry/postgresql-ha-pgpool diff --git a/ai-telemetry/overlays/nerc-ocp-obs/kustomization.yaml b/ai-telemetry/overlays/nerc-ocp-obs/kustomization.yaml index 4007ef41..e610536f 100644 --- a/ai-telemetry/overlays/nerc-ocp-obs/kustomization.yaml +++ b/ai-telemetry/overlays/nerc-ocp-obs/kustomization.yaml @@ -5,3 +5,5 @@ resources: patches: - path: externalsecrets/solr-externalsecret.yaml + - path: externalsecrets/postgresql-ha-pgpool-externalsecret.yaml + - path: externalsecrets/postgresql-ha-externalsecret.yaml diff --git a/cluster-scope/base/core/namespaces/postgresql-ha/kustomization.yaml b/cluster-scope/base/core/namespaces/postgresql-ha/kustomization.yaml new file mode 100644 index 00000000..48ef36e5 --- /dev/null +++ b/cluster-scope/base/core/namespaces/postgresql-ha/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml diff --git a/cluster-scope/base/core/namespaces/postgresql-ha/namespace.yaml b/cluster-scope/base/core/namespaces/postgresql-ha/namespace.yaml new file mode 100644 index 00000000..1325778d --- /dev/null +++ b/cluster-scope/base/core/namespaces/postgresql-ha/namespace.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: postgresql-ha +spec: {} diff --git a/cluster-scope/bundles/postgresql-ha/kustomization.yaml b/cluster-scope/bundles/postgresql-ha/kustomization.yaml new file mode 100644 index 00000000..eb992ab3 --- /dev/null +++ b/cluster-scope/bundles/postgresql-ha/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +commonLabels: + nerc.mghpcc.org/bundle: postgresql-ha +resources: +- ../../base/core/namespaces/postgresql-ha