From e9afd6a54a06c19a6e70d17a94de5bb0ae6d7e98 Mon Sep 17 00:00:00 2001 From: Sameer Naik Date: Tue, 27 Oct 2015 11:12:24 +0530 Subject: [PATCH] add support for streaming replication --- .../postgresql/rootfs/bitnami-utils-custom.sh | 196 ++++++++++++++---- .../etc/cont-init.d/01-bitnami-postgresql | 4 +- .../rootfs/etc/services.d/postgresql/run | 2 +- 3 files changed, 165 insertions(+), 37 deletions(-) diff --git a/bitnami/postgresql/rootfs/bitnami-utils-custom.sh b/bitnami/postgresql/rootfs/bitnami-utils-custom.sh index 1a126b0a3559..e7877baf532c 100644 --- a/bitnami/postgresql/rootfs/bitnami-utils-custom.sh +++ b/bitnami/postgresql/rootfs/bitnami-utils-custom.sh @@ -2,63 +2,189 @@ PROGRAM_OPTIONS="-D $BITNAMI_APP_DIR/data --config_file=$BITNAMI_APP_DIR/conf/postgresql.conf --hba_file=$BITNAMI_APP_DIR/conf/pg_hba.conf --ident_file=$BITNAMI_APP_DIR/conf/pg_ident.conf" initialize_database() { - echo "==> Initializing PostgreSQL database..." - echo "" + chmod 0700 $BITNAMI_APP_DIR/data chown -R $BITNAMI_APP_USER:$BITNAMI_APP_USER $BITNAMI_APP_DIR/data $BITNAMI_APP_DIR/conf - s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/initdb -D $BITNAMI_APP_DIR/data \ - -U $BITNAMI_APP_USER -E unicode -A trust >/dev/null + case "$POSTGRESQL_REPLICATION_MODE" in + slave) + echo "==> Trying to fetch replication parameters from the master link..." + echo "" + POSTGRESQL_MASTER_HOST=${POSTGRESQL_MASTER_HOST:-$MASTER_PORT_5432_TCP_ADDR} + POSTGRESQL_MASTER_PORT=${POSTGRESQL_MASTER_PORT:-$MASTER_PORT_5432_TCP_PORT} + POSTGRESQL_MASTER_USER=${POSTGRESQL_MASTER_USER:-$MASTER_ENV_POSTGRESQL_USER} + POSTGRESQL_MASTER_PASSWORD=${POSTGRESQL_MASTER_PASSWORD:-$MASTER_ENV_POSTGRESQL_PASSWORD} + POSTGRESQL_REPLICATION_USER=${POSTGRESQL_REPLICATION_USER:-$MASTER_ENV_POSTGRESQL_REPLICATION_USER} + POSTGRESQL_REPLICATION_PASSWORD=${POSTGRESQL_REPLICATION_PASSWORD:-$MASTER_ENV_POSTGRESQL_REPLICATION_PASSWORD} - # remove the config files generated by initdb + if [ ! $POSTGRESQL_MASTER_HOST ]; then + echo "In order to setup a replication slave you need to provide the POSTGRESQL_MASTER_HOST as well" + echo "" + exit -1 + fi + + if [ ! $POSTGRESQL_MASTER_PORT ]; then + echo "POSTGRESQL_MASTER_PORT not specified. Defaulting to 5432" + echo "" + POSTGRESQL_MASTER_PORT=${POSTGRESQL_MASTER_PORT:-5432} + fi + + if [ ! $POSTGRESQL_MASTER_USER ]; then + echo "In order to setup a replication slave you need to provide the POSTGRESQL_MASTER_USER as well" + echo "" + exit -1 + fi + + if [ ! $POSTGRESQL_REPLICATION_USER ]; then + echo "In order to setup a replication slave you need to provide the POSTGRESQL_REPLICATION_USER as well" + echo "" + exit -1 + fi + + if [ ! $POSTGRESQL_REPLICATION_PASSWORD ]; then + echo "In order to setup a replication slave you need to provide the POSTGRESQL_REPLICATION_PASSWORD as well" + echo "" + exit -1 + fi + + echo "==> Waiting for replication master to accept connections (60s timeout)..." + timeout=60 + while ! $BITNAMI_APP_DIR/bin/pg_isready -h $POSTGRESQL_MASTER_HOST -p $POSTGRESQL_MASTER_PORT -t 1 >/dev/null 2>&1 + do + timeout=$(expr $timeout - 1) + if [[ $timeout -eq 0 ]]; then + echo "Could not connect to replication master" + echo "" + exit -1 + fi + sleep 1 + done + echo "" + + echo "==> Replicating the initial database..." + echo "" + sudo -Hu $BITNAMI_APP_USER \ + PGPASSWORD=$POSTGRESQL_REPLICATION_PASSWORD $BITNAMI_APP_DIR/bin/pg_basebackup -D $BITNAMI_APP_DIR/data \ + -h ${POSTGRESQL_MASTER_HOST} -p ${POSTGRESQL_MASTER_PORT} -U ${POSTGRESQL_REPLICATION_USER} -X stream -w -v -P >/dev/null 2>&1 + + echo "==> Setting up streaming replication slave..." + echo "" + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#hot_standby = .*|hot_standby = on|" $BITNAMI_APP_DIR/conf/postgresql.conf + if [ ! -f $BITNAMI_APP_DIR/data/recovery.conf ]; then + s6-setuidgid $BITNAMI_APP_USER cp $BITNAMI_APP_DIR/share/recovery.conf.sample $BITNAMI_APP_DIR/data/recovery.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#standby_mode = .*|standby_mode = on|" $BITNAMI_APP_DIR/data/recovery.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#primary_conninfo = .*|primary_conninfo = 'host=${POSTGRESQL_MASTER_HOST} port=${POSTGRESQL_MASTER_PORT} user=${POSTGRESQL_REPLICATION_USER} password=${POSTGRESQL_REPLICATION_PASSWORD}'|" $BITNAMI_APP_DIR/data/recovery.conf + else + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^standby_mode = .*|standby_mode = on|" $BITNAMI_APP_DIR/data/recovery.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^primary_conninfo = .*|primary_conninfo = 'host=${POSTGRESQL_MASTER_HOST} port=${POSTGRESQL_MASTER_PORT} user=${POSTGRESQL_REPLICATION_USER} password=${POSTGRESQL_REPLICATION_PASSWORD}'|" $BITNAMI_APP_DIR/data/recovery.conf + fi + ;; + master|*) + echo "==> Initializing PostgreSQL database..." + echo "" + s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/initdb -D $BITNAMI_APP_DIR/data \ + -U $BITNAMI_APP_USER -E unicode -A trust >/dev/null + ;; + esac rm -rf $BITNAMI_APP_DIR/data/{pg_hba.conf,pg_ident.conf,postgresql.conf} } create_custom_database() { - if [ "$POSTGRESQL_DATABASE" ]; then - echo "==> Creating database $POSTGRESQL_DATABASE..." - echo "" - echo "CREATE DATABASE $POSTGRESQL_DATABASE;" | \ - s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + if [ "$POSTGRESQL_REPLICATION_MODE" != "slave" ]; then + if [ "$POSTGRESQL_DATABASE" ]; then + echo "==> Creating database $POSTGRESQL_DATABASE..." + echo "" + echo "CREATE DATABASE $POSTGRESQL_DATABASE;" | \ + s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + fi fi } create_postgresql_user() { - if [ ! "$POSTGRESQL_USER" ]; then - POSTGRESQL_USER=postgres + if [ "$POSTGRESQL_REPLICATION_MODE" != "slave" ]; then + if [ ! "$POSTGRESQL_USER" ]; then + POSTGRESQL_USER=postgres + fi + + if [ "$POSTGRESQL_USER" != "postgres" ] && [ ! $POSTGRESQL_DATABASE ]; then + echo "In order to use a custom POSTGRESQL_USER you need to provide the POSTGRESQL_DATABASE as well" + echo "" + exit -1 + fi + + if [ "$POSTGRESQL_USER" = postgres ]; then + echo "==> Creating postgres user with unrestricted access..." + echo "ALTER ROLE $POSTGRESQL_USER WITH PASSWORD '$POSTGRESQL_PASSWORD';" | \ + s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + else + echo "==> Creating user $POSTGRESQL_USER..." + echo "" + echo "CREATE ROLE $POSTGRESQL_USER WITH LOGIN CREATEDB PASSWORD '$POSTGRESQL_PASSWORD';" | \ + s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + + echo "==> Granting access to $POSTGRESQL_USER to the database $POSTGRESQL_DATABASE..." + echo "" + echo "GRANT ALL PRIVILEGES ON DATABASE $POSTGRESQL_DATABASE to $POSTGRESQL_USER;" | \ + s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + fi fi +} - if [ "$POSTGRESQL_USER" != "postgres" ] && [ ! $POSTGRESQL_DATABASE ]; then - echo "In order to use a custom POSTGRESQL_USER you need to provide the POSTGRESQL_DATABASE as well" - echo "" - exit -1 - fi +create_replication_user() { + if [ "$POSTGRESQL_REPLICATION_MODE" == "master" ]; then + if [ ! $POSTGRESQL_REPLICATION_USER ]; then + echo "In order to setup a replication master you need to provide the POSTGRESQL_REPLICATION_USER as well" + echo "" + exit -1 + fi - if [ "$POSTGRESQL_USER" = postgres ]; then - echo "==> Creating postgres user with unrestricted access..." - echo "ALTER ROLE $POSTGRESQL_USER WITH PASSWORD '$POSTGRESQL_PASSWORD';" | \ - s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null - else - echo "==> Creating user $POSTGRESQL_USER..." + if [ ! $POSTGRESQL_REPLICATION_PASSWORD ]; then + echo "In order to setup a replication master you need to provide the POSTGRESQL_REPLICATION_PASSWORD as well" + echo "" + exit -1 + fi + + echo "==> Creating replication user $POSTGRESQL_REPLICATION_USER..." echo "" - echo "CREATE ROLE $POSTGRESQL_USER WITH LOGIN CREATEDB PASSWORD '$POSTGRESQL_PASSWORD';" | \ + + echo "CREATE ROLE $POSTGRESQL_REPLICATION_USER REPLICATION LOGIN ENCRYPTED PASSWORD '$POSTGRESQL_REPLICATION_PASSWORD';" | \ s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null - echo "==> Granting access to $POSTGRESQL_USER to the database $POSTGRESQL_DATABASE..." + echo "==> Setting up streaming replication master..." echo "" - echo "GRANT ALL PRIVILEGES ON DATABASE $POSTGRESQL_DATABASE to $POSTGRESQL_USER;" | \ - s6-setuidgid $BITNAMI_APP_USER $BITNAMI_APP_DIR/bin/postgres --single $PROGRAM_OPTIONS >/dev/null + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#wal_level = .*|wal_level = hot_standby|" $BITNAMI_APP_DIR/conf/postgresql.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#max_wal_senders = .*|max_wal_senders = 16|" $BITNAMI_APP_DIR/conf/postgresql.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#checkpoint_segments = .*|checkpoint_segments = 8|" $BITNAMI_APP_DIR/conf/postgresql.conf + s6-setuidgid $BITNAMI_APP_USER sed -i "s|^#wal_keep_segments = .*|wal_keep_segments = 32|" $BITNAMI_APP_DIR/conf/postgresql.conf + + cat >> $BITNAMI_APP_DIR/conf/pg_hba.conf < $BITNAMI_APP_DIR/tmp/start