diff --git a/postgresql/templates/bin/_patroni_conversion.sh.tpl b/postgresql/templates/bin/_patroni_conversion.sh.tpl deleted file mode 100644 index 28b47e818..000000000 --- a/postgresql/templates/bin/_patroni_conversion.sh.tpl +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash - -{{/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/}} - -# This script creates the patroni replication user if it doesn't exist. -# This is only needed for brownfield upgrade scenarios, on top of sites that -# were greenfield-deployed with a pre-patroni version of postgres. -# -# For greenfield deployments, the patroni-enabled postgresql chart will -# create this user automatically. -# -# If any additional conversion steps are found to be needed, they can go here. - -set -ex - -function patroni_started() { - HOST=$1 - PORT=$2 - STATUS=$(timeout 10 bash -c "exec 3<>/dev/tcp/${HOST}/${PORT}; - echo -e \"GET / HTTP/1.1\r\nConnection: close\r\n\" >&3; - cat <&3 | tail -n1 | grep -o \"running\"") - - [[ x${STATUS} == "xrunning" ]] -} - -PGDATABASE=${PGDATABASE:-'postgres'} -PGHOST=${PGHOST:-'127.0.0.1'} -PGPORT={{- tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} -PSQL="psql -h ${PGHOST} -p ${PGPORT} -d ${PGDATABASE}" - -PVC_MNT={{- .Values.storage.mount.path }} -FILE_MADE_BY_POSTGRES=${PVC_MNT}/pgdata/pg_xlog -FILE_MADE_BY_PATRONI=${PVC_MNT}/pgdata/patroni.dynamic.json - -TIMEOUT=0 - -# Only need to add the user once, on the first replica -if [ "x${POD_NAME}" != "xpostgresql-0" ]; then - echo "Nothing to do on ${POD_NAME}" - exit 0 -fi - -# Look for a file-based clue that we're migrating from vanilla pg to patroni. -# This is lighter-weight than checking in the database for the user, since -# we have to fire up the database at this point to do the check. -if [[ -e "${FILE_MADE_BY_POSTGRES}" && ! -e "${FILE_MADE_BY_PATRONI}" ]] -then - echo "We are upgrading to Patroni -- checking for replication user" - - # Fire up a temporary postgres - /docker-entrypoint.sh postgres & - while ! $PSQL -c "select 1;"; do - sleep 1 - if [[ $TIMEOUT -gt 120 ]]; then - exit 1 - fi - TIMEOUT=$((TIMEOUT+1)) - done - TIMEOUT=0 - - # Add the replication user if it doesn't exist - USER_COUNT=$(${PSQL} -qt -c \ - "SELECT COUNT(*) FROM pg_roles \ - WHERE rolname='${PATRONI_REPLICATION_USERNAME}'") - - if [ ${USER_COUNT} -eq 0 ]; then - echo "The patroni replication user ${PATRONI_REPLICATION_USERNAME} doesn't exist yet; creating:" - # CREATE ROLE defaults to NOLOGIN not to allow password based login. - # Replication user uses SSL Cert to connect. - ${PSQL} -c "CREATE ROLE ${PATRONI_REPLICATION_USERNAME} \ - WITH REPLICATION;" - echo "done." - else - echo "The patroni replication user ${PATRONI_REPLICATION_USERNAME} already exists: nothing to do." - fi - - # Start Patroni to assimilate the postgres - sed "s/POD_IP_PATTERN/${PATRONI_KUBERNETES_POD_IP}/g" \ - /tmp/patroni-templated.yaml > /tmp/patroni.yaml - - READY_FLAG="i am the leader with the lock" - PATRONI_LOG=/tmp/patroni_conversion.log - /usr/bin/python3 /usr/local/bin/patroni /tmp/patroni-templated.yaml &> ${PATRONI_LOG} & - - # Sleep until patroni is running - while ! grep -q "${READY_FLAG}" ${PATRONI_LOG}; do - sleep 5 - if [[ $TIMEOUT -gt 24 ]]; then - echo "A timeout occurred. Patroni logs:" - cat ${PATRONI_LOG} - exit 1 - fi - TIMEOUT=$((TIMEOUT+1)) - done - TIMEOUT=0 - - # Gracefully stop postgres and patroni - while pkill INT --uid postgres; do - sleep 5 - if [[ $TIMEOUT -gt 24 ]]; then - echo "A timeout occurred. Patroni logs:" - cat ${PATRONI_LOG} - exit 1 - fi - TIMEOUT=$((TIMEOUT+1)) - done -else - echo "Patroni is already in place: nothing to do." -fi diff --git a/postgresql/templates/bin/_readiness.sh.tpl b/postgresql/templates/bin/_readiness.sh.tpl index 87a16f665..8aefefddc 100644 --- a/postgresql/templates/bin/_readiness.sh.tpl +++ b/postgresql/templates/bin/_readiness.sh.tpl @@ -16,8 +16,4 @@ limitations under the License. set -ex -if [ -f /tmp/postgres-disable-liveness-probe ]; then - exit 0 -else - pg_isready -U ${PATRONI_SUPERUSER_USERNAME} -fi +pg_isready -U ${POSTGRES_USER} diff --git a/postgresql/templates/bin/_set_password.sh.tpl b/postgresql/templates/bin/_set_password.sh.tpl deleted file mode 100644 index d3d31e3e6..000000000 --- a/postgresql/templates/bin/_set_password.sh.tpl +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -{{/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/}} - -PGDATABASE=${PGDATABASE:-'postgres'} -PGHOST=${PGHOST:-'127.0.0.1'} -PGPORT={{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - -# These are passed in via the Patroni callback interface -action="$1" -role="$2" -cluster="$3" - -# Note: this script when rendered is stored in a secret and encrypted to disk. -PATRONI_SUPERUSER_USERNAME={{ .Values.endpoints.postgresql.auth.admin.username }} -PATRONI_SUPERUSER_PASSWORD={{ .Values.endpoints.postgresql.auth.admin.password }} -PATRONI_REPLICATION_USERNAME={{ .Values.endpoints.postgresql.auth.replica.username }} - -if [[ x${role} == "xmaster" ]]; then - echo "I have become the patroni master: updating superuser and replication passwords" - - # It can take a few seconds for a freshly promoted leader to become read/write. - sleep 10 - if [[ ! -z "$PATRONI_SUPERUSER_PASSWORD" && ! -z "$PATRONI_SUPERUSER_USERNAME" ]]; then - psql -U $PATRONI_SUPERUSER_USERNAME -p "$PGPORT" -d "$PGDATABASE" -c "ALTER ROLE $PATRONI_SUPERUSER_USERNAME WITH PASSWORD '$PATRONI_SUPERUSER_PASSWORD';" - else - echo "WARNING: Did not set superuser password!!!" - fi - - echo "password update complete" -fi diff --git a/postgresql/templates/bin/_start.sh.tpl b/postgresql/templates/bin/_start.sh.tpl index 600a78acb..b671761c1 100644 --- a/postgresql/templates/bin/_start.sh.tpl +++ b/postgresql/templates/bin/_start.sh.tpl @@ -14,62 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */}} -set -ex +# Disable echo mode while setting the password +# unless we are in debug mode +{{- if .Values.conf.debug }} +set -x +{{- end }} +set -e -function patroni_started() { - HOST=$1 - PORT=$2 - STATUS=$(timeout 10 bash -c "exec 3<>/dev/tcp/${HOST}/${PORT}; - echo -e \"GET / HTTP/1.1\r\nConnection: close\r\n\" >&3; - cat <&3 | tail -n1 | grep -o \"running\"") +POSTGRES_DB=${POSTGRES_DB:-"postgres"} - [[ x${STATUS} == "xrunning" ]] -} -SVC_FQDN='{{ tuple "postgresql-restapi" "internal" . | include "helm-toolkit.endpoints.hostname_fqdn_endpoint_lookup" }}' -SVC_PORT='{{ tuple "postgresql-restapi" "internal" "restapi" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}' +# Check if the Postgres data directory exists before attempting to +# set the password +if [[ -d "$PGDATA" && -s "$PGDATA/PG_VERSION" ]] +then + postgres --single -D "$PGDATA" "$POSTGRES_DB" < \ - /tmp/patroni.yaml - -FILE_MADE_BY_PATRONI=${PGDATA}/patroni.dynamic.json -if [[ ! $POD_NAME -eq "postgresql-0" ]]; then - - echo "I am not postgresql pod zero: disabling liveness probe temporarily" - # disable liveness probe as it may take some time for the pod to come online - touch /tmp/postgres-disable-liveness-probe - - # During normal upgrades, we just need to turn liveness probes off temporarily - # for the sake of password rotation - need to bounce all pods at once - # (overriding RollingUpdate) to avoid deadlock. This accounts for that. - sleep 60 - - # During initial bootstrapping, we need to sequence 0,1,2 - if [[ ! -e "${FILE_MADE_BY_PATRONI}" ]]; then - echo "patroni has not been initialized on this node" - # NOTE: this boolean forces a second check after a delay. This accounts for a - # scenario during initial vanilla postgres -> patroni conversion, where - # a temporary master is brought up, killed off, and then restarted. - # This can be safely removed in the future, once all clusters are converted. - WAITED_EXTRA="false" - - while [ ${WAITED_EXTRA} = "false" ]; do - while ! patroni_started "${SVC_FQDN}" "${SVC_PORT}"; do - echo "Waiting until a Leader is elected..." - sleep 5 - done - # See note above: this code can be removed once all clusters are Patroni. - if [ ${WAITED_EXTRA} = "false" ]; then - echo "Leader is up; sleeping to ensure it gets through restarts..." - sleep 10 - WAITED_EXTRA="true" - fi - done - fi - - rm -fv /tmp/postgres-disable-liveness-probe fi -exec /usr/bin/python3 /usr/local/bin/patroni /tmp/patroni.yaml +set -x + +exec /docker-entrypoint.sh postgres -c config_file=/tmp/postgresql.conf diff --git a/postgresql/templates/configmap-bin.yaml b/postgresql/templates/configmap-bin.yaml index 108db3fc9..2c0e502dd 100644 --- a/postgresql/templates/configmap-bin.yaml +++ b/postgresql/templates/configmap-bin.yaml @@ -38,6 +38,4 @@ data: {{- if .Values.manifests.job_ks_user }} ks-user.sh: {{ include "helm-toolkit.scripts.keystone_user" . | b64enc }} {{- end }} - set_password.sh: {{ tuple "bin/_set_password.sh.tpl" . | include "helm-toolkit.utils.template" | b64enc }} - patroni_conversion.sh: {{ tuple "bin/_patroni_conversion.sh.tpl" . | include "helm-toolkit.utils.template" | b64enc }} {{- end }} diff --git a/postgresql/templates/configmap-etc.yaml b/postgresql/templates/configmap-etc.yaml index e01f6bf7f..9d8dbb339 100644 --- a/postgresql/templates/configmap-etc.yaml +++ b/postgresql/templates/configmap-etc.yaml @@ -17,10 +17,14 @@ limitations under the License. --- apiVersion: v1 -kind: Secret +kind: ConfigMap metadata: name: postgresql-etc -type: Opaque data: -{{- include "helm-toolkit.snippets.values_template_renderer" (dict "envAll" $envAll "template" .Values.conf.patroni "key" "patroni.yaml" "format" "Secret") | indent 2 }} + postgresql.conf: | +{{- range $key, $value := default dict .Values.conf.postgresql }} + {{ $key | snakecase }} = '{{ $value }}' +{{- end }} + pg_hba.conf: | +{{ .Values.conf.pg_hba | indent 4 }} {{- end }} diff --git a/postgresql/templates/secret-replica.yaml b/postgresql/templates/secret-replica.yaml deleted file mode 100644 index 343506620..000000000 --- a/postgresql/templates/secret-replica.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/}} - -{{- if .Values.manifests.secret_replica }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.secrets.postgresql.replica }} -type: Opaque -data: -{{ include "helm-toolkit.utils.tls_generate_certs" (dict "params" .Values.secrets.pki.replication "encode" true) | indent 2 }} -... -{{- end }} diff --git a/postgresql/templates/secret-server.yaml b/postgresql/templates/secret-server.yaml deleted file mode 100644 index 22b6c9a58..000000000 --- a/postgresql/templates/secret-server.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/}} - -{{- if .Values.manifests.secret_server }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.secrets.postgresql.server }} -type: Opaque -data: -{{ include "helm-toolkit.utils.tls_generate_certs" (dict "params" .Values.secrets.pki.server "encode" true) | indent 2 }} -... -{{- end }} diff --git a/postgresql/templates/service-postgres.yaml b/postgresql/templates/service-postgres.yaml index 54088212a..30ce15b18 100644 --- a/postgresql/templates/service-postgres.yaml +++ b/postgresql/templates/service-postgres.yaml @@ -21,6 +21,8 @@ metadata: name: {{ tuple "postgresql" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }} spec: ports: - - name: postgresql + - name: db port: {{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} + selector: +{{ tuple $envAll "postgresql" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }} {{- end }} diff --git a/postgresql/templates/statefulset.yaml b/postgresql/templates/statefulset.yaml index 7c049d82d..7456a88d8 100644 --- a/postgresql/templates/statefulset.yaml +++ b/postgresql/templates/statefulset.yaml @@ -35,9 +35,6 @@ rules: - patch - update - watch - # delete and deletecollection are required only for 'patronictl remove' - - delete - - deletecollection - apiGroups: - "" resources: @@ -50,9 +47,6 @@ rules: - create - list - watch - # delete and deletecollection are required only for 'patronictl remove' - - delete - - deletecollection - apiGroups: - "" resources: @@ -122,7 +116,6 @@ spec: configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }} {{ dict "envAll" $envAll "podName" "postgresql" "containerNames" (list "postgresql" "set-volume-perms" "init") | include "helm-toolkit.snippets.kubernetes_mandatory_access_control_annotation" | indent 8 }} configmap-admin-hash: {{ tuple "secret-admin.yaml" . | include "helm-toolkit.utils.hash" }} - configmap-replica-hash: {{ tuple "secret-replica.yaml" . | include "helm-toolkit.utils.hash" }} configmap-secrets-etc-hash: {{ tuple "secrets-etc.yaml" . | include "helm-toolkit.utils.hash" }} spec: serviceAccountName: {{ $serviceAccountName }} @@ -144,132 +137,13 @@ spec: /bin/chown {{ .Values.pod.security_context.server.pod.runAsUser }} {{ .Values.storage.mount.path }}; /bin/chmod 700 {{ .Values.storage.mount.path }}; /bin/chmod 700 {{ .Values.storage.mount.path }}/*; - /bin/cp {{ .Values.secrets.pki.client_cert_path }}_temp/* {{ .Values.secrets.pki.client_cert_path }}/.; - /bin/cp {{ .Values.secrets.pki.server_cert_path }}_temp/* {{ .Values.secrets.pki.server_cert_path }}/.; - /bin/chown {{ .Values.pod.security_context.server.pod.runAsUser }} {{ .Values.secrets.pki.client_cert_path }}; - /bin/chown {{ .Values.pod.security_context.server.pod.runAsUser }} {{ .Values.secrets.pki.client_cert_path }}/*; - /bin/chown {{ .Values.pod.security_context.server.pod.runAsUser }} {{ .Values.secrets.pki.server_cert_path }}; - /bin/chown {{ .Values.pod.security_context.server.pod.runAsUser }} {{ .Values.secrets.pki.server_cert_path }}/*; - /bin/chmod 700 {{ .Values.secrets.pki.client_cert_path }}; - /bin/chmod 600 {{ .Values.secrets.pki.client_cert_path }}/*; - /bin/chmod 700 {{ .Values.secrets.pki.server_cert_path }}; - /bin/chmod 600 {{ .Values.secrets.pki.server_cert_path }}/*; {{ dict "envAll" $envAll "application" "server" "container" "set_volume_perms" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }} volumeMounts: - name: pod-tmp mountPath: /tmp - name: postgresql-data mountPath: {{ .Values.storage.mount.path }} - - name: server-certs - mountPath: {{ .Values.secrets.pki.server_cert_path }} - # server-cert-temp mountpoint is temp storage for secrets. We copy the - # secrets to server-certs folder and set owner and permissions. - # This is needed because the secrets are always created readonly. - - name: server-certs-temp - mountPath: {{ .Values.secrets.pki.server_cert_path }}_temp - - name: postgresql-pki - subPath: crt - mountPath: {{ .Values.secrets.pki.server_cert_path }}_temp/server.crt - - name: postgresql-pki - subPath: key - mountPath: {{ .Values.secrets.pki.server_cert_path }}_temp/server.key - - name: replication-pki - subPath: ca - mountPath: {{ .Values.secrets.pki.server_cert_path }}_temp/ca.crt - - name: replication-pki - subPath: caKey - mountPath: {{ .Values.secrets.pki.server_cert_path }}_temp/ca.key - # client-certs is the permanent folder for the client secrets - - name: client-certs - mountPath: {{ .Values.secrets.pki.client_cert_path }} - # client-certs-temp is temporary folder for the client secrets, before they a copied to their permanent folder - - name: client-certs-temp - mountPath: {{ .Values.secrets.pki.client_cert_path }}_temp - - name: replication-pki - subPath: crt - mountPath: {{ .Values.secrets.pki.client_cert_path }}_temp/client.crt - - name: replication-pki - subPath: key - mountPath: {{ .Values.secrets.pki.client_cert_path }}_temp/client.key - - name: postgresql-pki - subPath: ca - mountPath: {{ .Values.secrets.pki.client_cert_path }}_temp/ca.crt - - name: postgresql-pki - subPath: caKey - mountPath: {{ .Values.secrets.pki.client_cert_path }}_temp/ca.key - # This is for non-HA -> Patroni conversion and can be removed in the future - - name: patroni-conversion -{{ tuple $envAll "postgresql" | include "helm-toolkit.snippets.image" | indent 10 }} -{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }} - env: - - name: PGDATA - value: "{{ .Values.storage.mount.path }}/pgdata" - - name: PATRONI_KUBERNETES_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: PATRONI_KUBERNETES_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: KUBERNETES_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: PATRONI_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: PATRONI_KUBERNETES_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: PATRONI_SUPERUSER_USERNAME - valueFrom: - secretKeyRef: - name: {{ .Values.secrets.postgresql.admin }} - key: 'POSTGRES_USER' - - name: PATRONI_SUPERUSER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.secrets.postgresql.admin }} - key: 'POSTGRES_PASSWORD' - - name: PATRONI_REPLICATION_USERNAME - value: {{ index .Values.secrets.pki.replication.hosts.names 0 | quote }} - - name: PATRONI_RESTAPI_CONNECT_ADDRESS - value: $(PATRONI_KUBERNETES_POD_IP):{{ tuple "postgresql-restapi" "internal" "restapi" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_RESTAPI_LISTEN - value: 0.0.0.0:{{ tuple "postgresql-restapi" "internal" "restapi" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_POSTGRESQL_CONNECT_ADDRESS - value: $(PATRONI_KUBERNETES_POD_IP):{{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_POSTGRESQL_LISTEN - value: 0.0.0.0:{{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_admin_PASSWORD - value: $(PATRONI_SUPERUSER_PASSWORD) - - name: PATRONI_admin_OPTIONS - value: 'createrole,createdb' - command: - - /tmp/patroni_conversion.sh -{{ dict "envAll" $envAll "application" "server" "container" "patroni_conversion" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }} - volumeMounts: - - name: pod-tmp - mountPath: /tmp - - name: patroni-conversion-tmp - mountPath: /var/run/postgresql - - name: postgresql-bin - mountPath: /tmp/patroni_conversion.sh - subPath: patroni_conversion.sh - readOnly: true - - name: postgresql-data - mountPath: {{ .Values.storage.mount.path }} - - name: postgresql-etc - mountPath: /tmp/patroni-templated.yaml - subPath: patroni.yaml - readOnly: true + subPath: {{ .Values.storage.mount.subpath }} containers: - name: postgresql {{ tuple $envAll "postgresql" | include "helm-toolkit.snippets.image" | indent 10 }} @@ -283,72 +157,24 @@ spec: env: - name: PGDATA value: "{{ .Values.storage.mount.path }}/pgdata" - - name: PATRONI_KUBERNETES_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: PATRONI_KUBERNETES_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - - name: PATRONI_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - - name: PATRONI_KUBERNETES_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: PATRONI_SUPERUSER_USERNAME - valueFrom: - secretKeyRef: - name: {{ .Values.secrets.postgresql.admin }} - key: 'POSTGRES_USER' - - name: PATRONI_SUPERUSER_PASSWORD + - name: 'POSTGRES_PASSWORD' valueFrom: secretKeyRef: name: {{ .Values.secrets.postgresql.admin }} key: 'POSTGRES_PASSWORD' - - name: PATRONI_REPLICATION_USERNAME - value: {{ index .Values.secrets.pki.replication.hosts.names 0 | quote }} - - name: PATRONI_RESTAPI_CONNECT_ADDRESS - value: $(PATRONI_KUBERNETES_POD_IP):{{ tuple "postgresql-restapi" "internal" "restapi" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_RESTAPI_LISTEN - value: 0.0.0.0:{{ tuple "postgresql-restapi" "internal" "restapi" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_POSTGRESQL_CONNECT_ADDRESS - value: $(PATRONI_KUBERNETES_POD_IP):{{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_POSTGRESQL_LISTEN - value: 0.0.0.0:{{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - - name: PATRONI_{{ .Values.endpoints.postgresql.auth.admin.username }}_PASSWORD - value: $(PATRONI_SUPERUSER_PASSWORD) - - name: PATRONI_{{ .Values.endpoints.postgresql.auth.admin.username }}_OPTIONS - value: 'createrole,createdb' -{{- if .Values.manifests.secret_audit }} - - name: AUDIT_PASSWORD + - name: 'POSTGRES_USER' valueFrom: secretKeyRef: - name: {{ .Values.secrets.postgresql.audit }} - key: AUDIT_PASSWORD - # Adding the audit user with no options just adds the user without - # any GRANTs. This means the user gets to do only what default - # PUBLIC permissions allow, which is only to SELECT from tables. - - name: PATRONI_{{ .Values.endpoints.postgresql.auth.audit.username }}_PASSWORD - value: $(AUDIT_PASSWORD) -{{- end }} - - name: PGSSLROOTCERT - value: {{ .Values.secrets.pki.client_cert_path }}/ca.crt - - name: PGSSLCERT - value: "/home/postgres/.postgresql/postgresql.crt" - - name: PGSSLKEY - value: "/home/postgres/.postgresql/postgresql.key" + name: {{ .Values.secrets.postgresql.admin }} + key: 'POSTGRES_USER' command: - /tmp/start.sh livenessProbe: @@ -370,10 +196,6 @@ spec: mountPath: /tmp - name: pg-run mountPath: /var/run/postgresql - - name: postgresql-bin - mountPath: /tmp/set_password.sh - subPath: set_password.sh - readOnly: true - name: postgresql-bin mountPath: /tmp/start.sh subPath: start.sh @@ -383,25 +205,16 @@ spec: subPath: readiness.sh readOnly: true - name: postgresql-etc - mountPath: /tmp/patroni-templated.yaml - subPath: patroni.yaml + mountPath: /tmp/postgresql.conf + subPath: postgresql.conf + readOnly: true + - name: postgresql-etc + mountPath: /tmp/pg_hba.conf + subPath: pg_hba.conf readOnly: true - name: postgresql-data mountPath: {{ .Values.storage.mount.path }} - - name: server-certs - mountPath: {{ .Values.secrets.pki.server_cert_path }} - - name: client-certs - mountPath: {{ .Values.secrets.pki.client_cert_path }} - - name: postgres-home-config - mountPath: "/home/postgres/.postgresql" - - name: client-certs - subPath: "client.crt" - mountPath: "/home/postgres/.postgresql/postgresql.crt" - readOnly: true - - name: client-certs - subPath: "client.key" - mountPath: "/home/postgres/.postgresql/postgresql.key" - readOnly: true + subPath: {{ .Values.storage.mount.subpath }} volumes: - name: pod-tmp emptyDir: {} @@ -410,32 +223,13 @@ spec: - name: pg-run emptyDir: medium: "Memory" - # This is for non-HA -> Patroni conversion and can be removed in the future - - name: patroni-conversion-tmp - emptyDir: {} - name: postgresql-bin secret: secretName: postgresql-bin defaultMode: 0555 - - name: client-certs-temp - emptyDir: {} - - name: server-certs-temp - emptyDir: {} - - name: client-certs - emptyDir: {} - - name: server-certs - emptyDir: {} - - name: replication-pki - secret: - secretName: {{ .Values.secrets.postgresql.replica }} - defaultMode: 0640 - - name: postgresql-pki - secret: - secretName: {{ .Values.secrets.postgresql.server }} - defaultMode: 0640 - name: postgresql-etc - secret: - secretName: postgresql-etc + configMap: + name: postgresql-etc defaultMode: 0444 {{- if not .Values.storage.pvc.enabled }} - name: postgresql-data diff --git a/postgresql/values.yaml b/postgresql/values.yaml index 07a659348..16791d6c0 100644 --- a/postgresql/values.yaml +++ b/postgresql/values.yaml @@ -40,10 +40,6 @@ pod: postgresql: readOnlyRootFilesystem: true allowPrivilegeEscalation: false - patroni_conversion: - runAsUser: 999 - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true postgresql_backup: pod: runAsUser: 65534 @@ -73,7 +69,8 @@ pod: weight: default: 10 replicas: - server: 3 + # only 1 replica currently supported + server: 1 prometheus_postgresql_exporter: 1 lifecycle: upgrades: @@ -144,10 +141,10 @@ pod: memory: "1024Mi" cpu: "2000m" -# using dockerhub patroni: https://hub.docker.com/r/openstackhelm/patroni/tags/ +# using dockerhub postgresql: https://hub.docker.com/r/library/postgres/tags/ images: tags: - postgresql: "docker.io/openstackhelm/patroni:latest-ubuntu_xenial" + postgresql: "docker.io/postgres:9.6" dep_check: quay.io/airshipit/kubernetes-entrypoint:v1.0.0 image_repo_sync: docker.io/docker:17.07.0 ks_user: docker.io/openstackhelm/heat:stein-ubuntu_bionic @@ -257,133 +254,42 @@ network_policy: conf: debug: false + pg_hba: | + host all all 127.0.0.1/32 trust + host all all 0.0.0.0/0 md5 + local all all trust + postgresql: - shared_buffers: 128MB - max_connections: 100 - patroni: | - scope: {{ tuple "postgresql" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }} - kubernetes: - labels: - application: {{ tuple "postgresql" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }} - component: server - use_endpoints: true - ports: - - name: {{ tuple "postgresql" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }} - port: {{ tuple "postgresql" "internal" "postgresql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} - bootstrap: - users: - {{ .Values.endpoints.postgresql.auth.admin.username }}: - password: {{ .Values.endpoints.postgresql.auth.admin.password }} - options: - - createrole - - createdb - dcs: - ttl: 30 - loop_wait: 10 - retry_timeout: 10 - maximum_lag_on_failover: 1048576 - postgresql: - data_dir: '{{ .Values.storage.mount.path }}/pgdata' - pgpass: '{{ .Values.storage.mount.path }}/pgpass' - use_pg_rewind: true - parameters: - archive_mode: 'off' - datestyle: 'iso, mdy' - external_pid_file: '/tmp/postgres.pid' - hot_standby: 'on' - log_checkpoints: 'on' - log_connections: 'on' - log_disconnections: 'on' - log_line_prefix: 'postgresql: %t [%p]: [%l-1] %c %x %d %u %a %h %m ' - log_lock_waits: 'on' - log_temp_files: 0 - log_timezone: 'UTC' - max_connections: {{ .Values.conf.postgresql.max_connections }} - max_replication_slots: 10 - max_wal_senders: 10 - max_worker_processes: 10 - ssl: 'on' - # These relative paths are relative to data_dir - ssl_cert_file: {{ .Values.secrets.pki.server_cert_path }}/server.crt - ssl_ca_file: {{ .Values.secrets.pki.server_cert_path }}/ca.crt - ssl_key_file: {{ .Values.secrets.pki.server_cert_path }}/server.key - ssl_ciphers: 'HIGH:+3DES:!aNULL' - tcp_keepalives_idle: 900 - tcp_keepalives_interval: 100 - timezone: 'UTC' - track_commit_timestamp: 'on' - track_functions: all - wal_keep_segments: 8 - wal_level: hot_standby - wal_log_hints: 'on' - initdb: - - auth-host: md5 - - auth-local: trust - - encoding: UTF8 - - locale: en_US.UTF-8 - - data-checksums - pg_hba: - - host all all 127.0.0.1/32 trust - - host all all 0.0.0.0/0 md5 - - hostssl replication {{ .Values.endpoints.postgresql.auth.replica.username }} {{ .Values.secrets.pki.pod_cidr }} cert clientcert=1 - - hostssl replication {{ .Values.endpoints.postgresql.auth.replica.username }} 127.0.0.1/32 cert clientcert=1 - - local all all trust - postgresql: - {{/* Note: the postgres pod mounts a volume at /var/lib/postgresql/data, - so let's just avoid it and use /var/lib/postgresql/pgdata instead. - Patroni moves this directory to a backup under the parent directory - (/var/lib/postgresql) under certain failure recovery scenarios, so - /var/lib/postgres itself must be exposed to the pod as a pvc mount.*/}} - authentication: - superuser: - username: {{ .Values.endpoints.postgresql.auth.admin.username }} - password: {{ .Values.endpoints.postgresql.auth.admin.password }} - data_dir: '{{ .Values.storage.mount.path }}/pgdata' - pgpass: '{{ .Values.storage.mount.path }}/pgpass' - callbacks: - on_role_change: /tmp/set_password.sh - on_start: /tmp/set_password.sh - use_pg_rewind: true - remove_data_directory_on_rewind_failure: true - remove_data_directory_on_diverged_timelines: true - parameters: - archive_mode: 'off' - datestyle: 'iso, mdy' - external_pid_file: '/tmp/postgres.pid' - hot_standby: 'on' - log_checkpoints: 'on' - log_connections: 'on' - log_disconnections: 'on' - log_line_prefix: 'postgresql: %t [%p]: [%l-1] %c %x %d %u %a %h %m ' - log_lock_waits: 'on' - log_temp_files: 0 - log_timezone: 'UTC' - max_connections: {{ .Values.conf.postgresql.max_connections }} - max_replication_slots: 10 - max_wal_senders: 10 - max_worker_processes: 10 - ssl: 'on' - # These relative paths are relative to data_dir - ssl_cert_file: {{ .Values.secrets.pki.server_cert_path }}/server.crt - ssl_ca_file: {{ .Values.secrets.pki.server_cert_path }}/ca.crt - ssl_key_file: {{ .Values.secrets.pki.server_cert_path }}/server.key - ssl_ciphers: 'HIGH:+3DES:!aNULL' - tcp_keepalives_idle: 900 - tcp_keepalives_interval: 100 - timezone: 'UTC' - track_commit_timestamp: 'on' - track_functions: all - wal_keep_segments: 8 - wal_level: hot_standby - wal_log_hints: 'on' - pg_hba: - - host all all 127.0.0.1/32 trust - - host all all 0.0.0.0/0 md5 - - hostssl replication {{ .Values.endpoints.postgresql.auth.replica.username }} {{ .Values.secrets.pki.pod_cidr }} cert clientcert=1 - - hostssl replication {{ .Values.endpoints.postgresql.auth.replica.username }} 127.0.0.1/32 cert clientcert=1 - - local all all trust - watchdog: - mode: off # Allowed values: off, automatic, required + archive_mode: 'off' + cluster_name: 'postgresql' + datestyle: 'iso, mdy' + external_pid_file: '/tmp/postgres.pid' + fsync: 'on' + listen_addresses: '0.0.0.0' + log_checkpoints: 'on' + log_connections: 'on' + log_disconnections: 'on' + log_line_prefix: 'postgresql: %t [%p]: [%l-1] %c %x %d %u %a %h %m ' + log_lock_waits: 'on' + log_temp_files: '0' + log_timezone: 'UTC' + max_connections: '1000' + max_locks_per_transaction: '64' + max_prepared_transactions: '0' + max_wal_senders: '16' + max_worker_processes: '10' + port: '5432' + shared_buffers: '2GB' + tcp_keepalives_idle: '900' + tcp_keepalives_interval: '100' + timezone: 'UTC' + track_commit_timestamp: 'on' + track_functions: 'all' + wal_keep_segments: '16' + wal_level: 'hot_standby' + wal_log_hints: 'on' + hba_file: '/tmp/pg_hba.conf' + ident_file: '/tmp/pg_ident.conf' backup: enabled: false base_path: /var/backup @@ -397,16 +303,6 @@ conf: exporter: queries: - pg_replication: - query: "SELECT EXTRACT(epoch FROM (now() - pg_last_xact_replay_timestamp()))::int AS lag, CASE WHEN pg_is_in_recovery() THEN 1 ELSE 0 END AS is_replica" - master: true - metrics: - - lag: - usage: "GAUGE" - description: "Replication lag behind master in seconds" - - is_replica: - usage: "GAUGE" - description: "Indicates if this host is a replica" pg_postmaster: query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()" master: true @@ -416,26 +312,8 @@ conf: description: "Time at which postmaster started" secrets: - pki: - client_cert_path: /client_certs - server_cert_path: /server_certs - pod_cidr: 0.0.0.0/0 - server: - hosts: - names: - # this name should be the service name for postgresql - - postgresql.ucp.svc.cluster.local - life: 365 - replication: - hosts: - names: - # this name needs to be the same as endpoints.postgres.auth.replica.username - - standby - life: 365 postgresql: admin: postgresql-admin - replica: postgresql-replication-pki - server: postgresql-server-pki exporter: postgresql-exporter audit: postgresql-audit backup_restore: postgresql-backup-restore @@ -462,8 +340,6 @@ endpoints: admin: username: postgres password: password - replica: - username: standby exporter: username: psql_exporter password: psql_exp_pass @@ -548,8 +424,6 @@ manifests: network_policy: false job_ks_user: false secret_admin: true - secret_replica: true - secret_server: true secret_etc: true secret_audit: true secret_backup_restore: false diff --git a/tools/deployment/common/postgresql.sh b/tools/deployment/common/postgresql.sh index 8da8c2846..3fa1c2519 100755 --- a/tools/deployment/common/postgresql.sh +++ b/tools/deployment/common/postgresql.sh @@ -26,7 +26,7 @@ helm upgrade --install postgresql ./postgresql \ --set monitoring.prometheus.enabled=true \ --set storage.pvc.size=1Gi \ --set storage.pvc.enabled=true \ - --set pod.replicas.server=3 \ + --set pod.replicas.server=1 \ ${OSH_INFRA_EXTRA_HELM_ARGS} \ ${OSH_INFRA_EXTRA_HELM_ARGS_POSTGRESQL}