Merge branch 'docs'

This commit is contained in:
Ian Barwick
2017-10-16 11:11:58 +09:00
54 changed files with 4987 additions and 27 deletions

2
.gitignore vendored
View File

@@ -40,6 +40,8 @@ lib*.pc
# test output
/results/
/doc/Makefile
# other
/.lineno
*.dSYM

View File

@@ -63,6 +63,12 @@ Makefile: Makefile.in config.status configure
Makefile.global: Makefile.global.in config.status configure
./config.status $@
doc:
$(MAKE) -C doc all
install-doc:
$(MAKE) -C doc install
clean: additional-clean
maintainer-clean: additional-maintainer-clean

View File

@@ -991,10 +991,10 @@ active primary, the previous warning will not be displayed:
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+----------------------------------------------------
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr port=5501
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr port=5502
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr port=5503
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr
However the sole remaining standby is still trying to replicate from the failed
primary; `repmgr standby follow` must now be executed to rectify this situation.

3
configure vendored
View File

@@ -1871,6 +1871,8 @@ ac_config_files="$ac_config_files Makefile"
ac_config_files="$ac_config_files Makefile.global"
ac_config_files="$ac_config_files doc/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -2564,6 +2566,7 @@ do
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;;
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View File

@@ -65,5 +65,6 @@ AC_SUBST(vpath_build)
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([Makefile.global])
AC_CONFIG_FILES([doc/Makefile])
AC_OUTPUT

5
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
HTML.index
bookindex.sgml
html-stamp
html/
version.sgml

71
doc/Makefile.in Normal file
View File

@@ -0,0 +1,71 @@
repmgr_subdir = doc
repmgr_top_builddir = ..
include $(repmgr_top_builddir)/Makefile.global
ifndef JADE
JADE = $(missing) jade
endif
SGMLINCLUDE = -D . -D ${srcdir}
SPFLAGS += -wall -wno-unused-param -wno-empty -wfully-tagged
JADE.html.call = $(JADE) $(JADEFLAGS) $(SPFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t sgml -i output-html
ALLSGML := $(wildcard $(srcdir)/*.sgml)
# to build bookindex
ALMOSTALLSGML := $(filter-out %bookindex.sgml,$(ALLSGML))
GENERATED_SGML = version.sgml bookindex.sgml
Makefile: Makefile.in
cd $(repmgr_top_builddir) && ./config.status doc/Makefile
all: html
html: html-stamp
html-stamp: repmgr.sgml $(ALLSGML) $(GENERATED_SGML) stylesheet.dsl website-docs.css
$(MKDIR_P) html
$(JADE.html.call) -i include-index $<
cp $(srcdir)/stylesheet.css $(srcdir)/website-docs.css html/
touch $@
version.sgml: ${repmgr_top_builddir}/repmgr_version.h
{ \
echo "<!ENTITY repmgrversion \"$(REPMGR_VERSION)\">"; \
} > $@
HTML.index: repmgr.sgml $(ALMOSTALLSGML) stylesheet.dsl
@$(MKDIR_P) html
$(JADE.html.call) -V html-index $<
website-docs.css:
@$(MKDIR_P) html
curl http://www.postgresql.org/media/css/docs.css > ${srcdir}/website-docs.css
bookindex.sgml: HTML.index
ifdef COLLATEINDEX
LC_ALL=C $(PERL) $(COLLATEINDEX) -f -g -i 'bookindex' -o $@ $<
else
@$(missing) collateindex.pl $< $@
endif
clean:
rm -f html-stamp
rm -f HTML.index $(GENERATED_SGML)
maintainer-clean:
rm -rf html
rm -rf Makefile
zip: html
cp -r html repmgr-docs-$(REPMGR_VERSION)
zip -r repmgr-docs-$(REPMGR_VERSION).zip repmgr-docs-$(REPMGR_VERSION)
rm -rf repmgr-docs-$(REPMGR_VERSION)
install: html
@$(MKDIR_P) $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
@$(INSTALL_DATA) $(wildcard html/*.html) $(wildcard html/*.css) $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
@echo Installed docs to $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
.PHONY: html all

View File

@@ -0,0 +1,5 @@
<appendix id="appendix-signatures" xreflabel="Verifying digital signatures">
<title>Verifying digital signatures</title>
<para>WIP</para>
</appendix>

403
doc/cloning-standbys.sgml Normal file
View File

@@ -0,0 +1,403 @@
<chapter id="cloning-standbys" xreflabel="cloning standbys">
<title>Cloning standbys</title>
<para>
</para>
<sect1 id="cloning-from-barman" xreflabel="Cloning from Barman">
<indexterm>
<primary>cloning</primary>
<secondary>from Barman</secondary>
</indexterm>
<title>Cloning a standby from Barman</title>
<para>
<xref linkend="repmgr-standby-clone"> can use
<ulink url="https://www.2ndquadrant.com/">2ndQuadrant</ulink>'s
<ulink url="https://www.pgbarman.org/">Barman</ulink> application
to clone a standby (and also as a fallback source for WAL files).
</para>
<tip>
<simpara>
Barman (aka PgBarman) should be considered as an integral part of any
PostgreSQL replication cluster. For more details see:
<ulink url="https://www.pgbarman.org/">https://www.pgbarman.org/</ulink>.
</simpara>
</tip>
<para>
Barman support provides the following advantages:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
the primary node does not need to perform a new backup every time a
new standby is cloned
</para>
</listitem>
<listitem>
<para>
a standby node can be disconnected for longer periods without losing
the ability to catch up, and without causing accumulation of WAL
files on the primary node
</para>
</listitem>
<listitem>
<para>
WAL management on the primary becomes much easier as there's no need
to use replication slots, and <varname>wal_keep_segments</varname>
does not need to be set.
</para>
</listitem>
</itemizedlist>
</para>
<sect2 id="cloning-from-barman-prerequisites" xreflabel="Prerequisites for cloning from Barman">
<title>Prerequisites for cloning from Barman</title>
<para>
In order to enable Barman support for <command>repmgr standby clone</command>, following
prerequisites must be met:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
the <varname>barman_server</varname> setting in <filename>repmgr.conf</filename> is the same as the
server configured in Barman;
</para>
</listitem>
<listitem>
<para>
the <varname>barman_host</varname> setting in <filename>repmgr.conf</filename> is set to the SSH
hostname of the Barman server;
</para>
</listitem>
<listitem>
<para>
the <varname>restore_command</varname> setting in <filename>repmgr.conf</filename> is configured to
use a copy of the <command>barman-wal-restore</command> script shipped with the
<literal>barman-cli</literal> package (see below);
</para>
</listitem>
<listitem>
<para>
the Barman catalogue includes at least one valid backup for this server.
</para>
</listitem>
</itemizedlist>
</para>
<note>
<simpara>
Barman support is automatically enabled if <varname>barman_server</varname>
is set. Normally it is good practice to use Barman, for instance
when fetching a base backup while cloning a standby; in any case,
Barman mode can be disabled using the <literal>--without-barman</literal>
command line option.
</simpara>
</note>
<tip>
<simpara>
If you have a non-default SSH configuration on the Barman
server, e.g. using a port other than 22, then you can set those
parameters in a dedicated Host section in <filename>~/.ssh/config</filename>
corresponding to the value of<varname>barman_host</varname> in
<filename>repmgr.conf</filename>. See the <literal>Host</literal>
section in <command>man 5 ssh_config</command> for more details.
</simpara>
</tip>
<para>
It's now possible to clone a standby from Barman, e.g.:
<programlisting>
NOTICE: using configuration file "/etc/repmgr.conf"
NOTICE: destination directory "/var/lib/postgresql/data" provided
INFO: connecting to Barman server to verify backup for test_cluster
INFO: checking and correcting permissions on existing directory "/var/lib/postgresql/data"
INFO: creating directory "/var/lib/postgresql/data/repmgr"...
INFO: connecting to Barman server to fetch server parameters
INFO: connecting to upstream node
INFO: connected to source node, checking its state
INFO: successfully connected to source node
DETAIL: current installation size is 29 MB
NOTICE: retrieving backup from Barman...
receiving file list ...
(...)
NOTICE: standby clone (from Barman) complete
NOTICE: you can now start your PostgreSQL server
HINT: for example: pg_ctl -D /var/lib/postgresql/data start</programlisting>
</para>
</sect2>
<sect2 id="cloning-from-barman-restore-command" xreflabel="Using Barman as a WAL file source">
<title>Using Barman as a WAL file source</title>
<para>
As a fallback in case streaming replication is interrupted, PostgreSQL can optionally
retrieve WAL files from an archive, such as that provided by Barman. This is done by
setting <varname>restore_command</varname> in <filename>recovery.conf</filename> to
a valid shell command which can retrieve a specified WAL file from the archive.
</para>
<para>
<command>barman-wal-restore</command> is a Python script provided as part of the <literal>barman-cli</literal>
package (Barman 2.0 and later; for Barman 1.x the script is provided separately as
<command>barman-wal-restore.py</command>) which performs this function for Barman.
</para>
<para>
To use <command>barman-wal-restore</command> with &repmgr;
and assuming Barman is located on the <literal>barmansrv</literal> host
and that <command>barman-wal-restore</command> is located as an executable at
<filename>/usr/bin/barman-wal-restore</filename>,
<filename>repmgr.conf</filename> should include the following lines:
<programlisting>
barman_host=barmansrv
barman_server=somedb
restore_command=/usr/bin/barman-wal-restore barmansrv somedb %f %p</programlisting>
</para>
<note>
<simpara>
<command>barman-wal-restore</command> supports command line switches to
control parallelism (<literal>--parallel=N</literal>) and compression (
<literal>--bzip2</literal>, <literal>--gzip</literal>).
</simpara>
</note>
<note>
<para>
To use a non-default Barman configuration file on the Barman server,
specify this in <filename>repmgr.conf</filename> with <filename>barman_config</filename>:
<programlisting>
barman_config=/path/to/barman.conf</programlisting>
</para>
</note>
</sect2>
</sect1>
<sect1 id="cloning-replication-slots" xreflabel="Cloning and replication slots">
<indexterm>
<primary>cloning</primary>
<secondary>replication slots</secondary>
</indexterm>
<indexterm>
<primary>replication slots</primary>
<secondary>cloning</secondary>
</indexterm>
<title>Cloning and replication slots</title>
<para>
Replication slots were introduced with PostgreSQL 9.4 and are designed to ensure
that any standby connected to the primary using a replication slot will always
be able to retrieve the required WAL files. This removes the need to manually
manage WAL file retention by estimating the number of WAL files that need to
be maintained on the primary using <varname>wal_keep_segments</varname>.
Do however be aware that if a standby is disconnected, WAL will continue to
accumulate on the primary until either the standby reconnects or the replication
slot is dropped.
</para>
<para>
To enable &repmgr; to use replication slots, set the boolean parameter
<varname>use_replication_slots</varname> in <filename>repmgr.conf</filename>:
<programlisting>
use_replication_slots=true
</programlisting>
</para>
<para>
Replication slots must be enabled in <filename>postgresql.conf</filename>` by
setting the parameter <varname>max_replication_slots</varname> to at least the
number of expected standbys (changes to this parameter require a server restart).
</para>
<para>
When cloning a standby, &repmgr; will automatically generate an appropriate
slot name, which is stored in the <literal>repmgr.nodes</literal> table, and create the slot
on the upstream node:
<programlisting>
repmgr=# SELECT node_id, upstream_node_id, active, node_name, type, priority, slot_name
FROM repmgr.nodes ORDER BY node_id;
node_id | upstream_node_id | active | node_name | type | priority | slot_name
---------+------------------+--------+-----------+---------+----------+---------------
1 | | t | node1 | primary | 100 | repmgr_slot_1
2 | 1 | t | node2 | standby | 100 | repmgr_slot_2
3 | 1 | t | node3 | standby | 100 | repmgr_slot_3
(3 rows)</programlisting>
<programlisting>
repmgr=# SELECT slot_name, slot_type, active, active_pid FROM pg_replication_slots ;
slot_name | slot_type | active | active_pid
---------------+-----------+--------+------------
repmgr_slot_2 | physical | t | 23658
repmgr_slot_3 | physical | t | 23687
(2 rows)</programlisting>
</para>
<para>
Note that a slot name will be created by default for the primary but not
actually used unless the primary is converted to a standby using e.g.
<command>repmgr standby switchover</command>.
</para>
<para>
Further information on replication slots in the PostgreSQL documentation:
<ulink url="https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION-SLOTS">https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION-SLOTS</ulink>
</para>
<tip>
<simpara>
While replication slots can be useful for streaming replication, it's
recommended to monitor for inactive slots as these will cause WAL files to
build up indefinitely, possibly leading to server failure.
</simpara>
<simpara>
As an alternative we recommend using 2ndQuadrant's <ulink url="https://www.pgbarman.org/">Barman</ulink>,
which offloads WAL management to a separate server, negating the need to use replication
slots to reserve WAL. See section <xref linkend="cloning-from-barman">
for more details on using &repmgr; together with Barman.
</simpara>
</tip>
</sect1>
<sect1 id="cloning-cascading" xreflabel="Cloning and cascading replication">
<indexterm>
<primary>cloning</primary>
<secondary>cascading replication</secondary>
</indexterm>
<title>Cloning and cascading replication</title>
<para>
Cascading replication, introduced with PostgreSQL 9.2, enables a standby server
to replicate from another standby server rather than directly from the primary,
meaning replication changes "cascade" down through a hierarchy of servers. This
can be used to reduce load on the primary and minimize bandwith usage between
sites. For more details, see the
<ulink url="https://www.postgresql.org/docs/current/static/warm-standby.html#CASCADING-REPLICATION">
PostgreSQL cascading replication documentation</ulink>.
</para>
<para>
&repmgr; supports cascading replication. When cloning a standby,
set the command-line parameter <literal>--upstream-node-id</literal> to the
<varname>node_id</varname> of the server the standby should connect to, and
&repmgr; will create <filename>recovery.conf</filename> to point to it. Note
that if <literal>--upstream-node-id</literal> is not explicitly provided,
&repmgr; will set the standby's <filename>recovery.conf</filename> to
point to the primary node.
</para>
<para>
To demonstrate cascading replication, first ensure you have a primary and standby
set up as shown in the <xref linkend="quickstart">.
Then create an additional standby server with <filename>repmgr.conf</filename> looking
like this:
<programlisting>
node_id=3
node_name=node3
conninfo='host=node3 user=repmgr dbname=repmgr'
data_directory='/var/lib/postgresql/data'</programlisting>
</para>
<para>
Clone this standby (using the connection parameters for the existing standby),
ensuring <literal>--upstream-node-id</literal> is provide with the <varname>node_id</varname>
of the previously created standby (if following the example, this will be <literal>2</literal>):
<programlisting>
$ repmgr -h node2 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone --upstream-node-id=2
NOTICE: using configuration file "/etc/repmgr.conf"
NOTICE: destination directory "/var/lib/postgresql/data" provided
INFO: connecting to upstream node
INFO: connected to source node, checking its state
NOTICE: checking for available walsenders on upstream node (2 required)
INFO: sufficient walsenders available on upstream node (2 required)
INFO: successfully connected to source node
DETAIL: current installation size is 29 MB
INFO: creating directory "/var/lib/postgresql/data"...
NOTICE: starting backup (using pg_basebackup)...
HINT: this may take some time; consider using the -c/--fast-checkpoint option
INFO: executing: 'pg_basebackup -l "repmgr base backup" -D /var/lib/postgresql/data -h node2 -U repmgr -X stream '
NOTICE: standby clone (using pg_basebackup) complete
NOTICE: you can now start your PostgreSQL server
HINT: for example: pg_ctl -D /var/lib/postgresql/data start</programlisting>
then register it (note that <literal>--upstream-node-id</literal> must be provided here
too):
<programlisting>
$ repmgr -f /etc/repmgr.conf standby register --upstream-node-id=2
NOTICE: standby node "node2" (ID: 2) successfully registered
</programlisting>
</para>
<para>
After starting the standby, the cluster will look like this, showing that <literal>node3</literal>
is attached to <literal>node2</literal>, not the primary (<literal>node1</literal>).
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr
</programlisting>
</para>
<tip>
<simpara>
Under some circumstances when setting up a cascading replication
cluster, you may wish to clone a downstream standby whose upstream node
does not yet exist. In this case you can clone from the primary (or
another upstream node); provide the parameter <literal>--upstream-conninfo</literal>
to explictly set the upstream's <varname>primary_conninfo</varname> string
in <filename>recovery.conf</filename>.
</simpara>
</tip>
</sect1>
<sect1 id="cloning-advanced" xreflabel="Advanced cloning options">
<indexterm>
<primary>cloning</primary>
<secondary>advanced options</secondary>
</indexterm>
<title>Advanced cloning options</title>
<sect2 id="cloning-advanced-pg-basebackup-options" xreflabel="pg_basebackup options when cloning a standby">
<title>pg_basebackup options when cloning a standby</title>
<para>
By default, <command>pg_basebackup</command> performs a checkpoint before beginning the backup
process. However, a normal checkpoint may take some time to complete;
a fast checkpoint can be forced with the <literal>-c/--fast-checkpoint</literal> option.
However this may impact performance of the server being cloned from
so should be used with care.
</para>
<para>
Further options can be passed to the <command>pg_basebackup</command> utility via
the setting <varname>pg_basebackup_options</varname> in <filename>repmgr.conf</filename>.
See the <ulink url="https://www.postgresql.org/docs/current/static/app-pgbasebackup.html">PostgreSQL pg_basebackup documentation</ulink>
for more details of available options.
</para>
</sect2>
<sect2 id="cloning-advanced-managing-passwords" xreflabel="Managing passwords">
<title>Managing passwords</title>
<para>
If replication connections to a standby's upstream server are password-protected,
the standby must be able to provide the password so it can begin streaming
replication.
</para>
<para>
The recommended way to do this is to store the password in the <literal>postgres</literal> system
user's <filename>~/.pgpass</filename> file. It's also possible to store the password in the
environment variable <varname>PGPASSWORD</varname>, however this is not recommended for
security reasons. For more details see the
<ulink url="https://www.postgresql.org/docs/current/static/libpq-pgpass.html">PostgreSQL password file documentation</ulink>.
</para>
<para>
If, for whatever reason, you wish to include the password in <filename>recovery.conf</filename>,
set <varname>use_primary_conninfo_password</varname> to <literal>true</literal> in
<filename>repmgr.conf</filename>. This will read a password set in <varname>PGPASSWORD</varname>
(but not <filename>~/.pgpass</filename>) and place it into the <literal>primary_conninfo</literal>
string in <filename>recovery.conf</filename>. Note that <varname>PGPASSWORD</varname>
will need to be set during any action which causes <filename>recovery.conf</filename> to be
rewritten, e.g. <xref linkend="repmgr-standby-follow">.
</para>
<para>
It is of course also possible to include the password value in the <varname>conninfo</varname>
string for each node, but this is obviously a security risk and should be
avoided.
</para>
</sect2>
<sect2 id="cloning-advanced-replication-user" xreflabel="Separate replication user">
<title>Separate replication user</title>
<para>
In some circumstances it might be desirable to create a dedicated replication-only
user (in addition to the user who manages the &repmgr; metadata). In this case,
the replication user should be set in <filename>repmgr.conf</filename> via the parameter
<varname>replication_user</varname>; &repmgr; will use this value when making
replication connections and generating <filename>recovery.conf</filename>. This
value will also be stored in the <literal>repmgr.nodes</literal>
table for each node; it no longer needs to be explicitly specified when
cloning a node or executing <xref linkend="repmgr-standby-follow">.
</para>
</sect2>
</sect1>
</chapter>

View File

@@ -0,0 +1,114 @@
<sect1 id="configuration-file-settings" xreflabel="configuration file settings">
<title>Configuration file settings</title>
<para>
Each <filename>repmgr.conf</filename> file must contain the following parameters:
</para>
<para>
<variablelist>
<varlistentry id="repmgr-conf-node-id" xreflabel="node_id">
<term><varname>node_id</varname> (<type>int</type>)
<indexterm>
<primary><varname>node_id</varname> configuration file parameter</primary>
</indexterm>
</term>
<listitem>
<para>
A unique integer greater than zero which identifies the node.
</para>
</listitem>
</varlistentry>
<varlistentry id="repmgr-conf-node-name" xreflabel="node_name">
<term><varname>node_name</varname> (<type>string</type>)
<indexterm>
<primary><varname>node_name</varname> configuration file parameter</primary>
</indexterm>
</term>
<listitem>
<para>
An arbitrary (but unique) string; we recommend using the server's hostname
or another identifier unambiguously associated with the server to avoid
confusion. Avoid choosing names which reflect the node's current role,
e.g. <varname>primary</varname> or <varname>standby1</varname>
as roles can change and if you end up in a solution where the current primary is
called <varname>standby1</varname> (for example), things will be confusing
to say the least.
</para>
</listitem>
</varlistentry>
<varlistentry id="repmgr-conf-conninfo" xreflabel="conninfo">
<term><varname>conninfo</varname> (<type>string</type>)
<indexterm>
<primary><varname>conninfo</varname> configuration file parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Database connection information as a conninfo string.
All servers in the cluster must be able to connect to
the local node using this string.
</para>
<para>
For details on conninfo strings, see section <ulink
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING">Connection Strings</>
in the PosgreSQL documentation.
</para>
<para>
If repmgrd is in use, consider explicitly setting
<varname>connect_timeout</varname> in the <varname>conninfo</varname>
string to determine the length of time which elapses before a network
connection attempt is abandoned; for details see <ulink
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT">
the PostgreSQL documentation</>.
</para>
</listitem>
</varlistentry>
<varlistentry id="repmgr-conf-data-directory" xreflabel="data_directory">
<term><varname>data_directory</varname> (<type>string</type>)
<indexterm>
<primary><varname>data_directory</varname> configuration file parameter</primary>
</indexterm>
</term>
<listitem>
<para>
The node's data directory. This is needed by repmgr
when performing operations when the PostgreSQL instance
is not running and there's no other way of determining
the data directory.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
For a full list of annotated configuration items, see the file
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>.
</para>
<note>
<para>
The following parameters in the configuration file can be overridden with
command line options:
<itemizedlist>
<listitem>
<simpara>
<literal>-L/--log-level</literal> overrides <literal>log_level</literal> in
<filename>repmgr.conf</filename>
</simpara>
</listitem>
<listitem>
<simpara>
<literal>-b/--pg_bindir</literal> overrides <literal>pg_bindir</literal> in
<filename>repmgr.conf</filename>
</simpara>
</listitem>
</itemizedlist>
</para>
</note>
</sect1>

View File

@@ -0,0 +1,46 @@
<sect1 id="configuration-file" xreflabel="configuration file location">
<title>Configuration file location</title>
<para>
<application>repmgr</application> and <application>repmgrd</application>
use a common configuration file, by default called
<filename>repmgr.conf</filename> (although any name can be used if explicitly specified).
<filename>repmgr.conf</filename> must contain a number of required parameters, including
the database connection string for the local node and the location
of its data directory; other values will be inferred from defaults if
not explicitly supplied. See section `configuration file parameters`
for more details.
</para>
<para>
The configuration file will be searched for in the following locations:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>a configuration file specified by the `-f/--config-file` command line option</para>
</listitem>
<listitem>
<para>
a location specified by the package maintainer (if <application>repmgr</application>
as installed from a package and the package maintainer has specified the configuration
file location)
</para>
</listitem>
<listitem>
<para><filename>repmgr.conf</filename> in the local directory</para>
</listitem>
<listitem>
<para><filename>/etc/repmgr.conf</filename></para>
</listitem>
<listitem>
<para>the directory reported by <application>pg_config --sysconfdir</application></para>
</listitem>
</itemizedlist>
</para>
<para>
Note that if a file is explicitly specified with <application>-f/--config-file</application>,
an error will be raised if it is not found or not readable and no attempt will be made to
check default locations; this is to prevent <application>repmgr</application> unexpectedly
reading the wrong file.
</para>
</sect1>

7
doc/configuration.sgml Normal file
View File

@@ -0,0 +1,7 @@
<chapter id="configuration" xreflabel="Configuration">
<title>repmgr configuration</title>
&configuration-file;
&configuration-file-settings;
</chapter>

View File

@@ -0,0 +1,181 @@
<chapter id="event-notifications" xreflabel="event notifications">
<title>Event Notifications</title>
<para>
Each time `repmgr` or `repmgrd` perform a significant event, a record
of that event is written into the `repmgr.events` table together with
a timestamp, an indication of failure or success, and further details
if appropriate. This is useful for gaining an overview of events
affecting the replication cluster. However note that this table has
advisory character and should be used in combination with the `repmgr`
and PostgreSQL logs to obtain details of any events.
</para>
<para>
Example output after a primary was registered and a standby cloned
and registered:
<programlisting>
repmgr=# SELECT * from repmgr.events ;
node_id | event | successful | event_timestamp | details
---------+------------------+------------+-------------------------------+-------------------------------------------------------------------------------------
1 | primary_register | t | 2016-01-08 15:04:39.781733+09 |
2 | standby_clone | t | 2016-01-08 15:04:49.530001+09 | Cloned from host 'repmgr_node1', port 5432; backup method: pg_basebackup; --force: N
2 | standby_register | t | 2016-01-08 15:04:50.621292+09 |
(3 rows)</programlisting>
</para>
<para>
Alternatively, use <xref linkend="repmgr-cluster-event"> to output a
formatted list of events.
</para>
<para>
Additionally, event notifications can be passed to a user-defined program
or script which can take further action, e.g. send email notifications.
This is done by setting the `event_notification_command` parameter in
`repmgr.conf`.
</para>
<para>
This parameter accepts the following format placeholders:
</para>
<variablelist>
<varlistentry>
<term><option>%n</option></term>
<listitem>
<para>
node ID
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>%e</option></term>
<listitem>
<para>
event type
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>%t</option></term>
<listitem>
<para>
success (1 or 0)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>%t</option></term>
<listitem>
<para>
timestamp
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>%d</option></term>
<listitem>
<para>
details
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
The values provided for <literal>%t</literal> and <literal>%d</literal>
will probably contain spaces, so should be quoted in the provided command
configuration, e.g.:
<programlisting>
event_notification_command='/path/to/some/script %n %e %s "%t" "%d"'
</programlisting>
</para>
<para>
Additionally the following format placeholders are available for the event
type <varname>bdr_failover</varname> and optionally <varname>bdr_recovery</varname>:
</para>
<variablelist>
<varlistentry>
<term><option>%c</option></term>
<listitem>
<para>
conninfo string of the next available node
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>%a</option></term>
<listitem>
<para>
name of the next available node
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
These should always be quoted.
</para>
<para>
By default, all notification types will be passed to the designated script;
the notification types can be filtered to explicitly named ones:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara><literal>primary_register</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_register</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_unregister</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_clone</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_promote</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_follow</literal></simpara>
</listitem>
<listitem>
<simpara><literal>standby_disconnect_manual</literal></simpara>
</listitem>
<listitem>
<simpara><literal>repmgrd_start</literal></simpara>
</listitem>
<listitem>
<simpara><literal>repmgrd_shutdown</literal></simpara>
</listitem>
<listitem>
<simpara><literal>repmgrd_failover_promote</literal></simpara>
</listitem>
<listitem>
<simpara><literal>repmgrd_failover_follow</literal></simpara>
</listitem>
<listitem>
<simpara><literal>bdr_failover</literal></simpara>
</listitem>
<listitem>
<simpara><literal>bdr_reconnect</literal></simpara>
</listitem>
<listitem>
<simpara><literal>bdr_recovery</literal></simpara>
</listitem>
<listitem>
<simpara><literal>bdr_register</literal></simpara>
</listitem>
<listitem>
<simpara><literal>bdr_unregister</literal></simpara>
</listitem>
</itemizedlist>
</para>
<para>
Note that under some circumstances (e.g. when no replication cluster primary
could be located), it will not be possible to write an entry into the
<literal>repmgr.events</literal>
table, in which case executing a script via <varname>event_notification_command</varname>
can serve as a fallback by generating some form of notification.
</para>
</chapter>

77
doc/filelist.sgml Normal file
View File

@@ -0,0 +1,77 @@
<!-- doc/filelist.sgml -->
<!ENTITY legal SYSTEM "legal.sgml">
<!ENTITY bookindex SYSTEM "bookindex.sgml">
<!--
Some parts of the documentation are also source for some plain-text
files used during installation. To selectively ignore or include
some parts (e.g., external xref's) when generating these files we use
these parameter entities. See also standalone-install.sgml.
-->
<!ENTITY % standalone-ignore "INCLUDE">
<!ENTITY % standalone-include "IGNORE">
<!-- doc/filelist.sgml -->
<!--
By default, no index is included. Use -i include-index on the command line
to include it.
-->
<!ENTITY % include-index "IGNORE">
<!--
Create empty index element for processing by XSLT stylesheet.
-->
<!ENTITY % include-xslt-index "IGNORE">
<!--
Include external documentation sections
-->
<!ENTITY overview SYSTEM "overview.sgml">
<!ENTITY install SYSTEM "install.sgml">
<!ENTITY install-requirements SYSTEM "install-requirements.sgml">
<!ENTITY install-packages SYSTEM "install-packages.sgml">
<!ENTITY install-source SYSTEM "install-source.sgml">
<!ENTITY quickstart SYSTEM "quickstart.sgml">
<!ENTITY configuration SYSTEM "configuration.sgml">
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
<!ENTITY configuration-file-settings SYSTEM "configuration-file-settings.sgml">
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
<!ENTITY switchover SYSTEM "switchover.sgml">
<!ENTITY event-notifications SYSTEM "event-notifications.sgml">
<!ENTITY upgrading-repmgr SYSTEM "upgrading-repmgr.sgml">
<!ENTITY repmgrd-automatic-failover SYSTEM "repmgrd-automatic-failover.sgml">
<!ENTITY repmgrd-configuration SYSTEM "repmgrd-configuration.sgml">
<!ENTITY repmgrd-demonstration SYSTEM "repmgrd-demonstration.sgml">
<!ENTITY repmgrd-monitoring SYSTEM "repmgrd-monitoring.sgml">
<!ENTITY repmgrd-degraded-monitoring SYSTEM "repmgrd-degraded-monitoring.sgml">
<!ENTITY repmgrd-cascading-replication SYSTEM "repmgrd-cascading-replication.sgml">
<!ENTITY repmgrd-network-split SYSTEM "repmgrd-network-split.sgml">
<!ENTITY repmgr-primary-register SYSTEM "repmgr-primary-register.sgml">
<!ENTITY repmgr-primary-unregister SYSTEM "repmgr-primary-unregister.sgml">
<!ENTITY repmgr-standby-clone SYSTEM "repmgr-standby-clone.sgml">
<!ENTITY repmgr-standby-register SYSTEM "repmgr-standby-register.sgml">
<!ENTITY repmgr-standby-unregister SYSTEM "repmgr-standby-unregister.sgml">
<!ENTITY repmgr-standby-promote SYSTEM "repmgr-standby-promote.sgml">
<!ENTITY repmgr-standby-follow SYSTEM "repmgr-standby-follow.sgml">
<!ENTITY repmgr-standby-switchover SYSTEM "repmgr-standby-switchover.sgml">
<!ENTITY repmgr-node-status SYSTEM "repmgr-node-status.sgml">
<!ENTITY repmgr-node-check SYSTEM "repmgr-node-check.sgml">
<!ENTITY repmgr-node-rejoin SYSTEM "repmgr-node-rejoin.sgml">
<!ENTITY repmgr-cluster-show SYSTEM "repmgr-cluster-show.sgml">
<!ENTITY repmgr-cluster-matrix SYSTEM "repmgr-cluster-matrix.sgml">
<!ENTITY repmgr-cluster-crosscheck SYSTEM "repmgr-cluster-crosscheck.sgml">
<!ENTITY repmgr-cluster-event SYSTEM "repmgr-cluster-event.sgml">
<!ENTITY repmgr-cluster-cleanup SYSTEM "repmgr-cluster-cleanup.sgml">
<!ENTITY appendix-signatures SYSTEM "appendix-signatures.sgml">
<!ENTITY bookindex SYSTEM "bookindex.sgml">

View File

@@ -0,0 +1,42 @@
<chapter id="follow-new-primary" xreflabel="Following a new primary">
<title>Following a new primary</title>
<para>
Following the failure or removal of the replication cluster's existing primary
server, <xref linkend="repmgr-standby-follow"> can be used to make 'orphaned' standbys
follow the new primary and catch up to its current state.
</para>
<para>
To demonstrate this, assuming a replication cluster in the same state as the
end of the preceding section (<xref linkend="promoting-standby">),
execute this:
<programlisting>
$ repmgr -f /etc/repmgr.conf repmgr standby follow
INFO: changing node 3's primary to node 2
NOTICE: restarting server using "pg_ctl -l /var/log/postgresql/startup.log -w -D '/var/lib/postgresql/data' restart"
waiting for server to shut down......... done
server stopped
waiting for server to start.... done
server started
NOTICE: STANDBY FOLLOW successful
DETAIL: node 3 is now attached to node 2
</programlisting>
</para>
<para>
The standby is now replicating from the new primary and `repmgr cluster show`
output reflects this:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
Note that with cascading replication, <command>repmgr standby follow</command> can also be
used to detach a standby from its current upstream server and follow the
primary. However it's currently not possible to have it follow another standby;
we hope to improve this in a future release.
</para>
</chapter>

32
doc/install-packages.sgml Normal file
View File

@@ -0,0 +1,32 @@
<sect1 id="installation-packages" xreflabel="Installing from packages">
<title>Installing &repmgr; from packages</title>
<para>
We recommend installing `repmgr` using the available packages for your
system.
</para>
<sect2 id="installation-packages-redhat" xreflabel="Installing from packages on RHEL, Fedora and CentOS">
<title>RedHat/Fedora/CentOS</title>
<para>
RPM packages for `repmgr` are available via Yum through
the PostgreSQL Global Development Group RPM repository
( <ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</>).
Follow the instructions for your distribution (RedHat, CentOS,
Fedora, etc.) and architecture as detailed at yum.postgresql.org.
</para>
<para>
2ndQuadrant also provides its own RPM packages which are made available
at the same time as each `repmgr` release, as it can take some days for
them to become available via the main PGDG repository. See here for details:
<ulink url="http://repmgr.org/yum-repository.html">http://repmgr.org/yum-repository.html</>
</para>
</sect2>
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
<title>Debian/Ubuntu</title>
<para>.deb packages for `repmgr` are available from the
PostgreSQL Community APT repository (<ulink url="http://apt.postgresql.org/">http://apt.postgresql.org/</> ).
Instructions can be found in the APT section of the PostgreSQL Wiki
(<ulink url="https://wiki.postgresql.org/wiki/Apt">https://wiki.postgresql.org/wiki/Apt</> ).
</para>
</sect2>
</sect1>

View File

@@ -0,0 +1,67 @@
<sect1 id="install-requirements" xreflabel="installation requirements">
<title>Requirements for installing repmgr</title>
<para>
repmgr is developed and tested on Linux and OS X, but should work on any
UNIX-like system supported by PostgreSQL itself. There is no support for
Microsoft Windows.
</para>
<para>
From version 4.0, repmgr is compatible with all PostgreSQL versions from 9.4, including PostgreSQL 10.
</para>
<para>
PostgreSQL 9.3 is supported by repmgr 3.3.
</para>
<note>
<simpara>
If upgrading from `repmgr 3`, please see the separate upgrade guide
`doc/upgrading-from-repmgr3.md`.
</simpara>
</note>
<para>
All servers in the replication cluster must be running the same major version of
PostgreSQL, and we recommend that they also run the same minor version.
</para>
<para>
`repmgr` must be installed on each server in the replication cluster.
If installing repmgr from packages, the package version must match the PostgreSQL
version. If installing from source, repmgr must be compiled against the same
major version.
</para>
<para>
A dedicated system user for `repmgr` is *not* required; as many `repmgr` and
`repmgrd` actions require direct access to the PostgreSQL data directory,
these commands should be executed by the `postgres` user.
</para>
<para>
Passwordless `ssh` connectivity between all servers in the replication cluster
is not required, but is necessary in the following cases:
<itemizedlist>
<listitem>
<simpara>if you need `repmgr` to copy configuration files from outside the PostgreSQL
data directory (in which case `rsync` is also required)</simpara>
</listitem>
<listitem>
<simpara>to perform switchover operations</simpara>
</listitem>
<listitem>
<simpara>when executing `repmgr cluster matrix` and `repmgr cluster crosscheck`</simpara>
</listitem>
</itemizedlist>
</para>
<tip>
<simpara>
We recommend using a session multiplexer utility such as `screen` or
`tmux` when performing long-running actions (such as cloning a database)
on a remote server - this will ensure the `repmgr` action won't be prematurely
terminated if your `ssh` session to the server is interrupted or closed.
</simpara>
</tip>
</sect1>

139
doc/install-source.sgml Normal file
View File

@@ -0,0 +1,139 @@
<sect1 id="installation-source" xreflabel="Installing from source code">
<title>Installing &repmgr; from source</title>
<sect2 id="installation-source-prereqs">
<title>Prerequisites for installing from source</title>
<para>
To install &repmgr; the prerequisites for compiling
&postgres; must be installed. These are described in &postgres;'s
documentation
on <ulink url="https://www.postgresql.org/docs/current/install-requirements.html">build requirements</ulink>
and <ulink url="https://www.postgresql.org/docs/current/docguide-toolsets.html">build requirements for documentation</ulink>.
</para>
<para>
Most mainstream Linux distributions and other UNIX variants provide simple
ways to install the prerequisites from packages.
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
<literal>Debian</literal> and <literal>Ubuntu</literal>: First
add the <ulink
url="http://apt.postgresql.org/">apt.postgresql.org</ulink>
repository to your <filename>sources.list</filename> if you
have not already done so. Then install the pre-requisites for
building PostgreSQL with:
<programlisting>
sudo apt-get update
sudo apt-get build-dep postgresql-9.6
</programlisting>
</para>
</listitem>
<listitem>
<para>
<literal>RHEL or CentOS 6.x or 7.x</literal>: install the appropriate repository RPM
for your system from <ulink url="https://yum.postgresql.org/repopackages.php">
yum.postgresql.org</ulink>. Then install the prerequisites for building
PostgreSQL with:
<programlisting>
sudo yum check-update
sudo yum groupinstall "Development Tools"
sudo yum install yum-utils openjade docbook-dtds docbook-style-dsssl docbook-style-xsl
sudo yum-builddep postgresql96
</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
<note>
<simpara>
Select the appropriate PostgreSQL versions for your target repmgr version.
</simpara>
</note>
</sect2>
<sect2 id="installation-get-source">
<title>Getting &repmgr; source code</title>
<para>
There are two ways to get the &repmgr; source code: with git, or by downloading tarballs of released versions.
</para>
<sect3>
<title>Using <application>git</application> to get the &repmgr; sources</title>
<para>
Use <application><ulink url="https://git-scm.com">git</ulink></application> if you expect
to update often, you want to keep track of development or if you want to contribute
changes to &repmgr;. There is no reason <emphasis>not</emphasis> to use <application>git</application>
if you're familiar with it.
</para>
<para>
The source for &repmgr; is maintained at
<ulink url="https://github.com/2ndQuadrant/repmgr">https://github.com/2ndQuadrant/repmgr</ulink>.
</para>
<para>
There are also tags for each &repmgr; release, e.g. <filename>REL4_0_STABLE</filename>.
</para>
<para>
Clone the source code using <application>git</application>:
<programlisting>
git clone https://github.com/2ndQuadrant/repmgr
</programlisting>
</para>
<para>
For more information on using <application>git</application> see
<ulink url="https://git-scm.com/">git-scm.com</ulink>.
</para>
</sect3>
<sect3>
<title>Downloading release source tarballs</title>
<para>
Official release source code is uploaded as tarballs to the
&repmgr; website along with a tarball checksum and a matching GnuPG
signature. See
<ulink url="http://repmgr.org/">http://repmgr.org/</ulink>
for the download information. See <xref linkend="appendix-signatures">
for information on verifying digital signatures.
</para>
<para>
You will need to download the repmgr source, e.g. <filename>repmgr-4.0.tar.gz</filename>.
You may optionally verify the package checksums from the
<literal>.md5</literal> files and/or verify the GnuPG signatures
per <xref linkend="appendix-signatures">.
</para>
<para>
After you unpack the source code archives using <literal>tar xf</literal>
the installation process is the same as if you were installing from a git
clone.
</para>
</sect3>
</sect2>
<sect2 id="installation-repmgr-source">
<title>Installation of &repmgr; from source</title>
<para>
To installing &repmgr; from source, simply execute:
<programlisting>
./configure && make install
</programlisting>
Ensure `pg_config` for the target PostgreSQL version is in `$PATH`.
</para>
</sect2>
</sect1>

24
doc/install.sgml Normal file
View File

@@ -0,0 +1,24 @@
<chapter id="installation" xreflabel="Installation">
<title>Installation</title>
<para>
&repmgr; can be installed from binary packages provided by your operating
system's packaging system, or from source.
</para>
<para>
In general we recommend using binary packages, unless unavailable for your operating system.
</para>
<para>
Source installs are mainly useful if you want to keep track of the very
latest repmgr development and contribute to development. They're also the
only option if there are no packages for your operating system yet.
</para>
<para>
Before installing &repmgr; make sure you satisfy the <xref linkend="install-requirements">.
</para>
&install-requirements;
&install-packages;
&install-source;
</chapter>

20
doc/legal.sgml Normal file
View File

@@ -0,0 +1,20 @@
<!-- doc/src/sgml/legal.sgml -->
<date>2017</date>
<copyright>
<year>2010-2017</year>
<holder>2ndQuadrant, Ltd.</holder>
</copyright>
<legalnotice id="legalnotice">
<title>Legal Notice</title>
<para>
<productname>repmgr</productname> is Copyright &copy; 2010-2017
by 2ndQuadrant, Ltd.
</para>
<para>add license</para>
</legalnotice>

209
doc/overview.sgml Normal file
View File

@@ -0,0 +1,209 @@
<chapter id="overview" xreflabel="Overview">
<title>repmgr overview</title>
<para>
This chapter provides a high-level overview of repmgr's components and functionality.
</para>
<sect1 id="repmgr-concepts" xreflabel="Concepts">
<title>Concepts</title>
<para>
This guide assumes that you are familiar with PostgreSQL administration and
streaming replication concepts. For further details on streaming
replication, see the PostgreSQL documentation section on <ulink
url="https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION">
streaming replication</>.
</para>
<para>
The following terms are used throughout the `repmgr` documentation.
<variablelist>
<varlistentry>
<term>replication cluster</term>
<listitem>
<simpara>
In the `repmgr` documentation, "replication cluster" refers to the network
of PostgreSQL servers connected by streaming replication.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>node</term>
<listitem>
<simpara>
A node is a server within a replication cluster.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>upstream node</term>
<listitem>
<simpara>
The node a standby server connects to, in order to receive streaming replication.
This is either the primary server or in the case of cascading replication, another
standby.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>failover</term>
<listitem>
<simpara>
This is the action which occurs if a primary server fails and a suitable standby
is promoted as the new primary. The `repmgrd` daemon supports automatic failover
to minimise downtime.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>switchover</term>
<listitem>
<simpara>
In certain circumstances, such as hardware or operating system maintenance,
it's necessary to take a primary server offline; in this case a controlled
switchover is necessary, whereby a suitable standby is promoted and the
existing primary removed from the replication cluster in a controlled manner.
The `repmgr` command line client provides this functionality.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>fencing</term>
<listitem>
<simpara>
In a failover situation, following the promotion of a new standby, it's
essential that the previous primary does not unexpectedly come back on
line, which would result in a split-brain situation. To prevent this,
the failed primary should be isolated from applications, i.e. "fenced off".
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect1>
<sect1 id="repmgr-components" xreflabel="Components">
<title>Components</title>
<para>
`repmgr` is a suite of open-source tools to manage replication and failover
within a cluster of PostgreSQL servers. It supports and enhances PostgreSQL's
built-in streaming replication, which provides a single read/write primary server
and one or more read-only standbys containing near-real time copies of the primary
server's database. It provides two main tools:
<variablelist>
<varlistentry>
<term>repmgr</term>
<listitem>
<para>
A command-line tool used to perform administrative tasks such as:
<itemizedlist>
<listitem>
<simpara>setting up standby servers</simpara>
</listitem>
<listitem>
<simpara>promoting a standby server to primary</simpara>
</listitem>
<listitem>
<simpara>switching over primary and standby servers</simpara>
</listitem>
<listitem>
<simpara>displaying the status of servers in the replication cluster</simpara>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>repmgrd</term>
<listitem>
<para>
A daemon which actively monitors servers in a replication cluster
and performs the following tasks:
<itemizedlist>
<listitem>
<simpara>monitoring and recording replication performance</simpara>
</listitem>
<listitem>
<simpara>performing failover by detecting failure of the primary and
promoting the most suitable standby server
</simpara>
</listitem>
<listitem>
<simpara>provide notifications about events in the cluster to a user-defined
script which can perform tasks such as sending alerts by email</simpara>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect1>
<sect1 id="repmgr-user-metadata" xreflabel="Repmgr user and metadata">
<title>Repmgr user and metadata</title>
<para>
In order to effectively manage a replication cluster, `repmgr` needs to store
information about the servers in the cluster in a dedicated database schema.
This schema is automatically by the `repmgr` extension, which is installed
during the first step in initialising a `repmgr`-administered cluster
(`repmgr primary register`) and contains the following objects:
<variablelist>
<varlistentry>
<term>Tables</term>
<listitem>
<para>
<itemizedlist>
<listitem>
<simpara>repmgr.events: records events of interest</simpara>
</listitem>
<listitem>
<simpara>repmgr.nodes: connection and status information for each server in the
replication cluster</simpara>
</listitem>
<listitem>
<simpara>repmgr.monitoring_history: historical standby monitoring information written by `repmgrd`</simpara>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Views</term>
<listitem>
<para>
<itemizedlist>
<listitem>
<simpara>repmgr.show_nodes: based on the table `repl_nodes`, additionally showing the
name of the server's upstream node</simpara>
</listitem>
<listitem>
<simpara>repmgr.replication_status: when `repmgrd`'s monitoring is enabled, shows current monitoring
status for each standby.</simpara>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The `repmgr` metadata schema can be stored in an existing database or in its own
dedicated database. Note that the `repmgr` metadata schema cannot reside on a database
server which is not part of the replication cluster managed by `repmgr`.
</para>
<para>
A database user must be available for `repmgr` to access this database and perform
necessary changes. This user does not need to be a superuser, however some operations
such as initial installation of the `repmgr` extension will require a superuser
connection (this can be specified where required with the command line option
`--superuser`).
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,75 @@
<chapter id="promoting-standby" xreflabel="Promoting a standby">
<title>Promoting a standby server with repmgr</title>
<para>
If a primary server fails or needs to be removed from the replication cluster,
a new primary server must be designated, to ensure the cluster continues
to function correctly. This can be done with <xref linkend="repmgr-standby-promote">,
which promotes the standby on the current server to primary.
</para>
<para>
To demonstrate this, set up a replication cluster with a primary and two attached
standby servers so that the cluster looks like this:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
Stop the current primary with e.g.:
<programlisting>
$ pg_ctl -D /var/lib/postgresql/data -m fast stop</programlisting>
</para>
<para>
At this point the replication cluster will be in a partially disabled state, with
both standbys accepting read-only connections while attempting to connect to the
stopped primary. Note that the &repmgr; metadata table will not yet have been updated;
executing <xref linkend="repmgr-cluster-show"> will note the discrepancy:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+---------------+----------+----------+--------------------------------------
1 | node1 | primary | ? unreachable | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr
WARNING: following issues were detected
node "node1" (ID: 1) is registered as an active primary but is unreachable</programlisting>
</para>
<para>
Now promote the first standby with:
<programlisting>
$ repmgr -f /etc/repmgr.conf standby promote</programlisting>
</para>
<para>
This will produce output similar to the following:
<programlisting>
INFO: connecting to standby database
NOTICE: promoting standby
DETAIL: promoting server using "pg_ctl -l /var/log/postgresql/startup.log -w -D '/var/lib/postgresql/data' promote"
server promoting
INFO: reconnecting to promoted server
NOTICE: STANDBY PROMOTE successful
DETAIL: node 2 was successfully promoted to primary</programlisting>
</para>
<para>
Executing <xref linkend="repmgr-cluster-show"> will show the current state; as there is now an
active primary, the previous warning will not be displayed:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
However the sole remaining standby (<literal>node3</literal>) is still trying to replicate from the failed
primary; <xref linkend="repmgr-standby-follow"> must now be executed to rectify this situation
(see <xref linkend="follow-new-primary"> for example).
</para>
</chapter>

446
doc/quickstart.sgml Normal file
View File

@@ -0,0 +1,446 @@
<chapter id="quickstart" xreflabel="Quick-start guide">
<title>Quick-start guide</title>
<para>
This section gives a quick introduction to &repmgr;, including setting up a
sample &repmgr; installation and a basic replication cluster.
</para>
<para>
These instructions are not suitable for a production install, as they may not
take into account security considerations, proper system administration
procedures etc..
</para>
<sect1 id="quickstart-prerequisites">
<title>Prerequisites for setting up a basic replication cluster with &repmgr;</title>
<para>
The following section will describe how to set up a basic replication cluster
with a primary and a standby server using the <application>repmgr</application>
command line tool.
</para>
<para>
We'll assume the primary is called <literal>node1</literal> with IP address
<literal>192.168.1.11</literal>, and the standby is called <literal>node2</literal>
with IP address <literal>192.168.1.12</literal>
</para>
<para>
Following software must be installed on both servers:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara><application>PostgreSQL</application></simpara>
</listitem>
<listitem>
<simpara>
<application>repmgr</application> (matching the installed
<application>PostgreSQL</application> major version)
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
At network level, connections between the PostgreSQL port (default: <literal>5432</literal>)
must be possible in both directions.
</para>
<para>
If you want <application>repmgr</application> to copy configuration files which are
located outside the PostgreSQL data directory, and/or to test <command>switchover</command>
functionality, you will also need passwordless SSH connections between both servers, and
<application>rsync</application> should be installed.
</para>
<tip>
<simpara>
For testing <application>repmgr</application>, it's possible to use multiple PostgreSQL
instances running on different ports on the same computer, with
passwordless SSH access to <filename>localhost</filename> enabled.
</simpara>
</tip>
</sect1>
<sect1 id="quickstart-postgresql-configuration">
<title>PostgreSQL configuration</title>
<para>
On the primary server, a PostgreSQL instance must be initialised and running.
The following replication settings may need to be adjusted:
</para>
<programlisting>
# Enable replication connections; set this figure to at least one more
# than the number of standbys which will connect to this server
# (note that repmgr will execute `pg_basebackup` in WAL streaming mode,
# which requires two free WAL senders)
max_wal_senders = 10
# Ensure WAL files contain enough information to enable read-only queries
# on the standby.
#
# PostgreSQL 9.5 and earlier: one of 'hot_standby' or 'logical'
# PostgreSQL 9.6 and later: one of 'replica' or 'logical'
# ('hot_standby' will still be accepted as an alias for 'replica')
#
# See: https://www.postgresql.org/docs/current/static/runtime-config-wal.html#GUC-WAL-LEVEL
wal_level = 'hot_standby'
# Enable read-only queries on a standby
# (Note: this will be ignored on a primary but we recommend including
# it anyway)
hot_standby = on
# Enable WAL file archiving
archive_mode = on
# Set archive command to a script or application that will safely store
# you WALs in a secure place. /bin/true is an example of a command that
# ignores archiving. Use something more sensible.
archive_command = '/bin/true'
# If you have configured `pg_basebackup_options`
# in `repmgr.conf` to include the setting `--xlog-method=fetch` (from
# PostgreSQL 10 `--wal-method=fetch`), *and* you have not set
# `restore_command` in `repmgr.conf`to fetch WAL files from another
# source such as Barman, you'll need to set `wal_keep_segments` to a
# high enough value to ensure that all WAL files generated while
# the standby is being cloned are retained until the standby starts up.
#
# wal_keep_segments = 5000
</programlisting>
<tip>
<simpara>
Rather than editing these settings in the default <filename>postgresql.conf</filename>
file, create a separate file such as <filename>postgresql.replication.conf</filename> and
include it from the end of the main configuration file with:
<command>include 'postgresql.replication.conf</command>.
</simpara>
</tip>
</sect1>
<sect1 id="quickstart-repmgr-user-database">
<title>Create the repmgr user and database</title>
<para>
Create a dedicated PostgreSQL superuser account and a database for
the &repmgr; metadata, e.g.
</para>
<programlisting>
createuser -s repmgr
createdb repmgr -O repmgr
</programlisting>
<para>
For the examples in this document, the name <literal>repmgr</literal> will be
used for both user and database, but any names can be used.
</para>
<note>
<para>
For the sake of simplicity, the <literal>repmgr</literal> user is created
as a superuser. If desired, it's possible to create the <literal>repmgr</literal>
user as a normal user. However for certain operations superuser permissions
are requiredl; in this case the command line option <command>--superuser</command>
can be provided to specify a superuser.
</para>
<para>
It's also assumed that the <literal>repmgr</literal> user will be used to make the
replication connection from the standby to the primary; again this can be
overridden by specifying a separate replication user when registering each node.
</para>
</note>
<tip>
<para>
&repmgr; will install the <literal>repmgr</literal> extension, which creates a
<literal>repmgr</literal> schema containing the &repmgr;'s metadata tables as
well as other functions and views. We also recommend that you set the
<literal>repmgr</literal> user's search path to include this schema name, e.g.
<programlisting>
ALTER USER repmgr SET search_path TO repmgr, "$user", public;</programlisting>
</para>
</tip>
</sect1>
<sect1 id="quickstart-authentication">
<title>Configuring authentication in pg_hba.conf</title>
<para>
Ensure the <literal>repmgr</literal> user has appropriate permissions in <filename>pg_hba.conf</filename> and
can connect in replication mode; <filename>pg_hba.conf</filename> should contain entries
similar to the following:
</para>
<programlisting>
local replication repmgr trust
host replication repmgr 127.0.0.1/32 trust
host replication repmgr 192.168.1.0/24 trust
local repmgr repmgr trust
host repmgr repmgr 127.0.0.1/32 trust
host repmgr repmgr 192.168.1.0/24 trust
</programlisting>
<para>
Note that these are simple settings for testing purposes.
Adjust according to your network environment and authentication requirements.
</para>
</sect1>
<sect1 id="quickstart-standby-preparation">
<title>Preparing the standby</title>
<para>
On the standby, do not create a PostgreSQL instance, but do ensure the destination
data directory (and any other directories which you want PostgreSQL to use)
exist and are owned by the <literal>postgres</literal> system user. Permissions
must be set to <literal>0700</literal> (<literal>drwx------</literal>).
</para>
<para>
Check the primary database is reachable from the standby using <application>psql</application>:
</para>
<programlisting>
psql 'host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlisting>
<note>
<para>
&repmgr; stores connection information as <ulink
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING">libpq
connection strings</ulink> throughout. This documentation refers to them as <literal>conninfo</literal>
strings; an alternative name is <literal>DSN</literal> (<literal>data source name</literal>).
We'll use these in place of the <command>-h hostname -d databasename -U username</command> syntax.
</para>
</note>
</sect1>
<sect1 id="quickstart-repmgr-conf">
<title>repmgr configuration file</title>
<para>
Create a <filename>repmgr.conf</filename> file on the primary server. The file must
contain at least the following parameters:
</para>
<programlisting>
node_id=1
node_name=node1
conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/data'
</programlisting>
<para>
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
as it could be overwritten when setting up or reinitialising the PostgreSQL
server. See sections on <xref linkend="configuration-file"> and <xref linkend="configuration-file-settings">
for further details about <filename>repmgr.conf</filename>.
</para>
<tip>
<simpara>
For Debian-based distributions we recommend explictly setting
<literal>pg_bindir</literal> to the directory where <command>pg_ctl</command> and other binaries
not in the standard path are located. For PostgreSQL 9.6 this would be <filename>/usr/lib/postgresql/9.6/bin/</filename>.
</simpara>
</tip>
<para>
See the file
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>
for details of all available configuration parameters.
</para>
</sect1>
<sect1 id="quickstart-primary-register">
<title>Register the primary server</title>
<para>
To enable &repmgr; to support a replication cluster, the primary node must
be registered with &repmgr;. This installs the <literal>repmgr</literal>
extension and metadata objects, and adds a metadata record for the primary server:
</para>
<programlisting>
$ repmgr -f /etc/repmgr.conf primary register
INFO: connecting to primary database...
NOTICE: attempting to install extension "repmgr"
NOTICE: "repmgr" extension successfully installed
NOTICE: primary node record (id: 1) registered</programlisting>
<para>
Verify status of the cluster like this:
</para>
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Connection string
----+-------+---------+-----------+----------+--------------------------------------------------------
1 | node1 | primary | * running | | host=node1 dbname=repmgr user=repmgr connect_timeout=2
</programlisting>
<para>
The record in the <literal>repmgr</literal> metadata table will look like this:
</para>
<programlisting>
repmgr=# SELECT * FROM repmgr.nodes;
-[ RECORD 1 ]----+-------------------------------------------------------
node_id | 1
upstream_node_id |
active | t
node_name | node1
type | primary
location | default
priority | 100
conninfo | host=node1 dbname=repmgr user=repmgr connect_timeout=2
repluser | repmgr
slot_name |
config_file | /etc/repmgr.conf</programlisting>
<para>
Each server in the replication cluster will have its own record. If <command>repmgrd</command>
is in use, the fields <literal>upstream_node_id</literal>, <literal>active</literal> and
<literal>type</literal> will be updated when the node's status or role changes.
</para>
</sect1>
<sect1 id="quickstart-standby-clone">
<title>Clone the standby server</title>
<para>
Create a <filename>repmgr.conf</filename> file on the standby server. It must contain at
least the same parameters as the primary's <filename>repmgr.conf</filename>, but with
the mandatory values <literal>node</literal>, <literal>node_name</literal>, <literal>conninfo</literal>
(and possibly <literal>data_directory</literal>) adjusted accordingly, e.g.:
</para>
<programlisting>
node=2
node_name=node2
conninfo='host=node2 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/data'
</programlisting>
<para>
Use the <command>--dry-run</command> option to check the standby can be cloned:
</para>
<programlisting>
$ repmgr -h node1 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone --dry-run
NOTICE: using provided configuration file "/etc/repmgr.conf"
NOTICE: destination directory "/var/lib/postgresql/data" provided
INFO: connecting to source node
NOTICE: checking for available walsenders on source node (2 required)
INFO: sufficient walsenders available on source node (2 required)
NOTICE: standby will attach to upstream node 1
HINT: consider using the -c/--fast-checkpoint option
INFO: all prerequisites for "standby clone" are met</programlisting>
<para>
If no problems are reported, the standby can then be cloned with:
</para>
<programlisting>
$ repmgr -h node1 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone
NOTICE: using configuration file "/etc/repmgr.conf"
NOTICE: destination directory "/var/lib/postgresql/data" provided
INFO: connecting to source node
NOTICE: checking for available walsenders on source node (2 required)
INFO: sufficient walsenders available on source node (2 required)
INFO: creating directory "/var/lib/postgresql/data"...
NOTICE: starting backup (using pg_basebackup)...
HINT: this may take some time; consider using the -c/--fast-checkpoint option
INFO: executing:
pg_basebackup -l "repmgr base backup" -D /var/lib/postgresql/data -h node1 -U repmgr -X stream
NOTICE: standby clone (using pg_basebackup) complete
NOTICE: you can now start your PostgreSQL server
HINT: for example: pg_ctl -D /var/lib/postgresql/data start
</programlisting>
<para>
This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal>
using PostgreSQL's <command>pg_basebackup</command> utility. A <filename>recovery.conf</filename>
file containing the correct parameters to start streaming from this primary server will be created
automatically.
</para>
<note>
<simpara>
By default, any configuration files in the primary's data directory will be
copied to the standby. Typically these will be <filename>postgresql.conf</filename>,
<filename>postgresql.auto.conf</filename>, <filename>pg_hba.conf</filename> and
<filename>pg_ident.conf</filename>. These may require modification before the standby
is started.
</simpara>
</note>
<para>
Make any adjustments to the standby's PostgreSQL configuration files now,
then start the server.
</para>
<para>
For more details on <command>repmgr standby clone</command>, see the
<link linkend="repmgr-standby-clone">command reference</link>.
A more detailed overview of cloning options is available in the
<link linkend="cloning-standbys">administration manual</link>.
</para>
</sect1>
<sect1 id="quickstart-verify-replication">
<title>Verify replication is functioning</title>
<para>
Connect to the primary server and execute:
<programlisting>
repmgr=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 19111
usesysid | 16384
usename | repmgr
application_name | node2
client_addr | 192.168.1.12
client_hostname |
client_port | 50378
backend_start | 2017-08-28 15:14:19.851581+09
backend_xmin |
state | streaming
sent_location | 0/7000318
write_location | 0/7000318
flush_location | 0/7000318
replay_location | 0/7000318
sync_priority | 0
sync_state | async</programlisting>
This shows that the previously cloned standby (<literal>node2</literal> shown in the field
<literal>application_name</literal>) has connected to the primary from IP address
<literal>192.168.1.12</literal>.
</para>
<para>
From PostgreSQL 9.6 you can also use the view
<ulink url="https://www.postgresql.org/docs/current/static/monitoring-stats.html#PG-STAT-WAL-RECEIVER-VIEW">
<literal>pg_stat_wal_receiver</literal></ulink> to check the replication status from the standby.
<programlisting>
repmgr=# SELECT * FROM pg_stat_wal_receiver;
Expanded display is on.
-[ RECORD 1 ]---------+--------------------------------------------------------------------------------
pid | 18236
status | streaming
receive_start_lsn | 0/3000000
receive_start_tli | 1
received_lsn | 0/7000538
received_tli | 1
last_msg_send_time | 2017-08-28 15:21:26.465728+09
last_msg_receipt_time | 2017-08-28 15:21:26.465774+09
latest_end_lsn | 0/7000538
latest_end_time | 2017-08-28 15:20:56.418735+09
slot_name |
conninfo | user=repmgr dbname=replication host=node1 application_name=node2
</programlisting>
Note that the <varname>conninfo</varname> value is that generated in <filename>recovery.conf</filename>
and will differ slightly from the primary's <varname>conninfo</varname> as set in <filename>repmgr.conf</filename> -
among others it will contain the connecting node's name as <varname>application_name</varname>.
</para>
</sect1>
<sect1 id="quickstart-register-standby">
<title>Register the standby</title>
<para>
Register the standby server with:
<programlisting>
$ repmgr -f /etc/repmgr.conf standby register
NOTICE: standby node "node2" (ID: 2) successfully registered</programlisting>
</para>
<para>
Check the node is registered by executing <command>repmgr cluster show</command> on the standby:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
Both nodes are now registered with &repmgr; and the records have been copied to the standby server.
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,23 @@
<chapter id="repmgr-cluster-cleanup" xreflabel="repmgr cluster cleanup">
<indexterm>
<primary>repmgr cluster cleanup</primary>
</indexterm>
<title>repmgr cluster cleanup</title>
<para>
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
prevent excessive table growth. Use the <literal>-k/--keep-history</literal> to specify the
number of days of monitoring history to retain. This command can be used
manually or as a cronjob.
</para>
<para>
This command requires a valid <filename>repmgr.conf</filename> file for the node on which it is
executed; no additional arguments are required.
</para>
<note>
<simpara>
Monitoring history will only be written if <command>repmgrd</command> is active, and
<varname>monitoring_history</varname> is set to <literal>true</literal> in
<filename>repmgr.conf</filename>.
</simpara>
</note>
</chapter>

View File

@@ -0,0 +1,28 @@
<chapter id="repmgr-cluster-crosscheck" xreflabel="repmgr cluster crosscheck">
<indexterm>
<primary>repmgr cluster crosscheck</primary>
</indexterm>
<title>repmgr cluster crosscheck</title>
<para>
<command>repmgr cluster crosscheck</command> is similar to <xref linkend="repmgr-cluster-matrix">,
but cross-checks connections between each combination of nodes. In "Example 3" in
<xref linkend="repmgr-cluster-matrix"> we have no information about the state of <literal>node3</literal>.
However by running <command>repmgr cluster crosscheck</command> it's possible to get a better
overview of the cluster situation:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster crosscheck
Name | Id | 1 | 2 | 3
-------+----+----+----+----
node1 | 1 | * | * | x
node2 | 2 | * | * | *
node3 | 3 | * | * | *</programlisting>
</para>
<para>
What happened is that <command>repmgr cluster crosscheck</command> merged its own
<command>repmgr cluster matrix</command> with the <command>repmgr cluster matrix</command>
output from <literal>node2</literal>; the latter is able to connect to <literal>node3</literal>
and therefore determine the state of outbound connections from that node.
</para>
</chapter>

View File

@@ -0,0 +1,37 @@
<chapter id="repmgr-cluster-event" xreflabel="repmgr cluster event">
<indexterm>
<primary>repmgr cluster event</primary>
</indexterm>
<title>repmgr cluster event</title>
<para>
This outputs a formatted list of cluster events, as stored in the
<literal>repmgr.events</literal> table. Output is in reverse chronological order, and
can be filtered with the following options:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara><literal>--all</literal>: outputs all entries</simpara>
</listitem>
<listitem>
<simpara><literal>--limit</literal>: set the maximum number of entries to output (default: 20)</simpara>
</listitem>
<listitem>
<simpara><literal>--node-id</literal>: restrict entries to node with this ID</simpara>
</listitem>
<listitem>
<simpara><literal>--node-name</literal>: restrict entries to node with this name</simpara>
</listitem>
<listitem>
<simpara><literal>--event</literal>: filter specific event</simpara>
</listitem>
</itemizedlist>
</para>
<para>
Example:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster event --event=standby_register
Node ID | Name | Event | OK | Timestamp | Details
---------+-------+------------------+----+---------------------+--------------------------------
3 | node3 | standby_register | t | 2017-08-17 10:28:55 | standby registration succeeded
2 | node2 | standby_register | t | 2017-08-17 10:28:53 | standby registration succeeded</programlisting>
</para>
</chapter>

View File

@@ -0,0 +1,83 @@
<chapter id="repmgr-cluster-matrix" xreflabel="repmgr cluster matrix">
<indexterm>
<primary>repmgr cluster matrix</primary>
</indexterm>
<title>repmgr cluster matrix</title>
<para>
<command>repmgr cluster matrix</command> runs <command>repmgr cluster show</command> on each
node and arranges the results in a matrix, recording success or failure.
</para>
<para>
<command>repmgr cluster matrix</command> requires a valid <filename>repmgr.conf</filename>
file on each node. Additionally passwordless `ssh` connections are required between
all nodes.
</para>
<para>
Example 1 (all nodes up):
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster matrix
Name | Id | 1 | 2 | 3
-------+----+----+----+----
node1 | 1 | * | * | *
node2 | 2 | * | * | *
node3 | 3 | * | * | *</programlisting>
</para>
<para>
Example 2 (<literal>node1</literal> and <literal>node2</literal> up, <literal>node3</literal> down):
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster matrix
Name | Id | 1 | 2 | 3
-------+----+----+----+----
node1 | 1 | * | * | x
node2 | 2 | * | * | x
node3 | 3 | ? | ? | ?
</programlisting>
</para>
<para>
Each row corresponds to one server, and indicates the result of
testing an outbound connection from that server.
</para>
<para>
Since <literal>node3</literal> is down, all the entries in its row are filled with
<literal>?</literal>, meaning that there we cannot test outbound connections.
</para>
<para>
The other two nodes are up; the corresponding rows have <literal>x</literal> in the
column corresponding to <literal>node3</literal>, meaning that inbound connections to
that node have failed, and `*` in the columns corresponding to
<literal>node1</literal> and <literal>node2</literal>, meaning that inbound connections
to these nodes have succeeded.
</para>
<para>
Example 3 (all nodes up, firewall dropping packets originating
from <literal>node1</literal> and directed to port 5432 on <literal>node3</literal>) -
running <command>repmgr cluster matrix</command> from <literal>node1</literal> gives the following output:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster matrix
Name | Id | 1 | 2 | 3
-------+----+----+----+----
node1 | 1 | * | * | x
node2 | 2 | * | * | *
node3 | 3 | ? | ? | ?</programlisting>
</para>
<para>
Note this may take some time depending on the <varname>connect_timeout</varname>
setting in the node <varname>conninfo</varname> strings; default is
<literal>1 minute</literal> which means without modification the above
command would take around 2 minutes to run; see comment elsewhere about setting
<varname>connect_timeout</varname>)
</para>
<para>
The matrix tells us that we cannot connect from <literal>node1</literal> to <literal>node3</literal>,
and that (therefore) we don't know the state of any outbound
connection from <literal>node3</literal>.
</para>
<para>
In this case, the <xref linkend="repmgr-cluster-crosscheck"> command will produce a more
useful result.
</para>
</chapter>

View File

@@ -0,0 +1,67 @@
<chapter id="repmgr-cluster-show" xreflabel="repmgr cluster show">
<indexterm>
<primary>repmgr cluster show</primary>
</indexterm>
<title>repmgr cluster show</title>
<para>
Displays information about each active node in the replication cluster. This
command polls each registered server and shows its role (<literal>primary</literal> /
<literal>standby</literal> / <literal>bdr</literal>) and status. It polls each server
directly and can be run on any node in the cluster; this is also useful when analyzing
connectivity from a particular node.
</para>
<para>
This command requires either a valid <filename>repmgr.conf</filename> file or a database
connection string to one of the registered nodes; no additional arguments are needed.
</para>
<para>
Example:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+-----------------------------------------
1 | node1 | primary | * running | | default | host=db_node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=db_node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=db_node3 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
To show database connection errors when polling nodes, run the command in
<literal>--verbose</literal> mode.
</para>
<para>
The `cluster show` command accepts an optional parameter <literal>--csv</literal>, which
outputs the replication cluster's status in a simple CSV format, suitable for
parsing by scripts:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show --csv
1,-1,-1
2,0,0
3,0,1</programlisting>
</para>
<para>
The columns have following meanings:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>
node ID
</simpara>
<simpara>
availability (0 = available, -1 = unavailable)
</simpara>
<simpara>
recovery state (0 = not in recovery, 1 = in recovery, -1 = unknown)
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
Note that the availability is tested by connecting from the node where
<command>repmgr cluster show</command> is executed, and does not necessarily imply the node
is down. See <xref linkend="repmgr-cluster-matrix"> and <xref linkend="repmgr-cluster-crosscheck"> to get
a better overviews of connections between nodes.
</para>
</chapter>

View File

@@ -0,0 +1,70 @@
<chapter id="repmgr-node-check" xreflabel="repmgr node check">
<indexterm>
<primary>repmgr node check</primary>
</indexterm>
<title>repmgr node check</title>
<para>
Performs some health checks on a node from a replication perspective.
This command must be run on the local node.
</para>
<para>
Sample output (execute <command>repmgr node check</command>):
<programlisting>
Node "node1":
Server role: OK (node is primary)
Replication lag: OK (N/A - node is primary)
WAL archiving: OK (0 pending files)
Downstream servers: OK (2 of 2 downstream nodes attached)
Replication slots: OK (node has no replication slots)
</programlisting>
</para>
<para>
Additionally each check can be performed individually by supplying
an additional command line parameter, e.g.:
<programlisting>
$ repmgr node check --role
OK (node is primary)
</programlisting>
</para>
<para>
Parameters for individual checks are as follows:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>
<literal>--role</literal>: checks if the node has the expected role
</simpara>
</listitem>
<listitem>
<simpara>
<literal>--replication-lag</literal>: checks if the node is lagging by more than
<varname>replication_lag_warning</varname> or <varname>replication_lag_critical</varname>
</simpara>
</listitem>
<listitem>
<simpara>
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived
</simpara>
</listitem>
<listitem>
<simpara>
<literal>--downstream</literal>: checks that the expected downstream nodes are attached
</simpara>
</listitem>
<listitem>
<simpara>
<literal>--slots</literal>: checks there are no inactive replication slots
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
Individual checks can also be output in a Nagios-compatible format by additionally
providing the option <literal>--nagios</literal>.
</para>
</chapter>

View File

@@ -0,0 +1,13 @@
<chapter id="repmgr-node-rejoin" xreflabel="repmgr node rejoin">
<indexterm>
<primary>repmgr node rejoin</primary>
</indexterm>
<title>repmgr node rejoin</title>
<para>
Enables a dormant (stopped) node to be rejoined to the replication cluster.
</para>
<para>
This can optionally use <command>pg_rewind</command> to re-integrate a node which has diverged
from the rest of the cluster, typically a failed primary.
</para>
</chapter>

View File

@@ -0,0 +1,29 @@
<chapter id="repmgr-node-status" xreflabel="repmgr node status">
<indexterm>
<primary>repmgr node status</primary>
</indexterm>
<title>repmgr node status</title>
<para>
Displays an overview of a node's basic information and replication
status. This command must be run on the local node.
</para>
<para>
Sample output (execute <command>repmgr node status</command>):
<programlisting>
Node "node1":
PostgreSQL version: 10beta1
Total data size: 30 MB
Conninfo: host=node1 dbname=repmgr user=repmgr connect_timeout=2
Role: primary
WAL archiving: off
Archive command: (none)
Replication connections: 2 (of maximal 10)
Replication slots: 0 (of maximal 10)
Replication lag: n/a
</programlisting>
</para>
<para>
See <xref linkend="repmgr-node-check"> to diagnose issues.
</para>
</chapter>

View File

@@ -0,0 +1,18 @@
<chapter id="repmgr-primary-register" xreflabel="repmgr primary register">
<indexterm><primary>repmgr primary register</primary></indexterm>
<title>repmgr primary register</title>
<para>
<command>repmgr primary register</command> registers a primary node in a
streaming replication cluster, and configures it for use with repmgr, including
installing the &repmgr; extension. This command needs to be executed before any
standby nodes are registered.
</para>
<para>
Execute with the <literal>--dry-run</literal> option to check what would happen without
actually registering the primary.
</para>
<para>
<command>repmgr master register</command> can be used as an alias for
<command>repmgr primary register</command>.
</para>
</chapter>

View File

@@ -0,0 +1,18 @@
<chapter id="repmgr-primary-unregister" xreflabel="repmgr primary unregister">
<indexterm><primary>repmgr primary unregister</primary></indexterm>
<title>repmgr primary unregister</title>
<para>
<command>repmgr primary register</command> unregisters an inactive primary node
from the &repmgr; metadata. This is typically when the primary has failed and is
being removed from the cluster after a new primary has been promoted.
</para>
<para>
Execute with the <literal>--dry-run</literal> option to check what would happen without
actually unregistering the node.
</para>
<para>
<command>repmgr master unregister</command> can be used as an alias for
<command>repmgr primary unregister</command>/
</para>
</chapter>

View File

@@ -0,0 +1,91 @@
<chapter id="repmgr-standby-clone" xreflabel="repmgr standby clone">
<indexterm>
<primary>repmgr standby clone</primary>
<seealso>cloning</seealso>
</indexterm>
<title>repmgr standby clone</title>
<para>
<command>repmgr standby clone</command> clones a PostgreSQL node from another
PostgreSQL node, typically the primary, but optionally from any other node in
the cluster or from Barman. It creates the <filename>recovery.conf</filename> file required
to attach the cloned node to the primary node (or another standby, if cascading replication
is in use).
</para>
<note>
<simpara>
<command>repmgr standby clone</command> does not start the standby, and after cloning
<command>repmgr standby register</command> must be executed to notify &repmgr; of its presence.
</simpara>
</note>
<sect1 id="repmgr-standby-clone-config-file-copying" xreflabel="Copying configuration files">
<title>Handling configuration files</title>
<para>
Note that by default, all configuration files in the source node's data
directory will be copied to the cloned node. Typically these will be
<filename>postgresql.conf</filename>, <filename>postgresql.auto.conf</filename>,
<filename>pg_hba.conf</filename> and <filename>pg_ident.conf</filename>.
These may require modification before the standby is started.
</para>
<para>
In some cases (e.g. on Debian or Ubuntu Linux installations), PostgreSQL's
configuration files are located outside of the data directory and will
not be copied by default. &repmgr; can copy these files, either to the same
location on the standby server (provided appropriate directory and file permissions
are available), or into the standby's data directory. This requires passwordless
SSH access to the primary server. Add the option <literal>--copy-external-config-files</literal>
to the <command>repmgr standby clone</command> command; by default files will be copied to
the same path as on the upstream server. Note that the user executing <command>repmgr</command>
must have write access to those directories.
</para>
<para>
To have the configuration files placed in the standby's data directory, specify
<literal>--copy-external-config-files=pgdata</literal>, but note that
any include directives in the copied files may need to be updated.
</para>
<tip>
<simpara>
For reliable configuration file management we recommend using a
configuration management tool such as Ansible, Chef, Puppet or Salt.
</simpara>
</tip>
</sect1>
<sect1 id="repmgr-standby-clone-wal-management" xreflabel="Managing WAL during the cloning process">
<title>Managing WAL during the cloning process</title>
<para>
When initially cloning a standby, you will need to ensure
that all required WAL files remain available while the cloning is taking
place. To ensure this happens when using the default `pg_basebackup` method,
&repmgr; will set <command>pg_basebackup</command>'s <literal>--xlog-method</literal>
parameter to <literal>stream</literal>,
which will ensure all WAL files generated during the cloning process are
streamed in parallel with the main backup. Note that this requires two
replication connections to be available (&repmgr; will verify sufficient
connections are available before attempting to clone, and this can be checked
before performing the clone using the <literal>--dry-run</literal> option).
</para>
<para>
To override this behaviour, in <filename>repmgr.conf</filename> set
<command>pg_basebackup</command>'s <literal>--xlog-method</literal>
parameter to <literal>fetch</literal>:
<programlisting>
pg_basebackup_options='--xlog-method=fetch'</programlisting>
and ensure that <literal>wal_keep_segments</literal> is set to an appropriately high value.
See the <ulink url="https://www.postgresql.org/docs/current/static/app-pgbasebackup.html">
pg_basebackup</ulink> documentation for details.
</para>
<note>
<simpara>
From PostgreSQL 10, <command>pg_basebackup</command>'s
<literal>--xlog-method</literal> parameter has been renamed to
<literal>--wal-method</literal>.
</simpara>
</note>
</sect1>
</chapter>

View File

@@ -0,0 +1,21 @@
<chapter id="repmgr-standby-follow" xreflabel="repmgr standby follow">
<indexterm>
<primary>repmgr standby follow</primary>
</indexterm>
<title>repmgr standby follow</title>
<para>
Attaches the standby to a new primary. This command requires a valid
<filename>repmgr.conf</filename> file for the standby, either specified
explicitly with <literal>-f/--config-file</literal> or located in a
default location; no additional arguments are required.
</para>
<para>
This command will force a restart of the standby server, which must be
running. It can only be used to attach a standby to a new primary node.
</para>
<para>
To re-add an inactive node to the replication cluster, see
<xref linkend="repmgr-node-rejoin">
</para>
</chapter>

View File

@@ -0,0 +1,18 @@
<chapter id="repmgr-standby-promote" xreflabel="repmgr standby promote">
<indexterm>
<primary>repmgr standby promote</primary>
</indexterm>
<title>repmgr standby promote</title>
<para>
Promotes a standby to a primary if the current primary has failed. This
command requires a valid <filename>repmgr.conf</filename> file for the standby, either
specified explicitly with <literal>-f/--config-file</literal> or located in a
default location; no additional arguments are required.
</para>
<para>
If the standby promotion succeeds, the server will not need to be
restarted. However any other standbys will need to follow the new server,
by using <xref linkend="repmgr-standby-follow">; if <command>repmgrd</command>
is active, it will handle this automatically.
</para>
</chapter>

View File

@@ -0,0 +1,50 @@
<chapter id="repmgr-standby-register" xreflabel="repmgr standby register">
<indexterm><primary>repmgr standby register</primary></indexterm>
<title>repmgr standby register</title>
<para>
<command>repmgr standby register</command> adds a standby's information to
the &repmgr; metadata. This command needs to be executed to enable
promote/follow operations and to allow <command>repmgrd</command> to work with the node.
An existing standby can be registered using this command. Execute with the
<literal>--dry-run</literal> option to check what would happen without actually registering the
standby.
</para>
<sect1 id="repmgr-standby-register-wait" xreflabel="repmgr standby register --wait">
<title>Waiting for the registration to propagate to the standby</title>
<para>
Depending on your environment and workload, it may take some time for
the standby's node record to propagate from the primary to the standby. Some
actions (such as starting <command>repmgrd</command>) require that the standby's node record
is present and up-to-date to function correctly.
</para>
<para>
By providing the option <literal>--wait-sync</literal> to the
<command>repmgr standby register</command> command, &repmgr; will wait
until the record is synchronised before exiting. An optional timeout (in
seconds) can be added to this option (e.g. <literal>--wait-sync=60</literal>).
</para>
</sect1>
<sect1 id="rempgr-standby-register-inactive-node" xreflabel="Registering an inactive node">
<title>Registering an inactive node</title>
<para>
Under some circumstances you may wish to register a standby which is not
yet running; this can be the case when using provisioning tools to create
a complex replication cluster. In this case, by using the <literal>-F/--force</literal>
option and providing the connection parameters to the primary server,
the standby can be registered.
</para>
<para>
Similarly, with cascading replication it may be necessary to register
a standby whose upstream node has not yet been registered - in this case,
using <literal>-F/--force</literal> will result in the creation of an inactive placeholder
record for the upstream node, which will however later need to be registered
with the <literal>-F/--force</literal> option too.
</para>
<para>
When used with <command>repmgr standby register</command>, care should be taken that use of the
<literal>-F/--force</literal> option does not result in an incorrectly configured cluster.
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,27 @@
<chapter id="repmgr-standby-switchover" xreflabel="repmgr standby switchover">
<indexterm>
<primary>repmgr standby switchover</primary>
</indexterm>
<title>repmgr standby switchover</title>
<para>
Promotes a standby to primary and demotes the existing primary to a standby.
This command must be run on the standby to be promoted, and requires a
passwordless SSH connection to the current primary.
</para>
<para>
If other standbys are connected to the demotion candidate, &repmgr; can instruct
these to follow the new primary if the option <literal>--siblings-follow</literal>
is specified.
</para>
<para>
Execute with the <literal>--dry-run</literal> option to test the switchover as far as
possible without actually changing the status of either node.
</para>
<para>
<command>repmgrd</command> should not be active on any nodes while a switchover is being
executed. This restriction may be lifted in a later version.
</para>
<para>
For more details see the section <xref linkend="performing-switchover">.
</para>
</chapter>

View File

@@ -0,0 +1,29 @@
<chapter id="repmgr-standby-unregister" xreflabel="repmgr standby unregister">
<indexterm><primary>repmgr standby unregister</primary></indexterm>
<title>repmgr standby unregister</title>
<para>
Unregisters a standby with `repmgr`. This command does not affect the actual
replication, just removes the standby's entry from the &repmgr; metadata.
</para>
<para>
To unregister a running standby, execute:
<programlisting>
repmgr standby unregister -f /etc/repmgr.conf</programlisting>
</para>
<para>
This will remove the standby record from &repmgr;'s internal metadata
table (<literal>repmgr.nodes</literal>). A <literal>standby_unregister</literal>
event notification will be recorded in the <literal>repmgr.events</literal> table.
</para>
<para>
If the standby is not running, the command can be executed on another
node by providing the id of the node to be unregistered using
the command line parameter <literal>--node-id</literal>, e.g. executing the following
command on the master server will unregister the standby with
id <literal>3</literal>:
<programlisting>
repmgr standby unregister -f /etc/repmgr.conf --node-id=3
</programlisting>
</para>
</chapter>

117
doc/repmgr.sgml Normal file
View File

@@ -0,0 +1,117 @@
<!-- doc/src/sgml/postgres.sgml -->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
<!ENTITY % version SYSTEM "version.sgml">
%version;
<!ENTITY % filelist SYSTEM "filelist.sgml">
%filelist;
<!ENTITY repmgr "<productname>repmgr</productname>">
<!ENTITY postgres "<productname>PostgreSQL</productname>">
]>
<book id="repmgr">
<title>repmgr &repmgrversion; Documentation</title>
<bookinfo>
<corpauthor>2ndQuadrant Ltd</corpauthor>
<productname>repmgr</productname>
<productnumber>&repmgrversion;</productnumber>
&legal;
<abstract>
<para>
Thisis the official documentation of &repmgr; &repmgrversion; for
use with PostgreSQL 9.3 - PostgreSQL 10.
It describes the functionality supported by the current version of &repmgr;.
</para>
<para>
repmgr was developed by
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
along with contributions from other individuals and companies.
Contributions from the community are appreciated and welcome - get
in touch via <ulink url="https://github.com/2ndQuadrant/repmgr">github</>
or <ulink url="https://groups.google.com/group/repmgr">the mailing list/forum</>.
Multiple 2ndQuadrant customers contribute funding
to make repmgr development possible.
</para>
<para>
2ndQuadrant, a Platinum sponsor of the PostgreSQL project,
continues to develop repmgr to meet internal needs and those of customers.
Other companies as well as individual developers
are welcome to participate in the efforts.
</para>
</abstract>
<keywordset>
<keyword>repmgr</keyword>
<keyword>PostgreSQL</keyword>
<keyword>replication</keyword>
<keyword>asynchronous</keyword>
<keyword>HA</keyword>
<keyword>high-availability</keyword>
</keywordset>
</bookinfo>
<part id="getting-started">
<title>Getting started</title>
&overview;
&install;
&quickstart;
</part>
<part id="repmgr-administration-manual">
<title>repmgr administration manual</title>
&configuration;
&cloning-standbys;
&promoting-standby;
&follow-new-primary;
&switchover;
&event-notifications;
&upgrading-repmgr;
</part>
<part id="using-repmgrd">
<title>Using repmgrd</title>
&repmgrd-automatic-failover;
&repmgrd-configuration;
&repmgrd-demonstration;
&repmgrd-cascading-replication;
&repmgrd-network-split;
&repmgrd-degraded-monitoring;
&repmgrd-monitoring;
</part>
<part id="repmgr-command-reference">
<title>repmgr command reference</title>
&repmgr-primary-register;
&repmgr-primary-unregister;
&repmgr-standby-clone;
&repmgr-standby-register;
&repmgr-standby-unregister;
&repmgr-standby-promote;
&repmgr-standby-follow;
&repmgr-standby-switchover;
&repmgr-node-status;
&repmgr-node-check;
&repmgr-node-rejoin;
&repmgr-cluster-show;
&repmgr-cluster-matrix;
&repmgr-cluster-crosscheck;
&repmgr-cluster-event;
&repmgr-cluster-cleanup;
</part>
&appendix-signatures;
<![%include-index;[&bookindex;]]>
<![%include-xslt-index;[<index id="bookindex"></index>]]>
</book>

View File

@@ -0,0 +1,12 @@
<chapter id="repmgrd-automatic-failover" xreflabel="Automatic failover with repmgrd">
<title>Automatic failover with repmgrd</title>
<para>
<command>repmgrd</command> is a management and monitoring daemon which runs
on each node in a replication cluster. It can automate actions such as
failover and updating standbys to follow the new primary, as well as
providing monitoring information about the state of each standby.
</para>
</chapter>

View File

@@ -0,0 +1,17 @@
<chapter id="repmgrd-cascading-replication">
<title>repmgrd and cascading replication</title>
<para>
Cascading replication - where a standby can connect to an upstream node and not
the primary server itself - was introduced in PostgreSQL 9.2. &repmgr; and
<command>repmgrd</command> support cascading replication by keeping track of the relationship
between standby servers - each node record is stored with the node id of its
upstream ("parent") server (except of course the primary server).
</para>
<para>
In a failover situation where the primary node fails and a top-level standby
is promoted, a standby connected to another standby will not be affected
and continue working as normal (even if the upstream standby it's connected
to becomes the primary node). If however the node's direct upstream fails,
the "cascaded standby" will attempt to reconnect to that node's parent.
</para>
</chapter>

View File

@@ -0,0 +1,94 @@
<chapter id="repmgrd-configuration">
<title>repmgrd configuration</title>
<para>
To use <command>repmgrd</command>, its associated function library must be
included in <filename>postgresql.conf</filename> with:
<programlisting>
shared_preload_libraries = 'repmgr'</programlisting>
</para>
<para>
Changing this setting requires a restart of PostgreSQL; for more details see
the <ulink url="https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
</para>
<para>
Additionally the following <command>repmgrd</command> options *must* be set in
<filename>repmgr.conf</filename> (adjust configuration file locations as appropriate):
<programlisting>
failover=automatic
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
follow_command='repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
</para>
<para>
Note that the <literal>--log-to-file</literal> option will cause
output generated by the &repmgr; command, when executed by <command>repmgrd</command>,
to be logged to the same destination configured to receive log output for <command>repmgrd</command>.
See <filename>repmgr.conf.sample</filename> for further <command>repmgrd</command>-specific settings.
</para>
<para>
When <varname>failover</varname> is set to <literal>automatic</literal>, upon detecting failure
of the current primary, <command>repmgrd</command> will execute one of
<varname>promote_command</varname> or <varname>follow_command</varname>,
depending on whether the current server is to become the new primary, or
needs to follow another server which has become the new primary. Note that
these commands can be any valid shell script which results in one of these
two actions happening, but if &repmgr;'s <command>standby follow</command> or
<command>standby promote</command>
commands are not executed (either directly as shown here, or from a script which
performs other actions), the &repmgr; metadata will not be updated and
&repmgr; will no longer function reliably.
</para>
<para>
The <varname>follow_command</varname> should provide the <literal>--upstream-node-id=%n</literal>
option to <command>repmgr standby follow</command>; the <literal>%n</literal> will be replaced by
<command>repmgrd</command> with the ID of the new primary node. If this is not provided, &repmgr;
will attempt to determine the new primary by itself, but if the
original primary comes back online after the new primary is promoted, there is a risk that
<command>repmgr standby follow</command> will result in the node continuing to follow
the original primary.
</para>
<sect1 id="repmgrd-connection-settings">
<title>repmgrd connection settings</title>
<para>
In addition to the &repmgr; configuration settings, parameters in the
<varname>conninfo</varname> string influence how &repmgr; makes a network connection to
PostgreSQL. In particular, if another server in the replication cluster
is unreachable at network level, system network settings will influence
the length of time it takes to determine that the connection is not possible.
</para>
<para>
In particular explicitly setting a parameter for <literal>connect_timeout</literal>
should be considered; the effective minimum value of <literal>2</literal>
(seconds) will ensure that a connection failure at network level is reported
as soon as possible, otherwise depending on the system settings (e.g.
<varname>tcp_syn_retries</varname> in Linux) a delay of a minute or more
is possible.
</para>
<para>
For further details on <varname>conninfo</varname> network connection
parameters, see the
<ulink url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS">PostgreSQL documentation</ulink>.
</para>
</sect1>
<sect1 id="repmgrd-log-rotation">
<title>repmgrd log rotation</title>
<para>
To ensure the current <command>repmgrd</command> logfile does not grow
indefinitely, configure your system's <command>logrotate</command> to
regularly rotate it.
</para>
<para>
Sample configuration to rotate logfiles weekly with retention for
up to 52 weeks and rotation forced if a file grows beyond 100Mb:
<programlisting>
/var/log/postgresql/repmgr-9.6.log {
missingok
compress
rotate 52
maxsize 100M
weekly
create 0600 postgres postgres
}</programlisting>
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,70 @@
<chapter id="repmgrd-degraded-monitoring">
<title>"degraded monitoring" mode</title>
<para>
In certain circumstances, <command>repmgrd</command> is not able to fulfill its primary mission
of monitoring the nodes' upstream server. In these cases it enters "degraded
monitoring" mode, where <command>repmgrd</command> remains active but is waiting for the situation
to be resolved.
</para>
<para>
Situations where this happens are:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>a failover situation has occurred, no nodes in the primary node's location are visible</simpara>
</listitem>
<listitem>
<simpara>a failover situation has occurred, but no promotion candidate is available</simpara>
</listitem>
<listitem>
<simpara>a failover situation has occurred, but the promotion candidate could not be promoted</simpara>
</listitem>
<listitem>
<simpara>a failover situation has occurred, but the node was unable to follow the new primary</simpara>
</listitem>
<listitem>
<simpara>a failover situation has occurred, but no primary has become available</simpara>
</listitem>
<listitem>
<simpara>a failover situation has occurred, but automatic failover is not enabled for the node</simpara>
</listitem>
<listitem>
<simpara>repmgrd is monitoring the primary node, but it is not available</simpara>
</listitem>
</itemizedlist>
</para>
<para>
Example output in a situation where there is only one standby with <literal>failover=manual</literal>,
and the primary node is unavailable (but is later restarted):
<programlisting>
[2017-08-29 10:59:19] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state (automatic failover disabled)
[2017-08-29 10:59:33] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
[2017-08-29 10:59:33] [INFO] checking state of node 1, 1 of 5 attempts
[2017-08-29 10:59:33] [INFO] sleeping 1 seconds until next reconnection attempt
(...)
[2017-08-29 10:59:37] [INFO] checking state of node 1, 5 of 5 attempts
[2017-08-29 10:59:37] [WARNING] unable to reconnect to node 1 after 5 attempts
[2017-08-29 10:59:37] [NOTICE] this node is not configured for automatic failover so will not be considered as promotion candidate
[2017-08-29 10:59:37] [NOTICE] no other nodes are available as promotion candidate
[2017-08-29 10:59:37] [HINT] use "repmgr standby promote" to manually promote this node
[2017-08-29 10:59:37] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state (automatic failover disabled)
[2017-08-29 10:59:53] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state (automatic failover disabled)
[2017-08-29 11:00:45] [NOTICE] reconnected to upstream node 1 after 68 seconds, resuming monitoring
[2017-08-29 11:00:57] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state (automatic failover disabled)</programlisting>
</para>
<para>
By default, <literal>repmgrd</literal> will continue in degraded monitoring mode indefinitely.
However a timeout (in seconds) can be set with <varname>degraded_monitoring_timeout</varname>,
after which <command>repmgrd</command> will terminate.
</para>
</chapter>

View File

@@ -0,0 +1,96 @@
<chapter id="repmgrd-demonstration">
<title>repmgrd demonstration</title>
<para>
To demonstrate automatic failover, set up a 3-node replication cluster (one primary
and two standbys streaming directly from the primary) so that the cluster looks
something like this:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr </programlisting>
</para>
<para>
Start <command>repmgrd</command> on each standby and verify that it's running by examining the
log output, which at log level <literal>INFO</literal> will look like this:
<programlisting>
[2017-08-24 17:31:00] [NOTICE] using configuration file "/etc/repmgr.conf"
[2017-08-24 17:31:00] [INFO] connecting to database "host=node2 dbname=repmgr user=repmgr"
[2017-08-24 17:31:00] [NOTICE] starting monitoring of node <literal>node2</literal> (ID: 2)
[2017-08-24 17:31:00] [INFO] monitoring connection to upstream node "node1" (node ID: 1) </programlisting>
</para>
<para>
Each <command>repmgrd</command> should also have recorded its successful startup as an event:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster event --event=repmgrd_start
Node ID | Name | Event | OK | Timestamp | Details
---------+-------+---------------+----+---------------------+-------------------------------------------------------------
3 | node3 | repmgrd_start | t | 2017-08-24 17:35:54 | monitoring connection to upstream node "node1" (node ID: 1)
2 | node2 | repmgrd_start | t | 2017-08-24 17:35:50 | monitoring connection to upstream node "node1" (node ID: 1)
1 | node1 | repmgrd_start | t | 2017-08-24 17:35:46 | monitoring cluster primary "node1" (node ID: 1) </programlisting>
</para>
<para>
Now stop the current primary server with e.g.:
<programlisting>
pg_ctl -D /var/lib/postgresql/data -m immediate stop</programlisting>
</para>
<para>
This will force the primary to shut down straight away, aborting all processes
and transactions. This will cause a flurry of activity in the <command>repmgrd</command> log
files as each <command>repmgrd</command> detects the failure of the primary and a failover
decision is made. This is an extract from the log of a standby server (<literal>node2</literal>)
which has promoted to new primary after failure of the original primary (<literal>node1</literal>).
<programlisting>
[2017-08-24 23:32:01] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state
[2017-08-24 23:32:08] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
[2017-08-24 23:32:08] [INFO] checking state of node 1, 1 of 5 attempts
[2017-08-24 23:32:08] [INFO] sleeping 1 seconds until next reconnection attempt
[2017-08-24 23:32:09] [INFO] checking state of node 1, 2 of 5 attempts
[2017-08-24 23:32:09] [INFO] sleeping 1 seconds until next reconnection attempt
[2017-08-24 23:32:10] [INFO] checking state of node 1, 3 of 5 attempts
[2017-08-24 23:32:10] [INFO] sleeping 1 seconds until next reconnection attempt
[2017-08-24 23:32:11] [INFO] checking state of node 1, 4 of 5 attempts
[2017-08-24 23:32:11] [INFO] sleeping 1 seconds until next reconnection attempt
[2017-08-24 23:32:12] [INFO] checking state of node 1, 5 of 5 attempts
[2017-08-24 23:32:12] [WARNING] unable to reconnect to node 1 after 5 attempts
INFO: setting voting term to 1
INFO: node 2 is candidate
INFO: node 3 has received request from node 2 for electoral term 1 (our term: 0)
[2017-08-24 23:32:12] [NOTICE] this node is the winner, will now promote self and inform other nodes
INFO: connecting to standby database
NOTICE: promoting standby
DETAIL: promoting server using '/home/barwick/devel/builds/HEAD/bin/pg_ctl -l /tmp/postgres.5602.log -w -D '/tmp/repmgr-test/node_2/data' promote'
INFO: reconnecting to promoted server
NOTICE: STANDBY PROMOTE successful
DETAIL: node 2 was successfully promoted to primary
INFO: node 3 received notification to follow node 2
[2017-08-24 23:32:13] [INFO] switching to primary monitoring mode</programlisting>
</para>
<para>
The cluster status will now look like this, with the original primary (<literal>node1</literal>)
marked as inactive, and standby <literal>node3</literal> now following the new primary
(<literal>node2</literal>):
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+----------------------------------------------------
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
</para>
<para>
<command>repmgr cluster event</command> will display a summary of what happened to each server
during the failover:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster event
Node ID | Name | Event | OK | Timestamp | Details
---------+-------+--------------------------+----+---------------------+-----------------------------------------------------------------------------------
3 | node3 | repmgrd_failover_follow | t | 2017-08-24 23:32:16 | node 3 now following new upstream node 2
3 | node3 | standby_follow | t | 2017-08-24 23:32:16 | node 3 is now attached to node 2
2 | node2 | repmgrd_failover_promote | t | 2017-08-24 23:32:13 | node 2 promoted to primary; old primary 1 marked as failed
2 | node2 | standby_promote | t | 2017-08-24 23:32:13 | node 2 was successfully promoted to primary</programlisting>
</para>
</chapter>

View File

@@ -0,0 +1,71 @@
<chapter id="repmgrd-monitoring">
<title>Monitoring with repmgrd</title>
<para>
When `repmgrd` is running with the option <literal>monitoring_history=true</literal>,
it will constantly write standby node status information to the
<varname>monitoring_history</varname> table, providing a near-real time
overview of replication status on all nodes
in the cluster.
</para>
<para>
The view <literal>replication_status</literal> shows the most recent state
for each node, e.g.:
<programlisting>
repmgr=# select * from repmgr.replication_status;
-[ RECORD 1 ]-------------+------------------------------
primary_node_id | 1
standby_node_id | 2
standby_name | node2
node_type | standby
active | t
last_monitor_time | 2017-08-24 16:28:41.260478+09
last_wal_primary_location | 0/6D57A00
last_wal_standby_location | 0/5000000
replication_lag | 29 MB
replication_time_lag | 00:00:11.736163
apply_lag | 15 MB
communication_time_lag | 00:00:01.365643</programlisting>
</para>
<para>
The interval in which monitoring history is written is controlled by the
configuration parameter <varname>monitor_interval_secs</varname>;
default is 2.
</para>
<para>
As this can generate a large amount of monitoring data in the table
<literal>repmgr.monitoring_history</literal>. it's advisable to regularly
purge historical data using the <xref linkend="repmgr-cluster-cleanup">
command; use the <literal>-k/--keep-history</literal> option to
specify how many day's worth of data should be retained.
</para>
<para>
It's possible to use <command>repmgrd</command> to run in monitoring
mode only (without automatic failover capability) for some or all
nodes by setting <literal>failover=manual</literal> in the node's
<filename>repmgr.conf</filename> file. In the event of the node's upstream failing,
no failover action will be taken and the node will require manual intervention to
be reattached to replication. If this occurs, an
<link linkend="event-notifications">event notification</link>
<varname>standby_disconnect_manual</varname> will be created.
</para>
<para>
Note that when a standby node is not streaming directly from its upstream
node, e.g. recovering WAL from an archive, <varname>apply_lag</varname> will always appear as
<literal>0 bytes</literal>.
</para>
<tip>
<para>
If monitoring history is enabled, the contents of the <literal>repmgr.monitoring_history</literal>
table will be replicated to attached standbys. This means there will be a small but
constant stream of replication activity which may not be desirable. To prevent
this, convert the table to an <literal>UNLOGGED</literal> one with:
<programlisting>
ALTER TABLE repmgr.monitoring_history SET UNLOGGED;</programlisting>
</para>
<para>
This will however mean that monitoring history will not be available on
another node following a failover, and the view <literal>repmgr.replication_status</literal>
will not work on standbys.
</para>
</tip>
</chapter>

View File

@@ -0,0 +1,43 @@
<chapter id="repmgrd-network-split">
<title>Handling network splits with repmgrd</title>
<para>
A common pattern for replication cluster setups is to spread servers over
more than one datacentre. This can provide benefits such as geographically-
distributed read replicas and DR (disaster recovery capability). However
this also means there is a risk of disconnection at network level between
datacentre locations, which would result in a split-brain scenario if
servers in a secondary data centre were no longer able to see the primary
in the main data centre and promoted a standby among themselves.
</para>
<para>
Previous &repmgr; versions used the concept of a "witness server" to
artificially create a quorum of servers in a particular location, ensuring
that nodes in another location will not elect a new primary if they
are unable to see the majority of nodes. However this approach does not
scale well, particularly with more complex replication setups, e.g.
where the majority of nodes are located outside of the primary datacentre.
It also means the <literal>witness</literal> node needs to be managed as an
extra PostgreSQL instance outside of the main replication cluster, which
adds administrative and programming complexity.
</para>
<para>
<literal>repmgr4</literal> introduces the concept of <literal>location</literal>:
each node is associated with an arbitrary location string (default is
<literal>default</literal>); this is set in <filename>repmgr.conf</filename>, e.g.:
<programlisting>
node_id=1
node_name=node1
conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/data'
location='dc1'</programlisting>
</para>
<para>
In a failover situation, <command>repmgrd</command> will check if any servers in the
same location as the current primary node are visible. If not, <command>repmgrd</command>
will assume a network interruption and not promote any node in any
other location (it will however enter <xref linkend="repmgrd-degraded-monitoring"> mode until
a primary becomes visible).
</para>
</chapter>

96
doc/stylesheet.css Normal file
View File

@@ -0,0 +1,96 @@
/* doc/src/sgml/stylesheet.css */
/* color scheme similar to www.postgresql.org */
BODY {
color: #000000;
background: #FFFFFF;
font-family: verdana, sans-serif;
}
A:link { color:#0066A2; }
A:visited { color:#004E66; }
A:active { color:#0066A2; }
A:hover { color:#000000; }
H1 {
font-size: 1.4em;
font-weight: bold;
margin-top: 0em;
margin-bottom: 0em;
color: #EC5800;
}
H2 {
font-size: 1.2em;
margin: 1.2em 0em 1.2em 0em;
font-weight: bold;
color: #666;
}
H3 {
font-size: 1.1em;
margin: 1.2em 0em 1.2em 0em;
font-weight: bold;
color: #666;
}
H4 {
font-size: 0.95em;
margin: 1.2em 0em 1.2em 0em;
font-weight: normal;
color: #666;
}
H5 {
font-size: 0.9em;
margin: 1.2em 0em 1.2em 0em;
font-weight: normal;
}
H6 {
font-size: 0.85em;
margin: 1.2em 0em 1.2em 0em;
font-weight: normal;
}
/* center some titles */
.BOOK .TITLE, .BOOK .CORPAUTHOR, .BOOK .COPYRIGHT {
text-align: center;
}
/* decoration for formal examples */
DIV.EXAMPLE {
padding-left: 15px;
border-style: solid;
border-width: 0px;
border-left-width: 2px;
border-color: black;
margin: 0.5ex;
}
/* less dense spacing of TOC */
.BOOK .TOC DL DT {
padding-top: 1.5ex;
padding-bottom: 1.5ex;
}
.BOOK .TOC DL DL DT {
padding-top: 0ex;
padding-bottom: 0ex;
}
/* miscellaneous */
PRE.LITERALLAYOUT, .SCREEN, .SYNOPSIS, .PROGRAMLISTING {
margin-left: 4ex;
}
.COMMENT { color: red; }
VAR { font-family: monospace; font-style: italic; }
/* Konqueror's standard style for ACRONYM is italic. */
ACRONYM { font-style: inherit; }

851
doc/stylesheet.dsl Normal file
View File

@@ -0,0 +1,851 @@
<!-- doc/src/sgml/stylesheet.dsl -->
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
<!-- must turn on one of these with -i on the jade command line -->
<!ENTITY % output-html "IGNORE">
<!ENTITY % output-print "IGNORE">
<!ENTITY % output-text "IGNORE">
<![ %output-html; [
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
]]>
<![ %output-print; [
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook Print Stylesheet//EN" CDATA DSSSL>
]]>
<![ %output-text; [
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
]]>
]>
<style-sheet>
<style-specification use="docbook">
<style-specification-body>
<!-- general customization ......................................... -->
<!-- (applicable to all output formats) -->
(define draft-mode #f)
;; Don't show manpage volume numbers
(define %refentry-xref-manvolnum% #f)
;; Don't use graphics for callouts. (We could probably do that, but
;; it needs extra work.)
(define %callout-graphics% #f)
;; Show comments during the development stage.
(define %show-comments% draft-mode)
;; Force a chapter TOC even if it includes only a single entry
(define %force-chapter-toc% #t)
;; Don't append period if run-in title ends with any of these
;; characters. We had to add the colon here. This is fixed in
;; stylesheets version 1.71, so it can be removed sometime.
(define %content-title-end-punct%
'(#\. #\! #\? #\:))
;; No automatic punctuation after honorific name parts
(define %honorific-punctuation% "")
;; Change display of some elements
(element command ($mono-seq$))
(element envar ($mono-seq$))
(element lineannotation ($italic-seq$))
(element literal ($mono-seq$))
(element option ($mono-seq$))
(element parameter ($mono-seq$))
(element structfield ($mono-seq$))
(element structname ($mono-seq$))
(element symbol ($mono-seq$))
(element token ($mono-seq$))
(element type ($mono-seq$))
(element varname ($mono-seq$))
(element (programlisting emphasis) ($bold-seq$)) ;; to highlight sections of code
;; Special support for Tcl synopses
(element optional
(if (equal? (attribute-string (normalize "role")) "tcl")
(make sequence
(literal "?")
($charseq$)
(literal "?"))
(make sequence
(literal %arg-choice-opt-open-str%)
($charseq$)
(literal %arg-choice-opt-close-str%))))
;; Avoid excessive cross-reference labels
(define (auto-xref-indirect? target ancestor)
(cond
; ;; Always add indirect references to another book
; ((member (gi ancestor) (book-element-list))
; #t)
;; Add indirect references to the section or component a block
;; is in iff chapters aren't autolabelled. (Otherwise "Figure 1-3"
;; is sufficient)
((and (member (gi target) (block-element-list))
(not %chapter-autolabel%))
#t)
;; Add indirect references to the component a section is in if
;; the sections are not autolabelled
((and (member (gi target) (section-element-list))
(member (gi ancestor) (component-element-list))
(not %section-autolabel%))
#t)
(else #f)))
;; Bibliography things
;; Use the titles of bibliography entries in cross-references
(define biblio-xref-title #t)
;; Process bibliography entry components in the order shown below, not
;; in the order they appear in the document. (I suppose this should
;; be made to fit some publishing standard.)
(define %biblioentry-in-entry-order% #f)
(define (biblioentry-inline-elements)
(list
(normalize "author")
(normalize "authorgroup")
(normalize "title")
(normalize "subtitle")
(normalize "volumenum")
(normalize "edition")
(normalize "othercredit")
(normalize "contrib")
(normalize "editor")
(normalize "publishername")
(normalize "confgroup")
(normalize "publisher")
(normalize "isbn")
(normalize "issn")
(normalize "pubsnumber")
(normalize "date")
(normalize "pubdate")
(normalize "pagenums")
(normalize "bibliomisc")))
(mode biblioentry-inline-mode
(element confgroup
(make sequence
(literal "Proc. ")
(next-match)))
(element isbn
(make sequence
(literal "ISBN ")
(process-children)))
(element issn
(make sequence
(literal "ISSN ")
(process-children))))
;; The rules in the default stylesheet for productname format it as a
;; paragraph. This may be suitable for productname directly within
;; *info, but it's nonsense when productname is used inline, as we do.
(mode book-titlepage-recto-mode
(element (para productname) ($charseq$)))
(mode book-titlepage-verso-mode
(element (para productname) ($charseq$)))
;; Add more here if needed...
;; Replace a sequence of whitespace in a string by a single space
(define (normalize-whitespace str #!optional (whitespace '(#\space #\U-000D)))
(let loop ((characters (string->list str))
(result '())
(prev-was-space #f))
(if (null? characters)
(list->string (reverse result))
(let ((c (car characters))
(rest (cdr characters)))
(if (member c whitespace)
(if prev-was-space
(loop rest result #t)
(loop rest (cons #\space result) #t))
(loop rest (cons c result) #f))))))
<!-- HTML output customization ..................................... -->
<![ %output-html; [
(define %section-autolabel% #t)
(define %label-preface-sections% #f)
(define %generate-legalnotice-link% #t)
(define %html-ext% ".html")
(define %root-filename% "index")
(define %link-mailto-url% (string-append "mailto: repmgr-list@2ndquadrant.com"))
(define %use-id-as-filename% #t)
(define website-build #f)
(define %stylesheet% (if website-build "/resources/docs.css" "website-docs.css"))
(define %graphic-default-extension% "gif")
(define %body-attr% '())
(define ($generate-book-lot-list$) '())
(define use-output-dir #t)
(define %output-dir% "html")
(define html-index-filename "../HTML.index")
;; Only build HTML.index or the actual HTML output, not both. Saves a
;; *lot* of time. (overrides docbook.dsl)
(root
(if (not html-index)
(make sequence
(process-children)
(with-mode manifest
(process-children)))
(with-mode htmlindex
(process-children))))
;; Do not combine first section into chapter chunk.
(define (chunk-skip-first-element-list) '())
;; Returns the depth of auto TOC that should be made at the nd-level
(define (toc-depth nd)
(cond ((string=? (gi nd) (normalize "book")) 2)
((string=? (gi nd) (normalize "part")) 2)
((string=? (gi nd) (normalize "chapter")) 2)
(else 1)))
;; Add character encoding and time of creation into HTML header
(define %html-header-tags%
(list (list "META" '("HTTP-EQUIV" "Content-Type") '("CONTENT" "text/html; charset=ISO-8859-1"))
(list "META" '("NAME" "creation") (list "CONTENT" (time->string (time) #t)))))
;; Block elements are allowed in PARA in DocBook, but not in P in
;; HTML. With %fix-para-wrappers% turned on, the stylesheets attempt
;; to avoid putting block elements in HTML P tags by outputting
;; additional end/begin P pairs around them.
(define %fix-para-wrappers% #t)
;; ...but we need to do some extra work to make the above apply to PRE
;; as well. (mostly pasted from dbverb.dsl)
(define ($verbatim-display$ indent line-numbers?)
(let ((content (make element gi: "PRE"
attributes: (list
(list "CLASS" (gi)))
(if (or indent line-numbers?)
($verbatim-line-by-line$ indent line-numbers?)
(process-children)))))
(if %shade-verbatim%
(make element gi: "TABLE"
attributes: ($shade-verbatim-attr$)
(make element gi: "TR"
(make element gi: "TD"
content)))
(make sequence
(para-check)
content
(para-check 'restart)))))
;; ...and for notes.
(element note
(make sequence
(para-check)
($admonition$)
(para-check 'restart)))
;;; XXX The above is very ugly. It might be better to run 'tidy' on
;;; the resulting *.html files.
;; Format multiple terms in varlistentry vertically, instead
;; of comma-separated.
(element (varlistentry term)
(make sequence
(process-children-trim)
(if (not (last-sibling?))
(make empty-element gi: "BR")
(empty-sosofo))))
;; Customization of header
;; - make title a link to the home page
;; - add tool tips to Prev/Next links
;; - add Up link
;; (overrides dbnavig.dsl)
(define (default-header-nav-tbl-noff elemnode prev next prevsib nextsib)
(let* ((r1? (nav-banner? elemnode))
(r1-sosofo (make element gi: "TR"
(make element gi: "TH"
attributes: (list
(list "COLSPAN" "4")
(list "ALIGN" "center")
(list "VALIGN" "bottom"))
(make element gi: "A"
attributes: (list
(list "HREF" (href-to (nav-home elemnode))))
(nav-banner elemnode)))))
(r2? (or (not (node-list-empty? prev))
(not (node-list-empty? next))
(nav-context? elemnode)))
(r2-sosofo (make element gi: "TR"
(make element gi: "TD"
attributes: (list
(list "WIDTH" "10%")
(list "ALIGN" "left")
(list "VALIGN" "top"))
(if (node-list-empty? prev)
(make entity-ref name: "nbsp")
(make element gi: "A"
attributes: (list
(list "TITLE" (element-title-string prev))
(list "HREF"
(href-to
prev))
(list "ACCESSKEY"
"P"))
(gentext-nav-prev prev))))
(make element gi: "TD"
attributes: (list
(list "WIDTH" "10%")
(list "ALIGN" "left")
(list "VALIGN" "top"))
(if (nav-up? elemnode)
(nav-up elemnode)
(nav-home-link elemnode)))
(make element gi: "TD"
attributes: (list
(list "WIDTH" "60%")
(list "ALIGN" "center")
(list "VALIGN" "bottom"))
(nav-context elemnode))
(make element gi: "TD"
attributes: (list
(list "WIDTH" "20%")
(list "ALIGN" "right")
(list "VALIGN" "top"))
(if (node-list-empty? next)
(make entity-ref name: "nbsp")
(make element gi: "A"
attributes: (list
(list "TITLE" (element-title-string next))
(list "HREF"
(href-to
next))
(list "ACCESSKEY"
"N"))
(gentext-nav-next next)))))))
(if (or r1? r2?)
(make element gi: "DIV"
attributes: '(("CLASS" "NAVHEADER"))
(make element gi: "TABLE"
attributes: (list
(list "SUMMARY" "Header navigation table")
(list "WIDTH" %gentext-nav-tblwidth%)
(list "BORDER" "0")
(list "CELLPADDING" "0")
(list "CELLSPACING" "0"))
(if r1? r1-sosofo (empty-sosofo))
(if r2? r2-sosofo (empty-sosofo)))
(make empty-element gi: "HR"
attributes: (list
(list "ALIGN" "LEFT")
(list "WIDTH" %gentext-nav-tblwidth%))))
(empty-sosofo))))
;; Put index "quicklinks" (A | B | C | ...) at the top of the bookindex page.
(element index
(let ((preamble (node-list-filter-by-not-gi
(children (current-node))
(list (normalize "indexentry"))))
(indexdivs (node-list-filter-by-gi
(children (current-node))
(list (normalize "indexdiv"))))
(entries (node-list-filter-by-gi
(children (current-node))
(list (normalize "indexentry")))))
(html-document
(with-mode head-title-mode
(literal (element-title-string (current-node))))
(make element gi: "DIV"
attributes: (list (list "CLASS" (gi)))
($component-separator$)
($component-title$)
(if (node-list-empty? indexdivs)
(empty-sosofo)
(make element gi: "P"
attributes: (list (list "CLASS" "INDEXDIV-QUICKLINKS"))
(with-mode indexdiv-quicklinks-mode
(process-node-list indexdivs))))
(process-node-list preamble)
(if (node-list-empty? entries)
(empty-sosofo)
(make element gi: "DL"
(process-node-list entries)))))))
(mode indexdiv-quicklinks-mode
(element indexdiv
(make sequence
(make element gi: "A"
attributes: (list (list "HREF" (href-to (current-node))))
(element-title-sosofo))
(if (not (last-sibling?))
(literal " | ")
(literal "")))))
;; Changed to strip and normalize index term content (overrides
;; dbindex.dsl)
(define (htmlindexterm)
(let* ((attr (gi (current-node)))
(content (data (current-node)))
(string (strip (normalize-whitespace content))) ;; changed
(sortas (attribute-string (normalize "sortas"))))
(make sequence
(make formatting-instruction data: attr)
(if sortas
(make sequence
(make formatting-instruction data: "[")
(make formatting-instruction data: sortas)
(make formatting-instruction data: "]"))
(empty-sosofo))
(make formatting-instruction data: " ")
(make formatting-instruction data: string)
(htmlnewline))))
(define ($html-body-start$)
(if website-build
(make empty-element gi: "!--#include virtual=\"/resources/docs-header.html\"--")
(empty-sosofo)))
(define ($html-body-end$)
(if website-build
(make empty-element gi: "!--#include virtual=\"/resources/docs-footer.html\"--")
(empty-sosofo)))
]]> <!-- %output-html -->
<!-- Print output customization .................................... -->
<![ %output-print; [
(define %section-autolabel% #t)
(define %default-quadding% 'justify)
;; Don't know how well hyphenation works with other backends. Might
;; turn this on if desired.
(define %hyphenation%
(if tex-backend #t #f))
;; Put footnotes at the bottom of the page (rather than end of
;; section), and put the URLs of links into footnotes.
;;
;; bop-footnotes only works with TeX, otherwise it's ignored. But
;; when both of these are #t and TeX is used, you need at least
;; stylesheets 1.73 because otherwise you don't get any footnotes at
;; all for the links.
(define bop-footnotes #t)
(define %footnote-ulinks% #t)
(define %refentry-new-page% #t)
(define %refentry-keep% #f)
;; Disabled because of TeX problems
;; (http://archives.postgresql.org/pgsql-docs/2007-12/msg00056.php)
(define ($generate-book-lot-list$) '())
;; Indentation of verbatim environments. (This should really be done
;; with start-indent in DSSSL.)
;; Use of indentation in this area exposes a bug in openjade,
;; http://archives.postgresql.org/pgsql-docs/2006-12/msg00064.php
;; (define %indent-programlisting-lines% " ")
;; (define %indent-screen-lines% " ")
;; (define %indent-synopsis-lines% " ")
;; Default graphic format: Jadetex wants eps, pdfjadetex wants pdf.
;; (Note that pdfjadetex will not accept eps, that's why we need to
;; create a different .tex file for each.) What works with RTF?
(define texpdf-output #f) ;; override from command line
(define %graphic-default-extension%
(cond (tex-backend (if texpdf-output "pdf" "eps"))
(rtf-backend "gif")
(else "XXX")))
;; Need to add pdf here so that the above works. Default setup
;; doesn't know about PDF.
(define preferred-mediaobject-extensions
(list "eps" "ps" "jpg" "jpeg" "pdf" "png"))
;; Don't show links when citing a bibliography entry. This fouls up
;; the footnumber counting. To get the link, one can still look into
;; the bibliography itself.
(mode xref-title-mode
(element ulink
(process-children)))
;; Format legalnotice justified and with space between paragraphs.
(mode book-titlepage-verso-mode
(element (legalnotice para)
(make paragraph
use: book-titlepage-verso-style ;; alter this if ever it needs to appear elsewhere
quadding: %default-quadding%
line-spacing: (* 0.8 (inherited-line-spacing))
font-size: (* 0.8 (inherited-font-size))
space-before: (* 0.8 %para-sep%)
space-after: (* 0.8 %para-sep%)
first-line-start-indent: (if (is-first-para)
(* 0.8 %para-indent-firstpara%)
(* 0.8 %para-indent%))
(process-children))))
;; Fix spacing problems in variablelists
(element (varlistentry term)
(make paragraph
space-before: (if (first-sibling?)
%para-sep%
0pt)
keep-with-next?: #t
(process-children)))
(define %varlistentry-indent% 2em)
(element (varlistentry listitem)
(make sequence
start-indent: (+ (inherited-start-indent) %varlistentry-indent%)
(process-children)))
;; Whitespace fixes for itemizedlists and orderedlists
(define (process-listitem-content)
(if (absolute-first-sibling?)
(make sequence
(process-children-trim))
(next-match)))
;; Default stylesheets format simplelists as tables. This spells
;; trouble for Jade. So we just format them as plain lines.
(define %simplelist-indent% 1em)
(define (my-simplelist-vert members)
(make display-group
space-before: %para-sep%
space-after: %para-sep%
start-indent: (+ %simplelist-indent% (inherited-start-indent))
(process-children)))
(element simplelist
(let ((type (attribute-string (normalize "type")))
(cols (if (attribute-string (normalize "columns"))
(if (> (string->number (attribute-string (normalize "columns"))) 0)
(string->number (attribute-string (normalize "columns")))
1)
1))
(members (select-elements (children (current-node)) (normalize "member"))))
(cond
((equal? type (normalize "inline"))
(if (equal? (gi (parent (current-node)))
(normalize "para"))
(process-children)
(make paragraph
space-before: %para-sep%
space-after: %para-sep%
start-indent: (inherited-start-indent))))
((equal? type (normalize "vert"))
(my-simplelist-vert members))
((equal? type (normalize "horiz"))
(simplelist-table 'row cols members)))))
(element member
(let ((type (inherited-attribute-string (normalize "type"))))
(cond
((equal? type (normalize "inline"))
(make sequence
(process-children)
(if (not (last-sibling?))
(literal ", ")
(literal ""))))
((equal? type (normalize "vert"))
(make paragraph
space-before: 0pt
space-after: 0pt))
((equal? type (normalize "horiz"))
(make paragraph
quadding: 'start
(process-children))))))
;; Jadetex doesn't handle links to the content of tables, so
;; indexterms that point to table entries will go nowhere. We fix
;; this by pointing the index entry to the table itself instead, which
;; should be equally useful in practice.
(define (find-parent-table nd)
(let ((table (ancestor-member nd ($table-element-list$))))
(if (node-list-empty? table)
nd
table)))
;; (The function below overrides the one in print/dbindex.dsl.)
(define (indexentry-link nd)
(let* ((id (attribute-string (normalize "role") nd))
(prelim-target (find-indexterm id))
(target (find-parent-table prelim-target))
(preferred (not (node-list-empty?
(select-elements (children (current-node))
(normalize "emphasis")))))
(sosofo (if (node-list-empty? target)
(literal "?")
(make link
destination: (node-list-address target)
(with-mode toc-page-number-mode
(process-node-list target))))))
(if preferred
(make sequence
font-weight: 'bold
sosofo)
sosofo)))
;; By default, the part and reference title pages get wrong page
;; numbers: The first title page gets roman numerals carried over from
;; preface/toc -- we want Arabic numerals. We also need to make sure
;; that page-number-restart is set of #f explicitly, because otherwise
;; it will carry over from the previous component, which is not good.
;;
;; (This looks worse than it is. It's copied from print/dbttlpg.dsl
;; and common/dbcommon.dsl and modified in minor detail.)
(define (first-part?)
(let* ((book (ancestor (normalize "book")))
(nd (ancestor-member (current-node)
(append
(component-element-list)
(division-element-list))))
(bookch (children book)))
(let loop ((nl bookch))
(if (node-list-empty? nl)
#f
(if (equal? (gi (node-list-first nl)) (normalize "part"))
(if (node-list=? (node-list-first nl) nd)
#t
#f)
(loop (node-list-rest nl)))))))
(define (first-reference?)
(let* ((book (ancestor (normalize "book")))
(nd (ancestor-member (current-node)
(append
(component-element-list)
(division-element-list))))
(bookch (children book)))
(let loop ((nl bookch))
(if (node-list-empty? nl)
#f
(if (equal? (gi (node-list-first nl)) (normalize "reference"))
(if (node-list=? (node-list-first nl) nd)
#t
#f)
(loop (node-list-rest nl)))))))
(define (part-titlepage elements #!optional (side 'recto))
(let ((nodelist (titlepage-nodelist
(if (equal? side 'recto)
(reference-titlepage-recto-elements)
(reference-titlepage-verso-elements))
elements))
;; partintro is a special case...
(partintro (node-list-first
(node-list-filter-by-gi elements (list (normalize "partintro"))))))
(if (part-titlepage-content? elements side)
(make simple-page-sequence
page-n-columns: %titlepage-n-columns%
;; Make sure that page number format is correct.
page-number-format: ($page-number-format$)
;; Make sure that the page number is set to 1 if this is the
;; first part in the book
page-number-restart?: (first-part?)
input-whitespace-treatment: 'collapse
use: default-text-style
;; This hack is required for the RTF backend. If an external-graphic
;; is the first thing on the page, RTF doesn't seem to do the right
;; thing (the graphic winds up on the baseline of the first line
;; of the page, left justified). This "one point rule" fixes
;; that problem.
(make paragraph
line-spacing: 1pt
(literal ""))
(let loop ((nl nodelist) (lastnode (empty-node-list)))
(if (node-list-empty? nl)
(empty-sosofo)
(make sequence
(if (or (node-list-empty? lastnode)
(not (equal? (gi (node-list-first nl))
(gi lastnode))))
(part-titlepage-before (node-list-first nl) side)
(empty-sosofo))
(cond
((equal? (gi (node-list-first nl)) (normalize "subtitle"))
(part-titlepage-subtitle (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "title"))
(part-titlepage-title (node-list-first nl) side))
(else
(part-titlepage-default (node-list-first nl) side)))
(loop (node-list-rest nl) (node-list-first nl)))))
(if (and %generate-part-toc%
%generate-part-toc-on-titlepage%
(equal? side 'recto))
(make display-group
(build-toc (current-node)
(toc-depth (current-node))))
(empty-sosofo))
;; PartIntro is a special case
(if (and (equal? side 'recto)
(not (node-list-empty? partintro))
%generate-partintro-on-titlepage%)
($process-partintro$ partintro #f)
(empty-sosofo)))
(empty-sosofo))))
(define (reference-titlepage elements #!optional (side 'recto))
(let ((nodelist (titlepage-nodelist
(if (equal? side 'recto)
(reference-titlepage-recto-elements)
(reference-titlepage-verso-elements))
elements))
;; partintro is a special case...
(partintro (node-list-first
(node-list-filter-by-gi elements (list (normalize "partintro"))))))
(if (reference-titlepage-content? elements side)
(make simple-page-sequence
page-n-columns: %titlepage-n-columns%
;; Make sure that page number format is correct.
page-number-format: ($page-number-format$)
;; Make sure that the page number is set to 1 if this is the
;; first part in the book
page-number-restart?: (first-reference?)
input-whitespace-treatment: 'collapse
use: default-text-style
;; This hack is required for the RTF backend. If an external-graphic
;; is the first thing on the page, RTF doesn't seem to do the right
;; thing (the graphic winds up on the baseline of the first line
;; of the page, left justified). This "one point rule" fixes
;; that problem.
(make paragraph
line-spacing: 1pt
(literal ""))
(let loop ((nl nodelist) (lastnode (empty-node-list)))
(if (node-list-empty? nl)
(empty-sosofo)
(make sequence
(if (or (node-list-empty? lastnode)
(not (equal? (gi (node-list-first nl))
(gi lastnode))))
(reference-titlepage-before (node-list-first nl) side)
(empty-sosofo))
(cond
((equal? (gi (node-list-first nl)) (normalize "author"))
(reference-titlepage-author (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "authorgroup"))
(reference-titlepage-authorgroup (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "corpauthor"))
(reference-titlepage-corpauthor (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "editor"))
(reference-titlepage-editor (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "subtitle"))
(reference-titlepage-subtitle (node-list-first nl) side))
((equal? (gi (node-list-first nl)) (normalize "title"))
(reference-titlepage-title (node-list-first nl) side))
(else
(reference-titlepage-default (node-list-first nl) side)))
(loop (node-list-rest nl) (node-list-first nl)))))
(if (and %generate-reference-toc%
%generate-reference-toc-on-titlepage%
(equal? side 'recto))
(make display-group
(build-toc (current-node)
(toc-depth (current-node))))
(empty-sosofo))
;; PartIntro is a special case
(if (and (equal? side 'recto)
(not (node-list-empty? partintro))
%generate-partintro-on-titlepage%)
($process-partintro$ partintro #f)
(empty-sosofo)))
(empty-sosofo))))
]]> <!-- %output-print -->
<!-- Plain text output customization ............................... -->
<!--
This is used for making the INSTALL file and others. We customize the
HTML stylesheets to be suitable for dumping plain text (via Netscape,
Lynx, or similar).
-->
<![ %output-text; [
(define %section-autolabel% #f)
(define %chapter-autolabel% #f)
(define $generate-chapter-toc$ (lambda () #f))
;; For text output, produce "ASCII markup" for emphasis and such.
(define ($asterix-seq$ #!optional (sosofo (process-children)))
(make sequence
(literal "*")
sosofo
(literal "*")))
(define ($dquote-seq$ #!optional (sosofo (process-children)))
(make sequence
(literal (gentext-start-quote))
sosofo
(literal (gentext-end-quote))))
(element (para command) ($dquote-seq$))
(element (para emphasis) ($asterix-seq$))
(element (para filename) ($dquote-seq$))
(element (para option) ($dquote-seq$))
(element (para replaceable) ($dquote-seq$))
(element (para userinput) ($dquote-seq$))
]]> <!-- %output-text -->
</style-specification-body>
</style-specification>
<external-specification id="docbook" document="dbstyle">
</style-sheet>

204
doc/switchover.sgml Normal file
View File

@@ -0,0 +1,204 @@
<chapter id="performing-switchover" xreflabel="Performing a switchover with repmgr">
<title>Performing a switchover with repmgr</title>
<para>
A typical use-case for replication is a combination of primary and standby
server, with the standby serving as a backup which can easily be activated
in case of a problem with the primary. Such an unplanned failover would
normally be handled by promoting the standby, after which an appropriate
action must be taken to restore the old primary.
</para>
<para>
In some cases however it's desirable to promote the standby in a planned
way, e.g. so maintenance can be performed on the primary; this kind of switchover
is supported by the <xref linkend="repmgr-standby-switchover"> command.
</para>
<para>
<command>repmgr standby switchover</command> differs from other &repmgr;
actions in that it lso performs actions on another server (the demotion
candidate), which means passwordless SSH access is required to that server
from the one where <command>repmgr standby switchover</command> is executed.
</para>
<note>
<simpara>
<command>repmgr standby switchover</command> performs a relatively complex
series of operations on two servers, and should therefore be performed after
careful preparation and with adequate attention. In particular you should
be confident that your network environment is stable and reliable.
</simpara>
<simpara>
Additionally you should be sure that the current primary can be shut down
quickly and cleanly. In particular, access from applications should be
minimalized or preferably blocked completely. Also be aware that if there
is a backlog of files waiting to be archived, PostgreSQL will not shut
down until archiving completes.
</simpara>
<simpara>
We recommend running <command>repmgr standby switchover</command> at the
most verbose logging level (<literal>--log-level=DEBUG --verbose</literal>)
and capturing all output to assist troubleshooting any problems.
</simpara>
<simpara>
Please also read carefully the sections <xref linkend="preparing-for-switchover"> and
`Caveats` below.
</simpara>
</note>
<sect1 id="preparing-for-switchover" xreflabel="Preparing for switchover">
<indexterm>
<primary>switchover</primary>
<secondary>preparation</secondary>
</indexterm>
<title>Preparing for switchover</title>
<para>
As mentioned above, success of the switchover operation depends on &repmgr;
being able to shut down the current primary server quickly and cleanly.
</para>
<para>
Double-check which commands will be used to stop/start/restart the current
primary; on the primary execute:
<programlisting>
repmgr -f /etc./repmgr.conf node service --list --action=stop
repmgr -f /etc./repmgr.conf node service --list --action=start
repmgr -f /etc./repmgr.conf node service --list --action=restart
</programlisting>
</para>
<note>
<simpara>
On <literal>systemd</literal> systems we strongly recommend using the appropriate
<command>systemctl</command> commands (typically run via <command>sudo</command>) to ensure
<literal>systemd</literal> informed about the status of the PostgreSQL service.
</simpara>
</note>
<para>
Check that access from applications is minimalized or preferably blocked
completely, so applications are not unexpectedly interrupted.
</para>
<para>
Check there is no significant replication lag on standbys attached to the
current primary.
</para>
<para>
If WAL file archiving is set up, check that there is no backlog of files waiting
to be archived, as PostgreSQL will not finally shut down until all these have been
archived. If there is a backlog exceeding <varname>archive_ready_warning</varname> WAL files,
`repmgr` will emit a warning before attempting to perform a switchover; you can also check
manually with <command>repmgr node check --archive-ready</command>.
</para>
<para>
Ensure that <command>repmgrd</command> is *not* running anywhere to prevent it unintentionally
promoting a node.
</para>
<para>
Finally, consider executing <command>repmgr standby switchover</command> with the
<literal>--dry-run</literal> option; this will perform any necessary checks and inform you about
success/failure, and stop before the first actual command is run (which would be the shutdown of the
current primary). Example output:
<programlisting>
$ repmgr standby switchover -f /etc/repmgr.conf --siblings-follow --dry-run
NOTICE: checking switchover on node "node2" (ID: 2) in --dry-run mode
INFO: SSH connection to host "localhost" succeeded
INFO: archive mode is "off"
INFO: replication lag on this standby is 0 seconds
INFO: all sibling nodes are reachable via SSH
NOTICE: local node "node2" (ID: 2) will be promoted to primary; current primary "node1" (ID: 1) will be demoted to standby
INFO: following shutdown command would be run on node "node1":
"pg_ctl -l /var/log/postgresql/startup.log -D '/var/lib/postgresql/data' -m fast -W stop"
</programlisting>
</para>
</sect1>
<sect1 id="switchover-execution" xreflabel="Executing the switchover command">
<indexterm>
<primary>switchover</primary>
<secondary>execution</secondary>
</indexterm>
<title>Executing the switchover command</title>
<para>
To demonstrate switchover, we will assume a replication cluster with a
primary (<literal>node1</literal>) and one standby (<literal>node2</literal>);
after the switchover <literal>node2</literal> should become the primary with
<literal>node1</literal> following it.
</para>
<para>
The switchover command must be run from the standby which is to be promoted,
and in its simplest form looks like this:
<programlisting>
$ repmgr -f /etc/repmgr.conf standby switchover
NOTICE: executing switchover on node "node2" (ID: 2)
INFO: searching for primary node
INFO: checking if node 1 is primary
INFO: current primary node is 1
INFO: SSH connection to host "localhost" succeeded
INFO: archive mode is "off"
INFO: replication lag on this standby is 0 seconds
NOTICE: local node "node2" (ID: 2) will be promoted to primary; current primary "node1" (ID: 1) will be demoted to standby
NOTICE: stopping current primary node "node1" (ID: 1)
NOTICE: issuing CHECKPOINT
DETAIL: executing server command "pg_ctl -l /var/log/postgres/startup.log -D '/var/lib/pgsql/data' -m fast -W stop"
INFO: checking primary status; 1 of 6 attempts
NOTICE: current primary has been cleanly shut down at location 0/3001460
NOTICE: promoting standby to primary
DETAIL: promoting server "node2" (ID: 2) using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/pgsql/data' promote"
server promoting
NOTICE: STANDBY PROMOTE successful
DETAIL: server "node2" (ID: 2) was successfully promoted to primary
INFO: setting node 1's primary to node 2
NOTICE: starting server using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/pgsql/data' restart"
NOTICE: NODE REJOIN successful
DETAIL: node 1 is now attached to node 2
NOTICE: switchover was successful
DETAIL: node "node2" is now primary
NOTICE: STANDBY SWITCHOVER is complete
</programlisting>
</para>
<para>
The old primary is now replicating as a standby from the new primary, and the
cluster status will now look like this:
<programlisting>
$ repmgr -f /etc/repmgr.conf cluster show
ID | Name | Role | Status | Upstream | Location | Connection string
----+-------+---------+-----------+----------+----------+--------------------------------------
1 | node1 | standby | running | node2 | default | host=node1 dbname=repmgr user=repmgr
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
</programlisting>
</para>
</sect1>
<sect1 id="switchover-caveats" xreflabel="Caveats">
<indexterm>
<primary>switchover</primary>
<secondary>caveats</secondary>
</indexterm>
<title>Caveats</title>
<para>
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>
If using PostgreSQL 9.3 or 9.4, you should ensure that the shutdown command
is configured to use PostgreSQL's <varname>fast</varname> shutdown mode (the default in 9.5
and later). If relying on <command>pg_ctl</command> to perform database server operations,
you should include <literal>-m fast</literal> in <varname>pg_ctl_options</varname>
in <filename>repmgr.conf</filename>.
</simpara>
</listitem>
<listitem>
<simpara>
<command>pg_rewind</command> *requires* that either <varname>wal_log_hints</varname> is enabled, or that
data checksums were enabled when the cluster was initialized. See the
<ulink url="https://www.postgresql.org/docs/current/static/app-pgrewind.html">pg_rewind documentation</ulink>
for details.
</simpara>
</listitem>
<listitem>
<simpara>
<command>repmgrd</command> should not be running with setting <varname>failover=automatic</varname>
in <filename>repmgr.conf</filename> when a switchover is carried out, otherwise the
<command>repmgrd</command> daemon may try and promote a standby by itself.
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
We hope to remove some of these restrictions in future versions of `repmgr`.
</para>
</sect1>
</chapter>

245
doc/upgrading-repmgr.sgml Normal file
View File

@@ -0,0 +1,245 @@
<chapter id="upgrading-repmgr" xreflabel="Upgrading repmgr">
<title>Upgrading repmgr</title>
<para>
&repmgr; is updated regularly with point releases (e.g. 4.0.1 to 4.0.2)
containing bugfixes and other minor improvements. Any substantial new
functionality will be included in a feature release (e.g. 4.0.x to 4.1.x).
</para>
<para>
&repmgr; is implemented as a PostgreSQL extension; to upgrade it, first
install the updated package (or compile the updated source), then in the
database where the &repmgr; extension is installed, execute
<command>ALTER EXTENSION repmgr UPDATE</command>.
</para>
<para>
If <command>repmgrd</command> is running, it may be necessary to restart
the PostgreSQL server if the upgrade contains changes to the shared object
file used by <command>repmgrd</command>; check the release notes for details.
</para>
<sect1 id="upgrading-from-repmgr-3">
<title>Upgrading from repmgr 3</title>
<para>
The upgrade process consists of two steps:
<orderedlist>
<listitem>
<simpara>
converting the repmgr.conf configuration files
</simpara>
</listitem>
<listitem>
<simpara>
upgrading the repmgr schema
</simpara>
</listitem>
</orderedlist>
</para>
<para>
A script is provided to assist with converting <filename>repmgr.conf</filename>.
</para>
<para>
The schema upgrade (which converts the &repmgr; metadata into
a packaged PostgreSQL extension) is normally carried out
automatically when the &repmgr; extension is created.
</para>
<sect2 id="converting-repmgr-conf">
<title>Converting repmgr.conf configuration files</title>
<para>
With a completely new repmgr version, we've taken the opportunity
to rename some configuration items have had their names changed for
clarity and consistency, both between the configuration file and
the column names in <structname>repmgr.nodes</structname>
(e.g. <varname>node</varname> to <varname>node_id</varname>), and
also for consistency with PostgreSQL naming conventions
(e.g. <varname>loglevel</varname> to <varname>log_level</varname>).
</para>
<para>
Other configuration items have been changed to command line options,
and vice-versa, e.g. to avoid hard-coding items such as a a node's
upstream ID, which might change over time.
</para>
<para>
&repmgr; will issue a warning about deprecated/altered options.
</para>
<sect3>
<title>Changed parameters in "repmgr.conf"</title>
<para>
Following parameters have been added:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara><varname>data_directory</varname>: this is mandatory and must
contain the path to the node's data directory</simpara>
</listitem>
<listitem>
<simpara><varname>monitoring_history</varname>: this replaces the
<command>repmgrd</command> command line option
<literal>--monitoring-history</literal></simpara>
</listitem>
</itemizedlist>
</para>
<para>
Following parameters have been renamed:
</para>
<table tocentry="1" id="repmgr3-repmgr4-renamed-parameters">
<title>Parameters renamed in repmgr4</title>
<tgroup cols="2">
<thead>
<row>
<entry>repmgr3</entry>
<entry>repmgr4</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>node</varname></entry>
<entry><varname>node_id</varname></entry>
</row>
<row>
<entry><varname>loglevel</varname></entry>
<entry><varname>log_level</varname></entry>
</row>
<row>
<entry><varname>logfacility</varname></entry>
<entry><varname>log_facility</varname></entry>
</row>
<row>
<entry><varname>logfile</varname></entry>
<entry><varname>log_file</varname></entry>
</row>
<row>
<entry><varname>master_reponse_timeout</varname></entry>
<entry><varname>async_query_timeout</varname></entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Following parameters have been removed:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara><varname>cluster</varname>: is no longer required and will
be ignored.</simpara>
</listitem>
<listitem>
<simpara><varname>upstream_node_id</varname>: is replaced by the
command-line parameter <literal>--upstream-node-id</literal></simpara>
</listitem>
</itemizedlist>
</para>
</sect3>
<sect3>
<title>Conversion script</title>
<para>
To assist with conversion of <filename>repmgr.conf</filename> files, a Perl script
is provided in <filename>contrib/convert-config.pl</filename>.
Use like this:
<programlisting>
$ ./convert-config.pl /etc/repmgr.conf
node_id=2
node_name=node2
conninfo=host=localhost dbname=repmgr user=repmgr connect_timeout=2
pg_ctl_options='-l /var/log/postgres/startup.log'
rsync_options=--exclude=postgresql.local.conf --archive
log_level=INFO
pg_basebackup_options=--no-slot
data_directory=</programlisting>
</para>
<para>
The converted file is printed to <literal>STDOUT</literal> and the original file is not
changed.
</para>
<para>
Please note that the parameter <varname>data_directory</varname> <emphasis>must</emphasis>
be provided; if not already present, the conversion script will add an empty
placeholder parameter.
</para>
</sect3>
</sect2>
<sect2>
<title>Upgrading the repmgr schema</title>
<para>
Ensure <command>repmgrd</command> is not running, or any cron jobs which execute the
<command>repmgr</command> binary.
</para>
<para>
Install <literal>repmgr4</literal>; any <literal>repmgr3</literal> packages should be uninstalled
(if not automatically uninstalled already).
</para>
<sect3>
<title>Upgrading from repmgr 3.1.1 or earlier</title>
<para>
If your repmgr version is 3.1.1 or earlier, you will need to update
the schema to the latest version in the 3.x series (3.3.2) before
converting the installation to repmgr 4.
</para>
<para>
To do this, apply the following upgrade scripts as appropriate for
your current version:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<simpara>
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.0_repmgr3.1.sql">repmgr3.0_repmgr3.1.sql</ulink></simpara>
</listitem>
<listitem>
<simpara><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.1.1_repmgr3.1.2.sql">repmgr3.1.1_repmgr3.1.2.sql</ulink></simpara>
</listitem>
</itemizedlist>
</para>
<para>
For more details see the
<ulink url="https://repmgr.org/release-notes-3.3.2.html#upgrading">repmgr 3 upgrade notes</ulink>.
</para>
</sect3>
<sect3>
<title>Manually create the repmgr extension</title>
<para>
In the database used by the existing &repmgr; installation, execute:
<programlisting>
CREATE EXTENSION repmgr FROM unpackaged;</programlisting>
</para>
<para>
This will move and convert all objects from the existing schema
into the new, standard <literal>repmgr</literal> schema.
</para>
<note>
<simpara>there must be only one schema matching <literal>repmgr_%</literal> in the
database, otherwise this step may not work.</simpara>
</note>
</sect3>
<sect3>
<title>Re-register each node</title>
<para>
This is necessary to update the <literal>repmgr</literal> metadata with some additional items.
</para>
<para>
On the primary node, execute e.g.
<programlisting>
repmgr primary register -f /etc/repmgr.conf --force</programlisting>
</para>
<para>
On each standby node, execute e.g.
<programlisting>
repmgr standby register -f /etc/repmgr.conf --force</programlisting>
</para>
<para>
Check the data is updated as expected by examining the <structname>repmgr.nodes</structname>
table; restart <command>repmgrd</command> if required.
</para>
<para>
The original <literal>repmgr_$cluster</literal> schema can be dropped at any time.
</para>
<tip>
<simpara>
If you don't care about any data from the existing &repmgr; installation,
(e.g. the contents of the <structname>events</structname> and <structname>monitoring</structname>
tables), the manual <command>CREATE EXTENSION</command> step can be skipped; just re-register
each node, starting with the primary node, and the <literal>repmgr</literal> extension will be
automatically created.
</simpara>
</tip>
</sect3>
</sect2>
</sect1>
</chapter>

1
doc/version.sgml Normal file
View File

@@ -0,0 +1 @@
<!ENTITY repmgrversion "4.0dev">

469
doc/website-docs.css Normal file
View File

@@ -0,0 +1,469 @@
/* PostgreSQL.org Documentation Style */
/* requires global.css, table.css and text.css to be loaded before this file! */
body {
font-family: verdana, sans-serif;
font-size: 76%;
background: url("/resources/background.png") repeat-x scroll left top transparent;
padding: 15px 4%;
margin: 0;
}
/* monospace font size fix */
pre, code, kbd, samp, tt {
font-family: monospace,monospace;
font-size: 1em;
}
div.NAVHEADER table {
margin-left: 0;
}
/* Container Definitions */
#docContainerWrap {
text-align: center; /* Win IE5 */
}
#docContainer {
margin: 0 auto;
width: 90%;
padding-bottom: 2em;
display: block;
text-align: left; /* Win IE5 */
}
#docHeader {
background-image: url("/media/img/docs/bg_hdr.png");
height: 83px;
margin: 0px;
padding: 0px;
display: block;
}
#docHeaderLogo {
position: relative;
width: 206px;
height: 83px;
border: 0px;
padding: 0px;
margin: 0 0 0 20px;
}
#docHeaderLogo img {
border: 0px;
}
#docNavSearchContainer {
padding-bottom: 2px;
}
#docNav, #docVersions {
position: relative;
text-align: left;
margin-left: 10px;
margin-top: 5px;
color: #666;
font-size: 0.95em;
}
#docSearch {
position: relative;
text-align: right;
padding: 0;
margin: 0;
color: #666;
}
#docTextSize {
text-align: right;
white-space: nowrap;
margin-top: 7px;
font-size: 0.95em;
}
#docSearch form {
position: relative;
top: 5px;
right: 0;
margin: 0; /* need for IE 5.5 OSX */
text-align: right; /* need for IE 5.5 OSX */
white-space: nowrap; /* for Opera */
}
#docSearch form label {
color: #666;
font-size: 0.95em;
}
#docSearch form input {
font-size: 0.95em;
}
#docSearch form #submit {
font-size: 0.95em;
background: #7A7A7A;
color: #fff;
border: 1px solid #7A7A7A;
padding: 1px 4px;
}
#docSearch form #q {
width: 170px;
font-size: 0.95em;
border: 1px solid #7A7A7A;
background: #E1E1E1;
color: #000000;
padding: 2px;
}
.frmDocSearch {
padding: 0;
margin: 0;
display: inline;
}
.inpDocSearch {
padding: 0;
margin: 0;
color: #000;
}
#docContent {
position: relative;
margin-left: 10px;
margin-right: 10px;
margin-top: 40px;
}
#docFooter {
position: relative;
font-size: 0.9em;
color: #666;
line-height: 1.3em;
margin-left: 10px;
margin-right: 10px;
}
#docComments {
margin-top: 10px;
}
#docClear {
clear: both;
margin: 0;
padding: 0;
}
/* Heading Definitions */
h1, h2, h3 {
font-weight: bold;
margin-top: 2ex;
color: #444;
}
h1 {
font-size: 1.4em;
}
h2 {
font-size: 1.2em !important;
}
h3 {
font-size: 1.1em;
}
h1 a:hover,
h2 a:hover,
h3 a:hover,
h4 a:hover {
color: #444;
text-decoration: none;
}
/* Text Styles */
div.SECT2 {
margin-top: 4ex;
}
div.SECT3 {
margin-top: 3ex;
margin-left: 3ex;
}
.txtCurrentLocation {
font-weight: bold;
}
p, ol, ul, li {
line-height: 1.5em;
}
.txtCommentsWrap {
border: 2px solid #F5F5F5;
width: 100%;
}
.txtCommentsContent {
background: #F5F5F5;
padding: 3px;
}
.txtCommentsPoster {
float: left;
}
.txtCommentsDate {
float: right;
}
.txtCommentsComment {
padding: 3px;
}
#docContainer pre code,
#docContainer pre tt,
#docContainer pre pre,
#docContainer tt tt,
#docContainer tt code,
#docContainer tt pre {
font-size: 1em;
}
pre.LITERALLAYOUT,
.SCREEN,
.SYNOPSIS,
.PROGRAMLISTING,
.REFSYNOPSISDIV p,
table.CAUTION,
table.WARNING,
blockquote.NOTE,
blockquote.TIP,
table.CALSTABLE {
-moz-box-shadow: 3px 3px 5px #DFDFDF;
-webkit-box-shadow: 3px 3px 5px #DFDFDF;
-khtml-box-shadow: 3px 3px 5px #DFDFDF;
-o-box-shadow: 3px 3px 5px #DFDFDF;
box-shadow: 3px 3px 5px #DFDFDF;
}
pre.LITERALLAYOUT,
.SCREEN,
.SYNOPSIS,
.PROGRAMLISTING,
.REFSYNOPSISDIV p,
table.CAUTION,
table.WARNING,
blockquote.NOTE,
blockquote.TIP {
color: black;
border-width: 1px;
border-style: solid;
padding: 2ex;
margin: 2ex 0 2ex 2ex;
overflow: auto;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
-khtml-border-radius: 8px;
border-radius: 8px;
}
pre.LITERALLAYOUT,
pre.SYNOPSIS,
pre.PROGRAMLISTING,
.REFSYNOPSISDIV p,
.SCREEN {
border-color: #CFCFCF;
background-color: #F7F7F7;
}
blockquote.NOTE,
blockquote.TIP {
border-color: #DBDBCC;
background-color: #EEEEDD;
padding: 14px;
width: 572px;
}
blockquote.NOTE,
blockquote.TIP,
table.CAUTION,
table.WARNING {
margin: 4ex auto;
}
blockquote.NOTE p,
blockquote.TIP p {
margin: 0;
}
blockquote.NOTE pre,
blockquote.NOTE code,
blockquote.TIP pre,
blockquote.TIP code {
margin-left: 0;
margin-right: 0;
-moz-box-shadow: none;
-webkit-box-shadow: none;
-khtml-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
}
.emphasis,
.c2 {
font-weight: bold;
}
.REPLACEABLE {
font-style: italic;
}
/* Table Styles */
table {
margin-left: 2ex;
}
table.CALSTABLE td,
table.CALSTABLE th,
table.CAUTION td,
table.CAUTION th,
table.WARNING td,
table.WARNING th {
border-style: solid;
}
table.CALSTABLE,
table.CAUTION,
table.WARNING {
border-spacing: 0;
border-collapse: collapse;
}
table.CALSTABLE
{
margin: 2ex 0 2ex 2ex;
background-color: #E0ECEF;
border: 2px solid #A7C6DF;
}
table.CALSTABLE tr:hover td
{
background-color: #EFEFEF;
}
table.CALSTABLE td {
background-color: #FFF;
}
table.CALSTABLE td,
table.CALSTABLE th {
border: 1px solid #A7C6DF;
padding: 0.5ex 0.5ex;
}
table.CAUTION,
table.WARNING {
border-collapse: separate;
display: block;
padding: 0;
max-width: 600px;
}
table.CAUTION {
background-color: #F5F5DC;
border-color: #DEDFA7;
}
table.WARNING {
background-color: #FFD7D7;
border-color: #DF421E;
}
table.CAUTION td,
table.CAUTION th,
table.WARNING td,
table.WARNING th {
border-width: 0;
padding-left: 2ex;
padding-right: 2ex;
}
table.CAUTION td,
table.CAUTION th {
border-color: #F3E4D5
}
table.WARNING td,
table.WARNING th {
border-color: #FFD7D7;
}
td.c1,
td.c2,
td.c3,
td.c4,
td.c5,
td.c6 {
font-size: 1.1em;
font-weight: bold;
border-bottom: 0px solid #FFEFEF;
padding: 1ex 2ex 0;
}
/* Link Styles */
#docNav a {
font-weight: bold;
}
a:link,
a:visited,
a:active,
a:hover {
text-decoration: underline;
}
a:link,
a:active {
color:#0066A2;
}
a:visited {
color:#004E66;
}
a:hover {
color:#000000;
}
#docFooter a:link,
#docFooter a:visited,
#docFooter a:active {
color:#666;
}
#docContainer code.FUNCTION tt {
font-size: 1em;
}
div.header {
color: #444;
margin-top: 5px;
}
div.footer {
text-align: center;
background-image: url("/resources/footerl.png"), url("/resources/footerr.png"), url("/resources/footerc.png");
background-position: left top, right top, center top;
background-repeat: no-repeat, no-repeat, repeat-x;
padding-top: 45px;
}
img {
border-style: none;
}

View File

@@ -1,25 +1,2 @@
/*
* repmgr_version.h
* Copyright (c) 2ndQuadrant, 2010-2017
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _VERSION_H_
#define _VERSION_H_
#define REPMGR_VERSION_DATE ""
#define REPMGR_VERSION "4.0dev"
#endif