Patroni exclusion for Postgres

This PS removes the previously put in place HA clustering support
Patroni provided.

Change-Id: I03ed11282413a454062ab34b8594ba60ac2175aa
This commit is contained in:
anthony.bellino 2020-04-24 22:36:21 +00:00
parent 303d5e3108
commit 96369491cb
12 changed files with 82 additions and 665 deletions

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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" <<EOF
ALTER ROLE $POSTGRES_USER WITH PASSWORD '$POSTGRES_PASSWORD'
EOF
# This is required because the declarative values.yaml config doesn't
# know the dynamic podIP. TODO: something more elegant.
sed "s/POD_IP_PATTERN/${PATRONI_KUBERNETES_POD_IP}/g" \
/tmp/patroni-templated.yaml > \
/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

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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

View File

@ -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

View File

@ -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}