In the directory which you have extracted the source tar ball,
execute the following commands.
<programlisting>
- $ ./configure
- $ make
- $ make install
+$ ./configure
+$ make
+$ make install
</programlisting>
<command>configure</command> script collects your system information
and use it for the compilation procedure. You can pass command
If the <command>configure</command> script displays the following error message, the
<literal>libpq</literal> library may not be installed, or it is not of version 3
<programlisting>
- configure: error: libpq is not installed or libpq is old
+configure: error: libpq is not installed or libpq is old
</programlisting>
If the library is version 3, but the above message is still displayed, your
<literal>libpq</literal> library is probably not recognized by the <command>
We recommend copying and renaming it to <literal>pgpool.conf</literal>, and edit
it as you like.
<programlisting>
- $ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf
+$ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf
</programlisting>
<productname>Pgpool-II</productname> only accepts connections from the localhost
using port 9999. If you wish to receive conenctions from other hosts,
set <xref linkend="guc-listen-addresses"> to <literal>'*'</literal>.
<programlisting>
- listen_addresses = 'localhost'
- port = 9999
+listen_addresses = 'localhost'
+port = 9999
</programlisting>
We will use the default parameters in thie tutorial.
</para>
<literal>md5</literal> hash format.
<programlisting>
- postgres:e8a48653851e28c69d0506508fb27fc5
+postgres:e8a48653851e28c69d0506508fb27fc5
</programlisting>
When you install <productname>Pgpool-II</productname>, <literal>pcp.conf.sample
</literal> is automatically created. We recommend copying and renaming it
to <literal>pcp.conf</literal>, and edit it.
<programlisting>
- $ cp /usr/local/etc/pcp.conf.sample /usr/local/etc/pcp.conf
+$ cp /usr/local/etc/pcp.conf.sample /usr/local/etc/pcp.conf
</programlisting>
To encrypt your password into md5 hash format, use the <command>pg_md5</command>
command, which is installed as one of <productname>Pgpool-II</productname>'s
For example, give <literal>"postgres"</literal> as the command line argument,
and <command>pg_md5</command> displays md5-hashed text on its standard output.
<programlisting>
- $ /usr/bin/pg_md5 postgres
- e8a48653851e28c69d0506508fb27fc5
+$ /usr/bin/pg_md5 postgres
+e8a48653851e28c69d0506508fb27fc5
</programlisting>
PCP commands are executed via network, so the port number must be configured
with <xref linkend="guc-pcp-port"> parameter in <literal>pgpool.conf</literal> file.
We will use the default 9898 for <xref linkend="guc-pcp-port"> in this tutorial.
<programlisting>
- pcp_port = 9898
+pcp_port = 9898
</programlisting>
</para>
</sect3>
connections from <productname>Pgpool-II</productname>.
<programlisting>
- backend_hostname0 = 'localhost'
- backend_port0 = 5432
- backend_weight0 = 1
- backend_hostname1 = 'localhost'
- backend_port1 = 5433
- backend_weight1 = 1
- backend_hostname2 = 'localhost'
- backend_port2 = 5434
- backend_weight2 = 1
+backend_hostname0 = 'localhost'
+backend_port0 = 5432
+backend_weight0 = 1
+backend_hostname1 = 'localhost'
+backend_port1 = 5433
+backend_weight1 = 1
+backend_hostname2 = 'localhost'
+backend_port2 = 5434
+backend_weight2 = 1
</programlisting>
For <xref linkend="guc-backend-hostname">, <xref linkend="guc-backend-port">,
command on a terminal.
<programlisting>
- $ pgpool
+$ pgpool
</programlisting>
The above command, however, prints no log messages because <productname>
option to <command>pgpool</command> command so <productname>Pgpool-II</productname>
is executed as non-daemon process, and the terminal will not be detached.
<programlisting>
- $ pgpool -n &
+$ pgpool -n &
</programlisting>
The log messages are printed on the terminal, so it is recommended to use the following options.
<programlisting>
- $ pgpool -n -d > /tmp/pgpool.log 2>&1 &
+$ pgpool -n -d > /tmp/pgpool.log 2>&1 &
</programlisting>
The <literal>-d</literal> option enables debug messages to be generated.
For example, you can use <ulink url="https://httpd.apache.org/docs/2.4/programs/rotatelogs.html">
<command>rotatelogs</command></ulink> from Apache2:
<programlisting>
- $ pgpool -n 2>&1 | /usr/local/apache2/bin/rotatelogs \
- -l -f /var/log/pgpool/pgpool.log.%A 86400 &
+$ pgpool -n 2>&1 | /usr/local/apache2/bin/rotatelogs \
+-l -f /var/log/pgpool/pgpool.log.%A 86400 &
</programlisting>
This will generate a log file named <literal>"pgpool.log.Thursday"</literal>
then rotate it 00:00 at midnight. Rotatelogs adds logs to a file if it already
exists. To delete old log files before rotation, you could use cron:
<programlisting>
- 55 23 * * * /usr/bin/find /var/log/pgpool -type f -mtime +5 -exec /bin/rm -f '{}' \;
+55 23 * * * /usr/bin/find /var/log/pgpool -type f -mtime +5 -exec /bin/rm -f '{}' \;
</programlisting>
Please note that rotatelogs may exist as <literal>/usr/sbin/rotatelogs2</literal>
<command>rotatelogs</command> starts and is available in apache2 2.2.9 or greater.
Also <ulink url="http://www.cronolog.org/">cronolog</ulink> can be used.
<programlisting>
- $ pgpool -n 2>&1 | /usr/sbin/cronolog \
- --hardlink=/var/log/pgsql/pgpool.log \
- '/var/log/pgsql/%Y-%m-%d-pgpool.log' &
+$ pgpool -n 2>&1 | /usr/sbin/cronolog \
+--hardlink=/var/log/pgsql/pgpool.log \
+'/var/log/pgsql/%Y-%m-%d-pgpool.log' &
</programlisting>
To stop <productname>Pgpool-II</productname> execute the following command.
<programlisting>
- $ pgpool stop
+$ pgpool stop
</programlisting>
If any client is still connected, <productname>Pgpool-II</productname>
command instead if you want to shutdown <productname>Pgpool-II</productname>
forcibly.
<programlisting>
- $ pgpool -m fast stop
+$ pgpool -m fast stop
</programlisting>
</para>
To enable the database replication function, set
<xref linkend="guc-replication-mode"> to on in <literal>pgpool.conf</literal> file.
<programlisting>
- replication_mode = true
+replication_mode = true
</programlisting>
When <xref linkend="guc-replication-mode"> is on, <productname>Pgpool-II</productname>
will send a copy of a received query to all the database nodes.
<productname>Pgpool-II</productname> will distribute <acronym>SELECT</acronym> queries
among the database nodes.
<programlisting>
- load_balance_mode = true
+load_balance_mode = true
</programlisting>
In this section, we will enable both <xref linkend="guc-replication-mode">
and <xref linkend="guc-load-balance-mode">.
<productname>Pgpool-II</productname>, and the database will be created
on all the nodes.
<programlisting>
- $ createdb -p 9999 bench_replication
+$ createdb -p 9999 bench_replication
</programlisting>
Then, we'll execute <ulink url="https://www.postgresql.org/docs/current/static/pgbench.html">
<command>pgbench</command></ulink> with <literal>-i</literal> option.
<literal>-i</literal> option initializes the database with pre-defined tables and data.
<programlisting>
- $ pgbench -i -p 9999 bench_replication
+$ pgbench -i -p 9999 bench_replication
</programlisting>
The following table is the summary of tables and data, which will be created by
<ulink url="https://www.postgresql.org/docs/current/static/pgbench.html">
The following script will display the number of rows in branches,
tellers, accounts, and history tables on all the nodes (5432, 5433, 5434).
<programlisting>
- $ for port in 5432 5433 5434; do
- > echo $port
- > for table_name in branches tellers accounts history; do
- > echo $table_name
- > psql -c "SELECT count(*) FROM $table_name" -p $port bench_replication
- > done
- > done
+$ for port in 5432 5433 5434; do
+> echo $port
+> for table_name in branches tellers accounts history; do
+> echo $table_name
+> psql -c "SELECT count(*) FROM $table_name" -p $port bench_replication
+> done
+> done
</programlisting>
</para>
<para>
First of all, set <xref linkend="guc-use-watchdog"> to on.
<programlisting>
- use_watchdog = on
- # Activates watchdog
+use_watchdog = on
+# Activates watchdog
</programlisting>
</para>
</sect3>
Specify the up stream servers (e.g. application servers).
Leaving it blank is also fine.
<programlisting>
- trusted_servers = ''
- # trusted server list which are used
- # to confirm network connection
- # (hostA,hostB,hostC,...)
+trusted_servers = ''
+ # trusted server list which are used
+ # to confirm network connection
+ # (hostA,hostB,hostC,...)
</programlisting>
</para>
</sect3>
<para>
Specify the TCP port number for watchdog communication.
<programlisting>
- wd_port = 9000
- # port number for watchdog service
+wd_port = 9000
+ # port number for watchdog service
</programlisting>
</para>
</sect3>
Specify the IP address to be used as a virtual IP address
in the <xref linkend="guc-delegate-IP">.
<programlisting>
- delegate_IP = '133.137.177.143'
- # delegate IP address
+delegate_IP = '133.137.177.143'
+# delegate IP address
</programlisting>
</para>
<note>
<title>Active (osspc16) Server configurations</title>
<para>
<programlisting>
- other_pgpool_hostname0 = 'osspc20'
- # Host name or IP address to connect to for other pgpool 0
- other_pgpool_port0 = 9999
- # Port number for othet pgpool 0
- other_wd_port0 = 9000
- # Port number for othet watchdog 0
+other_pgpool_hostname0 = 'osspc20'
+ # Host name or IP address to connect to for other pgpool 0
+other_pgpool_port0 = 9999
+ # Port number for othet pgpool 0
+other_wd_port0 = 9000
+ # Port number for othet watchdog 0
</programlisting>
</para>
</sect3>
<title>Standby (osspc20) Server configurations</title>
<para>
<programlisting>
- other_pgpool_hostname0 = 'osspc16'
- # Host name or IP address to connect to for other pgpool 0
- other_pgpool_port0 = 9999
- # Port number for othet pgpool 0
- other_wd_port0 = 9000
- # Port number for othet watchdog 0
+other_pgpool_hostname0 = 'osspc16'
+ # Host name or IP address to connect to for other pgpool 0
+other_pgpool_port0 = 9999
+ # Port number for othet pgpool 0
+other_wd_port0 = 9000
+ # Port number for othet watchdog 0
</programlisting>
</para>
</sect3>
<para>
First start the <productname>Pgpool-II</productname> on Active server.
<programlisting>
- [user@osspc16]$ su -
- [root@osspc16]# {installed_dir}/bin/pgpool -n -f {installed_dir}/etc/pgpool.conf > pgpool.log 2>&1
+[user@osspc16]$ su -
+[root@osspc16]# {installed_dir}/bin/pgpool -n -f {installed_dir}/etc/pgpool.conf > pgpool.log 2>&1
</programlisting>
Log messages will show that <productname>Pgpool-II</productname>
has the virtual IP address and starts watchdog process.
<programlisting>
- LOG: I am announcing my self as master/coordinator watchdog node
- LOG: I am the cluster leader node
- DETAIL: our declare coordinator message is accepted by all nodes
- LOG: I am the cluster leader node. Starting escalation process
- LOG: escalation process started with PID:59449
- <emphasis>LOG: watchdog process is initialized
- LOG: watchdog: escalation started
- LOG: I am the master watchdog node</emphasis>
- DETAIL: using the local backend node status
+LOG: I am announcing my self as master/coordinator watchdog node
+LOG: I am the cluster leader node
+DETAIL: our declare coordinator message is accepted by all nodes
+LOG: I am the cluster leader node. Starting escalation process
+LOG: escalation process started with PID:59449
+<emphasis>LOG: watchdog process is initialized
+LOG: watchdog: escalation started
+LOG: I am the master watchdog node</emphasis>
+ DETAIL: using the local backend node status
</programlisting>
</para>
</sect3>
<para>
Now start the <productname>Pgpool-II</productname> on Standby server.
<programlisting>
- [user@osspc20]$ su -
- [root@osspc20]# {installed_dir}/bin/pgpool -n -f {installed_dir}/etc/pgpool.conf > pgpool.log 2>&1
+[user@osspc20]$ su -
+[root@osspc20]# {installed_dir}/bin/pgpool -n -f {installed_dir}/etc/pgpool.conf > pgpool.log 2>&1
</programlisting>
Log messages will show that <productname>Pgpool-II</productname>
has joind the watchdog cluster as standby watchdog.
<programlisting>
- LOG: watchdog cluster configured with 1 remote nodes
- LOG: watchdog remote node:0 on Linux_osspc16_9000:9000
- LOG: interface monitoring is disabled in watchdog
- LOG: IPC socket path: "/tmp/.s.PGPOOLWD_CMD.9000"
- LOG: watchdog node state changed from [DEAD] to [LOADING]
- LOG: new outbond connection to Linux_osspc16_9000:9000
- LOG: watchdog node state changed from [LOADING] to [INITIALIZING]
- LOG: watchdog node state changed from [INITIALIZING] to [STANDBY]
- <emphasis>
- LOG: successfully joined the watchdog cluster as standby node
- DETAIL: our join coordinator request is accepted by cluster leader node "Linux_osspc16_9000"
- LOG: watchdog process is initialized
- </emphasis>
+LOG: watchdog cluster configured with 1 remote nodes
+LOG: watchdog remote node:0 on Linux_osspc16_9000:9000
+LOG: interface monitoring is disabled in watchdog
+LOG: IPC socket path: "/tmp/.s.PGPOOLWD_CMD.9000"
+LOG: watchdog node state changed from [DEAD] to [LOADING]
+LOG: new outbond connection to Linux_osspc16_9000:9000
+LOG: watchdog node state changed from [LOADING] to [INITIALIZING]
+LOG: watchdog node state changed from [INITIALIZING] to [STANDBY]
+<emphasis>
+LOG: successfully joined the watchdog cluster as standby node
+DETAIL: our join coordinator request is accepted by cluster leader node "Linux_osspc16_9000"
+LOG: watchdog process is initialized
+</emphasis>
</programlisting>
</para>
</sect3>
<para>
Confirm to ping to the virtual IP address.
<programlisting>
- [user@someserver]$ ping 133.137.177.142
- PING 133.137.177.143 (133.137.177.143) 56(84) bytes of data.
- 64 bytes from 133.137.177.143: icmp_seq=1 ttl=64 time=0.328 ms
- 64 bytes from 133.137.177.143: icmp_seq=2 ttl=64 time=0.264 ms
- 64 bytes from 133.137.177.143: icmp_seq=3 ttl=64 time=0.412 ms
+[user@someserver]$ ping 133.137.177.142
+PING 133.137.177.143 (133.137.177.143) 56(84) bytes of data.
+64 bytes from 133.137.177.143: icmp_seq=1 ttl=64 time=0.328 ms
+64 bytes from 133.137.177.143: icmp_seq=2 ttl=64 time=0.264 ms
+64 bytes from 133.137.177.143: icmp_seq=3 ttl=64 time=0.412 ms
</programlisting>
Confirm if the Active server which started at first has the virtual IP address.
<programlisting>
- [root@osspc16]# ifconfig
- eth0 ...
+[root@osspc16]# ifconfig
+eth0 ...
- eth0:0 inet addr:133.137.177.143 ...
+eth0:0 inet addr:133.137.177.143 ...
- lo ...
+lo ...
</programlisting>
Confirm if the Standby server which started not at first doesn't have the virtual IP address.
<programlisting>
- [root@osspc20]# ifconfig
- eth0 ...
+[root@osspc20]# ifconfig
+eth0 ...
- lo ...
+lo ...
</programlisting>
Try to connect <productname>PostgreSQL</productname> by "psql -h delegate_IP -p port".
<programlisting>
- [user@someserver]$ psql -h 133.137.177.142 -p 9999 -l
+[user@someserver]$ psql -h 133.137.177.142 -p 9999 -l
</programlisting>
</para>
</sect2>
Confirm how the Standby server works when the Active server can't provide its service.
Stop <productname>Pgpool-II</productname> on the Active server.
<programlisting>
- [root@osspc16]# {installed_dir}/bin/pgpool stop
+[root@osspc16]# {installed_dir}/bin/pgpool stop
</programlisting>
Then, the Standby server starts to use the virtual IP address. Log shows:
<programlisting>
- <emphasis>
- LOG: remote node "Linux_osspc16_9000" is shutting down
- LOG: watchdog cluster has lost the coordinator node
- </emphasis>
- LOG: watchdog node state changed from [STANDBY] to [JOINING]
- LOG: watchdog node state changed from [JOINING] to [INITIALIZING]
- LOG: I am the only alive node in the watchdog cluster
- HINT: skiping stand for coordinator state
- LOG: watchdog node state changed from [INITIALIZING] to [MASTER]
- LOG: I am announcing my self as master/coordinator watchdog node
- LOG: I am the cluster leader node
- DETAIL: our declare coordinator message is accepted by all nodes
- <emphasis>
- LOG: I am the cluster leader node. Starting escalation process
- LOG: watchdog: escalation started
- </emphasis>
- LOG: watchdog escalation process with pid: 59551 exit with SUCCESS.
+<emphasis>
+LOG: remote node "Linux_osspc16_9000" is shutting down
+LOG: watchdog cluster has lost the coordinator node
+</emphasis>
+LOG: watchdog node state changed from [STANDBY] to [JOINING]
+LOG: watchdog node state changed from [JOINING] to [INITIALIZING]
+LOG: I am the only alive node in the watchdog cluster
+HINT: skiping stand for coordinator state
+LOG: watchdog node state changed from [INITIALIZING] to [MASTER]
+LOG: I am announcing my self as master/coordinator watchdog node
+LOG: I am the cluster leader node
+DETAIL: our declare coordinator message is accepted by all nodes
+<emphasis>
+LOG: I am the cluster leader node. Starting escalation process
+LOG: watchdog: escalation started
+</emphasis>
+LOG: watchdog escalation process with pid: 59551 exit with SUCCESS.
</programlisting>
Confirm to ping to the virtual IP address.
<programlisting>
- [user@someserver]$ ping 133.137.177.142
- PING 133.137.177.143 (133.137.177.143) 56(84) bytes of data.
- 64 bytes from 133.137.177.143: icmp_seq=1 ttl=64 time=0.328 ms
- 64 bytes from 133.137.177.143: icmp_seq=2 ttl=64 time=0.264 ms
- 64 bytes from 133.137.177.143: icmp_seq=3 ttl=64 time=0.412 ms
+[user@someserver]$ ping 133.137.177.142
+PING 133.137.177.143 (133.137.177.143) 56(84) bytes of data.
+64 bytes from 133.137.177.143: icmp_seq=1 ttl=64 time=0.328 ms
+64 bytes from 133.137.177.143: icmp_seq=2 ttl=64 time=0.264 ms
+64 bytes from 133.137.177.143: icmp_seq=3 ttl=64 time=0.412 ms
</programlisting>
Confirm that the Active server doesn't use the virtual IP address any more.
<programlisting>
- [root@osspc16]# ifconfig
- eth0 ...
+[root@osspc16]# ifconfig
+eth0 ...
- lo ...
+lo ...
</programlisting>
Confirm that the Standby server uses the virtual IP address.
<programlisting>
- [root@osspc20]# ifconfig
- eth0 ...
+[root@osspc20]# ifconfig
+eth0 ...
- eth0:0 inet addr:133.137.177.143 ...
+eth0:0 inet addr:133.137.177.143 ...
- lo ...
+lo ...
</programlisting>
Try to connect <productname>PostgreSQL</productname> by "psql -h delegate_IP -p port".
<programlisting>
- [user@someserver]$ psql -h 133.137.177.142 -p 9999 -l
+[user@someserver]$ psql -h 133.137.177.142 -p 9999 -l
</programlisting>
</para>
the qyery to check <xref linkend="guc-wd-lifecheck-query"> and
finaly the type of lifecheck <xref linkend="guc-wd-lifecheck-method">.
<programlisting>
- wd_lifecheck_method = 'query'
- # Method of watchdog lifecheck ('heartbeat' or 'query' or 'external')
- # (change requires restart)
- wd_interval = 10
- # lifecheck interval (sec) > 0
- wd_life_point = 3
- # lifecheck retry times
- wd_lifecheck_query = 'SELECT 1'
- # lifecheck query to pgpool from watchdog
+wd_lifecheck_method = 'query'
+ # Method of watchdog lifecheck ('heartbeat' or 'query' or 'external')
+ # (change requires restart)
+wd_interval = 10
+ # lifecheck interval (sec) > 0
+wd_life_point = 3
+ # lifecheck retry times
+wd_lifecheck_query = 'SELECT 1'
+ # lifecheck query to pgpool from watchdog
</programlisting>
</para>
switching to send ARP request <xref linkend="guc-arping-cmd">
and the path to it <xref linkend="guc-arping-path">.
<programlisting>
- ifconfig_path = '/sbin'
- # ifconfig command path
- if_up_cmd = 'ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0'
- # startup delegate IP command
- if_down_cmd = 'ifconfig eth0:0 down'
- # shutdown delegate IP command
+ifconfig_path = '/sbin'
+# ifconfig command path
+if_up_cmd = 'ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0'
+# startup delegate IP command
+if_down_cmd = 'ifconfig eth0:0 down'
+# shutdown delegate IP command
- arping_path = '/usr/sbin' # arping command path
+arping_path = '/usr/sbin' # arping command path
- arping_cmd = 'arping -U $_IP_$ -w 1'
+arping_cmd = 'arping -U $_IP_$ -w 1'
</programlisting>
You can also use the custom scripts to bring up and bring down the
virtual IP using <xref linkend="guc-wd-escalation-command"> and
</sect2>
</sect1>
+ <sect1 id="example-cluster">
+ <title><productname>Pgpoo-II</productname> + Watchdog Setup Example</title>
+ <para>
+This section shows an example of streaming replication configuration using <productname>Pgpool-II</productname>. In this example, we use 3 <productname>Pgpool-II</productname> servers to manage <productname>PostgreSQL</productname> servers to create a robust cluster system and avoid the single point of failure or split brain.
+ </para>
+ <sect2 id="example-cluster-requirement">
+ <title>Requirements</title>
+ <para>
+We assume that all the Pgpool-II servers and the <productname>PostgreSQL</productname> servers are in the same subnet.
+ </para>
+ </sect2>
+
+ <sect2 id="example-cluster-structure">
+ <title>Cluster System Configuration</title>
+ <para>
+We use 2 <productname>PostgreSQL</productname> servers and 3 <productname>Pgpool-II</productname> servers with CentOS7. Let these servers be <literal>osspc16</literal>, <literal>osspc17</literal>, <literal>osspc18</literal>, <literal>osspc19</literal> and <literal>osspc20</literal>.
+ </para>
+ <para>
+ <figure>
+ <title>Cluster System Configuration</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="cluster.gif">
+ </imageobject>
+ </mediaobject>
+ </figure>
+ </para>
+ <note>
+ <para>
+ The roles of <literal>Active</literal>, <literal>Standy</literal>, <literal>Primary</literal>, <literal>Standby</literal> are not fixed and may be changed by further operations.
+ </para>
+ </note>
+ </sect2>
+
+ <sect2 id="example-cluster-installation">
+ <title>Installation</title>
+ <para>
+In this example, we install <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> by using RPM packages.
+ </para>
+
+ <table id="example-cluster-table">
+ <title><productname>Pgpool-II</productname>, <productname>PostgreSQL</productname> version informations and Configuration</title>
+ <tgroup cols="5">
+ <thead>
+ <row>
+ <entry>Server</entry>
+ <entry>Version</entry>
+ <entry>Host Name</entry>
+ <entry>Port</entry>
+ <entry>$PGDATA Directory</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><productname>PostgreSQL</productname> server (primary)</entry>
+ <entry><productname>PostgreSQL</productname> 9.6.1</entry>
+ <entry>osspc19</entry>
+ <entry>5432</entry>
+ <entry>/var/lib/pgsql/9.6/data</entry>
+ </row>
+ <row>
+ <entry><productname>PostgreSQL</productname> server (standby) </entry>
+ <entry><productname>PostgreSQL</productname> 9.6.1</entry>
+ <entry>osspc20</entry>
+ <entry>5432</entry>
+ <entry>/var/lib/pgsql/9.6/data</entry>
+ </row>
+ <row>
+ <entry><productname>Pgpool-II</productname> server</entry>
+ <entry><productname>Pgpool-II</productname> 3.6.1</entry>
+ <entry>osspc16</entry>
+ <entry>9999</entry>
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry><productname>Pgpool-II</productname> server</entry>
+ <entry><productname>Pgpool-II</productname> 3.6.1</entry>
+ <entry>osspc17</entry>
+ <entry>9999</entry>
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry><productname>Pgpool-II</productname> server</entry>
+ <entry><productname>Pgpool-II</productname> 3.6.1</entry>
+ <entry>osspc18</entry>
+ <entry>9999</entry>
+ <entry>-</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ Install <productname>Pgpool-II</productname> by using Pgpool-II YUM repository.
+ </para>
+ <programlisting>
+# yum install http://www.pgpool.net/yum/rpms/3.6/redhat/rhel-7-x86_64/pgpool-II-release-3.6-1.noarch.rpm
+# yum install pgpool-II-pg96
+# yum install pgpool-II-pg96-debuginfo
+# yum install pgpool-II-pg96-devel
+# yum install pgpool-II-pg96-extensions
+ </programlisting>
+
+ <para>
+ Install <productname>PostgreSQL</productname> by using <productname>PostgreSQL</productname> YUM repository.
+ </para>
+ <programlisting>
+# yum install https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm
+# yum install postgresql96 postgresql96-devel postgresql96-server
+ </programlisting>
+ </sect2>
+
+ <sect2 id="example-cluster-pre-setup">
+ <title>Before Starting</title>
+ <para>
+ Before you start the configuration process, please check the following prerequisites.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+Set up <productname>PostgreSQL</productname> streaming replication on the primary server. In this example, we use WAL archiving.
+ </para>
+ <para>
+First, we create the directory <filename>/var/lib/pgsql/archivedir</filename> to store <acronym>WAL</acronym> segments on both <productname>PostgreSQL</productname> servers (<literal>osspc19</literal> and <literal>osspc20</literal>).
+ </para>
+ <programlisting>
+[PostgreSQL server]$ mkdir /var/lib/pgsql/archivedir
+ </programlisting>
+
+ <para>
+Then we edit the configuration file <filename>$PGDATA/postgresql.conf</filename> on <literal>osspc19</literal> (primary) as follows.
+ </para>
+ <programlisting>
+listen_addresses = '*'
+wal_level = hot_standby
+max_wal_senders = 2
+
+archive_mode = on
+archive_command = 'cp "%p" "/var/lib/pgsql/archivedir/%f"'
+ </programlisting>
+ <para>
+We use the online recovery functionality of Pgpool-II to setup standby server after the primary server is started.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+Because of the security reasons, we create a user <literal>repl</literal> solely used for replication purpose, and a user <literal>pgpool</literal> for streaming replication delay check and health check of <productname>Pgpool-II</productname>. Assuming that all the <productname>Pgpool-II</productname> servers and the <productname>PostgreSQL</productname> servers are in the network of <literal>133.137.174.0/24</literal>, and edit <filename>pg_hba.conf</filename> to enable <literal>md5</literal> authentication method.
+ </para>
+ <programlisting>
+host all pgpool 133.137.174.0/24 md5
+host all all 0.0.0.0/0 md5
+
+host replication repl 133.137.174.0/24 md5
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>
+To use the failover and online recovery of <productname>Pgpool-II</productname>, the settings that allow SSH without passowrd to other servers (<literal>osspc16</literal> - <literal>osspc20</literal>) are necessary.
+ </para>
+ </listitem>
+
+
+ <listitem>
+ <para>
+To allow <literal>repl</literal> user without specifying password for streaming replication and online recovery, we create the <filename>.pgpass</filename> file in <literal>postgres</literal> user's home directory and change the permisson to <literal>600</literal> on both postgreSQL servers <literal>osspc19</literal> and <literal>osspc20</literal>.
+ </para>
+ <programlisting>
+[osspc19]$ cat /var/lib/pgsql/.pgpass
+osspc20:5432:replication:repl:<password of repl user>
+ </programlisting>
+
+ <programlisting>
+[osspc20]$ cat /var/lib/pgsql/.pgpass
+osspc19:5432:replication:repl:<passowrd of repl user>
+ </programlisting>
+
+ <programlisting>
+$ chmod 600 /var/lib/pgsql/.pgpass
+ </programlisting>
+
+ </listitem>
+
+ <listitem>
+ <para>
+When <productname>Pgpool-II</productname> connects to other <productname>Pgpool-II</productname> servers or <productname>PostgreSQL</productname> servers, the target port must be accessible by enabling firewall management softwares. Following is an example for <systemitem>CentOS/RHEL7</systemitem>.
+ </para>
+ <programlisting>
+[PostgreSQL server]# firewall-cmd --permanent --zone=public --add-service=postgresql
+[PostgreSQL server]# firewall-cmd --reload
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>
+The following commands are to enable <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> start on system boot.
+ </para>
+ <programlisting>
+[Pgpool-II server]# systemctl enable pgpool.service
+ </programlisting>
+ <programlisting>
+[PostgreSQL server]# systemctl enable postgresql.service
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="example-cluster-pgpool-config">
+ <title><productname>Pgpool-II</productname> Configuration</title>
+ <sect3 id="example-cluster-pgpool-config-common">
+ <title>Common Settings</title>
+ <para>
+Here are the common settings on <literal>osspc16</literal>, <literal>osspc17</literal> and <literal>osspc18</literal>.
+ </para>
+ <para>
+When installing Pgpool-II from RPM, all the Pgpool-II configuration files are in <filename>/etc/pgpool-II</filename>. In this example, we copy the sample configuration file for streaming replicaton mode.
+ </para>
+ <programlisting>
+# cp /etc/pgpool-II/pgpool.conf.sample-stream /etc/pgpool-II/pgpool.conf
+ </programlisting>
+ <para>
+To allow Pgpool-II to accept all incoming connections, we set <varname>listen_addresses = '*'</varname>.
+ </para>
+ <programlisting>
+listen_addresses = '*'
+ </programlisting>
+ <para>
+Specifiy replication delay check user and password.
+ </para>
+ <programlisting>
+sr_check_user = 'pgpool'
+sr_check_password = 'pgpool'
+ </programlisting>
+ <para>
+Enable health check so that pgpool-II performs failover. Also, if the network is unstable, the health check fails even though the backend is running properly, failover or degenerate operation may occur. In order to prevent such incorrect detection of health check, we set <varname>health_check_max_retries = 10</varname>.
+ </para>
+ <programlisting>
+health_check_period = 5
+ # Health check period
+ # Disabled (0) by default
+health_check_timeout = 20
+ # Health check timeout
+ # 0 means no timeout
+health_check_user = 'pgpool'
+health_check_password = 'pgpool'
+
+health_check_max_retries = 10
+ </programlisting>
+ <para>
+Specify the backend informations with <literal>osspc19</literal> and <literal>osspc20</literal>.
+ </para>
+ <programlisting>
+# - Backend Connection Settings -
+
+backend_hostname0 = 'osspc19'
+ # Host name or IP address to connect to for backend 0
+backend_port0 = 5432
+ # Port number for backend 0
+backend_weight0 = 1
+ # Weight for backend 0 (only in load balancing mode)
+backend_data_directory0 = '/var/lib/pgsql/9.6/data'
+ # Data directory for backend 0
+backend_flag0 = 'ALLOW_TO_FAILOVER'
+ # Controls various backend behavior
+ # ALLOW_TO_FAILOVER or DISALLOW_TO_FAILOVER
+backend_hostname1 = 'osspc20'
+backend_port1 = 5432
+backend_weight1 = 1
+backend_data_directory1 = '/var/lib/pgsql/9.6/data'
+backend_flag1 = 'ALLOW_TO_FAILOVER'
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-pgpool-config-failover">
+ <title>Failover configuration</title>
+ <para>
+Specify <varname>failover_command</varname> to execute failover.sh script. The special characters <command>%d %P %H %R</command> in failover_command are replcaed with <literal>DB node ID of the detached node</literal>, <literal>Old primary node ID</literal>, <literal>Hostname of the new master node</literal>, <literal>Database cluster directory of the new master node</literal>.
+ </para>
+ <programlisting>
+failover_command = '/etc/pgpool-II/failover.sh %d %P %H %R'
+ </programlisting>
+ <para>
+Create <filename>/etc/pgpool-II/failover.sh</filename>, and set the file permisson to <literal>755</literal>.
+ </para>
+ <programlisting>
+# vi /etc/pgpool-II/failover.sh
+# chmod 755 /etc/pgpool-II/failover.sh
+ </programlisting>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+/etc/pgpool-II/failover.sh
+ </para>
+ <programlisting>
+#! /bin/sh -x
+# Execute command by failover.
+# special values: %d = node id
+# %h = host name
+# %p = port number
+# %D = database cluster path
+# %m = new master node id
+# %M = old master node id
+# %H = new master node host name
+# %P = old primary node id
+# %R = new master database cluster path
+# %r = new master port number
+# %% = '%' character
+
+falling_node=$1 # %d
+old_primary=$2 # %P
+new_primary=$3 # %H
+pgdata=$4 # %R
+
+pghome=/usr/pgsql-9.6
+log=/var/log/pgpool/failover.log
+
+date >> $log
+echo "failed_node_id=$falling_node new_primary=$new_primary" >> $log
+
+if [ $falling_node = $old_primary ]; then
+ if [ $UID -eq 0 ]
+ then
+ su postgres -c "ssh -T postgres@$new_primary $pghome/bin/pg_ctl promote -D $pgdata"
+ else
+ ssh -T postgres@$new_primary $pghome/bin/pg_ctl promote -D $pgdata
+ fi
+ exit 0;
+fi;
+exit 0;
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ </sect3>
+
+ <sect3 id="example-cluster-pgpool-config-online-recovery">
+ <title>Pgpool-II Online Recovery Configurations</title>
+ <para>
+Next, in order to perform online recovery with <productname>Pgpool-II</productname> we specify the <productname>PostgreSQL</productname> user name and online recovery command <command>recovery_1st_stage</command>. Then, we create <filename>recovery_1st_stage</filename> and <filename>pgpool_remote_start</filename> in database cluster directory of <productname>PostgreSQL</productname> primary server, and set the file permissions to <literal>755</literal>.
+ </para>
+ <programlisting>
+recovery_user = 'postgres'
+ # Online recovery user
+recovery_password = 'postgres'
+ # Online recovery password
+
+recovery_1st_stage_command = 'recovery_1st_stage'
+ </programlisting>
+ <programlisting>
+$ vi /var/lib/pgsql/9.6/data/recovery_1st_stage
+$ vi /var/lib/pgsql/9.6/data/pgpool_remote_start
+$ chmod 755 /var/lib/pgsql/9.6/data/recovery_1st_stage
+$ chmod 755 /var/lib/pgsql/9.6/data/pgpool_remote_start
+ </programlisting>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+/var/lib/pgsql/9.6/data/recovery_1st_stage
+ </para>
+ <programlisting>
+#!/bin/bash -x
+# Recovery script for streaming replication.
+
+pgdata=$1
+remote_host=$2
+remote_pgdata=$3
+port=$4
+
+pghome=/usr/pgsql-9.6
+archivedir=/var/lib/pgsql/archivedir
+hostname=$(hostname)
+
+ssh -T postgres@$remote_host "
+rm -rf $remote_pgdata
+$pghome/bin/pg_basebackup -h $hostname -U repl -D $remote_pgdata -x -c fast
+rm -rf $archivedir/*
+
+cd $remote_pgdata
+cp postgresql.conf postgresql.conf.bak
+sed -e 's/#*hot_standby = off/hot_standby = on/' postgresql.conf.bak > postgresql.conf
+rm -f postgresql.conf.bak
+cat > recovery.conf << EOT
+standby_mode = 'on'
+primary_conninfo = 'host="$hostname" port=$port user=repl'
+restore_command = 'scp $hostname:$archivedir/%f %p'
+EOT
+"
+ </programlisting>
+ </listitem>
+ <listitem>
+
+ <para>
+/var/lib/pgsql/9.6/data/pgpool_remote_start
+ </para>
+ <programlisting>
+#! /bin/sh -x
+
+pghome=/usr/pgsql-9.6
+remote_host=$1
+remote_pgdata=$2
+
+# Start recovery target PostgreSQL server
+ssh -T $remote_host $pghome/bin/pg_ctl -w -D $remote_pgdata start > /dev/null 2>&1 < /dev/null &
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ In order to use the online recovery functionality, the functions of <function>pgpool_recovery</function>, <function>pgpool_remote_start</function>, <function>pgpool_switch_xlog</function> are required, so we need install <function>pgpool_recovery</function> on template1 of <productname>PostgreSQL</productname> server <literal>osspc19</literal>.
+ </para>
+ <programlisting>
+# su - postgres
+$ psql template1
+=# CREATE EXTENSION pgpool_recovery;
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-pgpool-config-auth">
+ <title>Client Authentication Configuration</title>
+ <para>
+Because in the section <link linkend="EXAMPLE-CLUSTER-PRE-SETUP">Before Starting</link>, we already set <productname>PostgreSQL</productname> authentication method to <acronym>md5</acronym>, it is necessary to set a client authentication by <productname>Pgpool-II</productname> to connect to backend nodes. When installing from RPM, the <productname>Pgpool-II</productname> configuration file <filename>pool_hba.conf</filename> is in <filename>/etc/pgpool-II</filename>. By default, pool_hba authentication is disabled, and set <varname>enable_pool_hba = on</varname> to enable it.
+ </para>
+ <programlisting>
+enable_pool_hba = on
+ </programlisting>
+ <para>
+The format of <filename>pool_hba.conf</filename> file follows very closely PostgreSQL's <filename>pg_hba.conf</filename> format. Set <literal>pgpool</literal> and <literal>postgres</literal> user's authentication method to <literal>md5</literal>.
+ </para>
+ <programlisting>
+host all pgpool 0.0.0.0/0 md5
+host all postgres 0.0.0.0/0 md5
+ </programlisting>
+ <para>
+To use md5 authentication, we need to register the user name and password in file <filename>pool_passwd</filename>. Execute command <command>pg_md5 --md5auth --username=<user name> <password></command> to regist user name and MD5-hashed password in file <filename>pool_passwd</filename>. If <filename>pool_passwd</filename> doesn't exist yet, it will be created in the same directory as <filename>pgpool.conf</filename>.
+ </para>
+ <programlisting>
+# pg_md5 --md5auth --username=pgpool <password of pgpool user>
+# pg_md5 --md5auth --username=postgres <password of postgres user>
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-pgpool-config-watchdog">
+ <title>Watchdog Configuration</title>
+ <para>
+ Enable watchdog functionality on <literal>osspc16</literal>, <literal>osspc17</literal>, <literal>osspc18</literal>.
+ </para>
+ <programlisting>
+use_watchdog = on
+ </programlisting>
+ <para>
+ Specify virtual IP address that accepts connections from clients on <literal>osspc16</literal>, <literal>osspc17</literal>, <literal>osspc18</literal>. Ensure that the IP address set to virtual IP isn't used yet.
+ </para>
+ <programlisting>
+delegate_IP = '133.137.174.153'
+ </programlisting>
+ <para>
+ Specify the hostname and port number of each <productname>Pgpool-II</productname> server.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>osspc16</literal>
+ </para>
+ <programlisting>
+wd_hostname = 'osspc16'
+wd_port = 9000
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc17</literal>
+ </para>
+ <programlisting>
+wd_hostname = 'osspc17'
+wd_port = 9000
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc18</literal>
+ </para>
+ <programlisting>
+wd_hostname = 'osspc18'
+wd_port = 9000
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Specify the hostname, <productname>Pgpool-II</productname> port number, and watchdog port number of monitored <productname>Pgpool-II</productname> servers on each <productname>Pgpool-II</productname> server.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>osspc16</literal>
+ </para>
+ <programlisting>
+# - Other pgpool Connection Settings -
+
+other_pgpool_hostname0 = 'osspc17'
+ # Host name or IP address to connect to for other pgpool 0
+ # (change requires restart)
+other_pgpool_port0 = 9999
+ # Port number for othet pgpool 0
+ # (change requires restart)
+other_wd_port0 = 9000
+ # Port number for othet watchdog 0
+ # (change requires restart)
+other_pgpool_hostname1 = 'osspc18'
+other_pgpool_port1 = 9999
+other_wd_port1 = 9000
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc17</literal>
+ </para>
+ <programlisting>
+# - Other pgpool Connection Settings -
+
+other_pgpool_hostname0 = 'osspc16'
+ # Host name or IP address to connect to for other pgpool 0
+ # (change requires restart)
+other_pgpool_port0 = 9999
+ # Port number for othet pgpool 0
+ # (change requires restart)
+other_wd_port0 = 9000
+ # Port number for othet watchdog 0
+ # (change requires restart)
+other_pgpool_hostname1 = 'osspc18'
+other_pgpool_port1 = 9999
+other_wd_port1 = 9000
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc18</literal>
+ </para>
+ <programlisting>
+# - Other pgpool Connection Settings -
+
+other_pgpool_hostname0 = 'osspc16'
+ # Host name or IP address to connect to for other pgpool 0
+ # (change requires restart)
+other_pgpool_port0 = 9999
+ # Port number for othet pgpool 0
+ # (change requires restart)
+other_wd_port0 = 9000
+ # Port number for othet watchdog 0
+ # (change requires restart)
+other_pgpool_hostname1 = 'osspc17'
+other_pgpool_port1 = 9999
+other_wd_port1 = 9000
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Specify the hostname and port number of destination for sending heartbeat signal on <literal>osspc16</literal>, <literal>osspc17</literal>, <literal>osspc18</literal>.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>osspc16</literal>
+ </para>
+ <programlisting>
+heartbeat_destination0 = 'osspc17'
+ # Host name or IP address of destination 0
+ # for sending heartbeat signal.
+ # (change requires restart)
+heartbeat_destination_port0 = 9694
+ # Port number of destination 0 for sending
+ # heartbeat signal. Usually this is the
+ # same as wd_heartbeat_port.
+ # (change requires restart)
+heartbeat_device0 = ''
+ # Name of NIC device (such like 'eth0')
+ # used for sending/receiving heartbeat
+ # signal to/from destination 0.
+ # This works only when this is not empty
+ # and pgpool has root privilege.
+ # (change requires restart)
+
+heartbeat_destination1 = 'osspc18'
+heartbeat_destination_port1 = 9694
+heartbeat_device1 = ''
+
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc17</literal>
+ </para>
+ <programlisting>
+heartbeat_destination0 = 'osspc16'
+ # Host name or IP address of destination 0
+ # for sending heartbeat signal.
+ # (change requires restart)
+heartbeat_destination_port0 = 9694
+ # Port number of destination 0 for sending
+ # heartbeat signal. Usually this is the
+ # same as wd_heartbeat_port.
+ # (change requires restart)
+heartbeat_device0 = ''
+ # Name of NIC device (such like 'eth0')
+ # used for sending/receiving heartbeat
+ # signal to/from destination 0.
+ # This works only when this is not empty
+ # and pgpool has root privilege.
+ # (change requires restart)
+
+heartbeat_destination1 = 'osspc18'
+heartbeat_destination_port1 = 9694
+heartbeat_device1 = ''
+
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>osspc18</literal>
+ </para>
+ <programlisting>
+heartbeat_destination0 = 'osspc16'
+ # Host name or IP address of destination 0
+ # for sending heartbeat signal.
+ # (change requires restart)
+heartbeat_destination_port0 = 9694
+ # Port number of destination 0 for sending
+ # heartbeat signal. Usually this is the
+ # same as wd_heartbeat_port.
+ # (change requires restart)
+heartbeat_device0 = ''
+ # Name of NIC device (such like 'eth0')
+ # used for sending/receiving heartbeat
+ # signal to/from destination 0.
+ # This works only when this is not empty
+ # and pgpool has root privilege.
+ # (change requires restart)
+
+heartbeat_destination1 = 'osspc17'
+heartbeat_destination_port1 = 9694
+heartbeat_device1 = ''
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="example-cluster-pgpool-config-pcp">
+ <title>PCP Command Configuration</title>
+ <para>
+ Because user authentication is required to use the <literal>PCP</literal> command, we specify user name and <literal>md5</literal> encrypted password in <filename>pcp.conf</filename>. Here we create the encrypted password for user <literal>postgres</literal>, and add <username: encrypted password≷ in <filename>/etc/pgpool-II/pcp.conf</filename>.
+ </para>
+ <programlisting>
+# pg_md5 -p
+Password: (input password)
+(paste the md5 encrypted password to pcp.conf)
+
+# vi /etc/pgpool-II/pcp.conf
+(add password entry)
+user name:md5 encrypted password
+ </programlisting>
+ <para>
+The settings of Pgpool-II is completed.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="example-cluster-start-stop">
+ <title>Starting/Stopping Pgpool-II</title>
+ <para>
+ Next we start <productname>Pgpool-II</productname>. Before starting <productname>Pgpool-II</productname>, please start <productname>PostgreSQL</productname> servers first. Also, when stopping <productname>PostgreSQL</productname>, it is necessary to stop Pgpool-II first.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+Starting <productname>Pgpool-II</productname>
+ </para>
+ <para>
+ In section <link linkend="EXAMPLE-CLUSTER-PRE-SETUP">Before Starting</link>, we already set the auto-start of <productname>Pgpool-II</productname>. To start <productname>Pgpool-II</productname>, restart the whole system or execute the following command.
+ </para>
+ <programlisting>
+# systemctl start pgpool.service
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Stopping <productname>Pgpool-II</productname>
+ </para>
+ <programlisting>
+# systemctl stop pgpool.service
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="example-cluster-log">
+ <title>Log</title>
+ <para>
+ Use <command>journalctl</command> command to see <productname>Pgpool-II</productname> logs.
+ </para>
+ <programlisting>
+# journalctl -a | grep pgpool
+ </programlisting>
+ </sect2>
+
+ <sect2 id="example-cluster-try">
+ <title>How to use</title>
+ <para>
+ Let's start to use <productname>Pgpool-II</productname>. First, let's start <productname>Pgpool-II</productname> on <literal>osspc16</literal>, <literal>osspc17</literal>, <literal>osspc18</literal> by using the following command.
+ </para>
+ <programlisting>
+# systemctl start pgpool.service
+ </programlisting>
+
+ <sect3 id="example-cluster-try-standby">
+ <title>Set up PostgreSQL standby server</title>
+ <para>
+First, we should set up <productname>PostgreSQL</productname> standby server by using Pgpool-II online recovery functionality. Ensure that <filename>recovery_1st_stage</filename> and <filename>pgpool_remote_start</filename> scripts used by <command>pcp_recovery_node</command> command are in database cluster directory of <productname>PostgreSQL</productname> primary server (<literal>osspc19</literal>).
+ </para>
+ <programlisting>
+# pcp_recovery_node -h 133.137.174.153 -p 9898 -U postgres -n 1
+ </programlisting>
+ <para>
+ After executing <command>pcp_recovery_node</command> command, vertify that <literal>osspc20</literal> is started as a <productname>PostgreSQL</productname> standby server.
+ </para>
+ <programlisting>
+# psql -h 133.137.174.153 -p 9999 -U pgpool postgres
+
+postgres=> show pool_nodes;
+ node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay
+---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------
+ 0 | osspc19 | 5432 | up | 0.500000 | primary | 0 | true | 0
+ 1 | osspc20 | 5432 | up | 0.500000 | standby | 0 | false | 0
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-try-watchdog">
+ <title>Switching active/standby watchdog</title>
+ <para>
+ Confirm the watchdog status by using <command>pcp_watchdog_info</command>. The <command>Pgpool-II</command> server which is started first run as <literal>MASTER</literal>.
+ </para>
+ <programlisting>
+# pcp_watchdog_info -h 133.137.174.153 -p 9898 -U postgres
+Password:
+3 YES osspc16:9999 Linux osspc16 osspc16
+
+osspc16:9999 Linux osspc16 osspc16 9999 9000 4 MASTER #The Pgpool-II server started first becames "MASTER".
+osspc17:9999 Linux osspc17 osspc17 9999 9000 7 STANDBY #run as standby
+osspc18:9999 Linux osspc18 osspc18 9999 9000 7 STANDBY #run as standby
+ </programlisting>
+ <para>
+Stop active server <literal>osspc16</literal>, then <literal>osspc17</literal> or <literal>osspc18</literal> will be promoted to active server. To stop <literal>osspc16</literal>, we can stop <productname>Pgpool-II</productname> service or shutdown the whole system. Here, we stop <productname>Pgpool-II</productname> service.
+ </para>
+ <programlisting>
+[root@osspc16 ~]# systemctl stop pgpool.service
+[root@osspc16 ~]# pcp_watchdog_info -h 133.137.174.153 -p 9898 -U postgres
+Password:
+3 YES osspc17:9999 Linux osspc17 osspc17
+
+osspc17:9999 Linux osspc17 osspc17 9999 9000 4 MASTER #osspc17 is promoted to MASTER
+osspc16:9999 Linux osspc16 osspc16 9999 9000 10 SHUTDOWN #osspc16 is stopped
+osspc18:9999 Linux osspc18 osspc18 9999 9000 7 STANDBY #osspc18 runs as STANDBY
+ </programlisting>
+ <para>
+Start <productname>Pgpool-II</productname> (<literal>osspc16</literal>) which we have stopped again, and vertify that <literal>osspc16</literal> runs as a standby.
+ </para>
+ <programlisting>
+[root@osspc16 ~]# systemctl start pgpool.service
+[root@osspc16 ~]# pcp_watchdog_info -h 133.137.174.153 -p 9898 -U postgres
+Password:
+3 YES osspc17:9999 Linux osspc17 osspc17
+
+osspc17:9999 Linux osspc17 osspc17 9999 9000 4 MASTER
+osspc16:9999 Linux osspc16 osspc16 9999 9000 7 STANDBY
+osspc18:9999 Linux osspc18 osspc18 9999 9000 7 STANDBY
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-try-failover">
+ <title>Failover</title>
+ <para>
+First, use <command>psql</command> to connect to <productname>PostgreSQL</productname> via virtual IP, and verify the backend informations.
+ </para>
+ <programlisting>
+# psql -h 133.137.174.153 -p 9999 -U pgpool postgres
+
+postgres=> show pool_nodes;
+ node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay
+---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------
+ 0 | osspc19 | 5432 | up | 0.500000 | primary | 0 | true | 0
+ 1 | osspc20 | 5432 | up | 0.500000 | standby | 0 | false | 0
+ </programlisting>
+ <para>
+Next, stop primary <productname>PostgreSQL</productname> server <literal>osspc19</literal>, and verify automatic failover.
+ </para>
+ <programlisting>
+$ pg_ctl -D /var/lib/pgsql/9.6/data -m immediate stop
+ </programlisting>
+ <para>
+After stopping <productname>PostgreSQL</productname> on <literal>osspc19</literal>, failover occurs and <productname>PostgreSQL</productname> on <literal>osspc20</literal> becomes new primary DB.
+ </para>
+ <programlisting>
+# psql -h 133.137.174.153 -p 9999 -U pgpool postgres
+
+postgres=> show pool_nodes;
+ node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay
+---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------
+ 0 | osspc19 | 5432 | down | 0.500000 | standby | 0 | false | 0
+ 1 | osspc20 | 5432 | up | 0.500000 | primary | 0 | true | 0
+ </programlisting>
+ </sect3>
+
+ <sect3 id="example-cluster-try-online-recovery">
+ <title>Online Recovery</title>
+ <para>
+Here, we use <productname>Pgpool-II</productname> online recovery functionality to restore <literal>osspc19</literal> (old primary server) as a standby. Before restoring the old primary server, please ensure that <filename>recovery_1st_stage</filename> and <filename>pgpool_remote_start</filename> scripts exist in database cluster directory of current primary server <literal>osspc20</literal>.
+ </para>
+ <programlisting>
+# pcp_recovery_node -h 133.137.174.153 -p 9898 -U postgres -n 0
+ </programlisting>
+ <para>
+Then verify that <literal>osspc19</literal> is started as a standby.
+ </para>
+ <programlisting>
+# psql -h 133.137.174.153 -p 9999 -U pgpool postgres
+
+postgres=> show pool_nodes;
+ node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay
+---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------
+ 0 | osspc19 | 5432 | up | 0.500000 | standby | 0 | false | 0
+ 1 | osspc20 | 5432 | up | 0.500000 | primary | 0 | true | 0
+ </programlisting>
+ </sect3>
+ </sect2>
+
+ </sect1>
+
<sect1 id="example-AWS">
<title>AWS Configuration Example</title>
<para>
<programlisting>
- use_watchdog = on
- delegate_IP = ''
- wd_hostname = 'instance-1-private-ip'
- other_pgpool_hostname0 = 'instance-2-private-ip'
- other_pgpool_port0 = 9999
- other_wd_port0 = 9000
- wd_escalation_command = '$path_to_script/aws-escalation.sh'
- wd_de_escalation_command = '$path_to_script/aws-de-escalation.sh'
+use_watchdog = on
+delegate_IP = ''
+wd_hostname = 'instance-1-private-ip'
+other_pgpool_hostname0 = 'instance-2-private-ip'
+other_pgpool_port0 = 9999
+other_wd_port0 = 9000
+wd_escalation_command = '$path_to_script/aws-escalation.sh'
+wd_de_escalation_command = '$path_to_script/aws-de-escalation.sh'
</programlisting>
</para>
<para>
<programlisting>
- use_watchdog = on
- delegate_IP = ''
- wd_hostname = 'instance-2-private-ip'
- other_pgpool_hostname0 = 'instance-1-private-ip'
- other_pgpool_port0 = 9999
- other_wd_port0 = 9000
- wd_escalation_command = '$path_to_script/aws-escalation.sh'
- wd_de_escalation_command = '$path_to_script/aws-de-escalation.sh'
+use_watchdog = on
+delegate_IP = ''
+wd_hostname = 'instance-2-private-ip'
+other_pgpool_hostname0 = 'instance-1-private-ip'
+other_pgpool_port0 = 9999
+other_wd_port0 = 9000
+wd_escalation_command = '$path_to_script/aws-escalation.sh'
+wd_de_escalation_command = '$path_to_script/aws-de-escalation.sh'
</programlisting>
</para>
<para>
<emphasis>aws-escalation.sh:</emphasis>
<programlisting>
- #! /bin/sh
+#! /bin/sh
- ELASTIC_IP=35.163.178.3
- # replace it with the Elastic IP address you
- # allocated from the aws console
- INSTANCE_ID=i-0a9b64e449b17ed4b
- # replace it with the instance id of the Instance
- # this script is installed on
+ELASTIC_IP=35.163.178.3
+ # replace it with the Elastic IP address you
+ # allocated from the aws console
+INSTANCE_ID=i-0a9b64e449b17ed4b
+ # replace it with the instance id of the Instance
+ # this script is installed on
- echo "Assigning Elastic IP $ELASTIC_IP to the instance $INSTANCE_ID"
- # bring up the Elastic IP
- aws ec2 associate-address --instance-id $INSTANCE_ID --public-ip $ELASTIC_IP
+echo "Assigning Elastic IP $ELASTIC_IP to the instance $INSTANCE_ID"
+# bring up the Elastic IP
+aws ec2 associate-address --instance-id $INSTANCE_ID --public-ip $ELASTIC_IP
- exit 0
+exit 0
</programlisting>
</para>
<para>
<emphasis>aws-de-escalation.sh:</emphasis>
<programlisting>
- #! /bin/sh
+#! /bin/sh
- ELASTIC_IP=35.163.178.3
- # replace it with the Elastic IP address you
- # allocated from the aws console
+ELASTIC_IP=35.163.178.3
+ # replace it with the Elastic IP address you
+ # allocated from the aws console
- echo "disassociating the Elastic IP $ELASTIC_IP from the instance"
- # bring down the Elastic IP
- aws ec2 disassociate-address --public-ip $ELASTIC_IP
- exit 0
+echo "disassociating the Elastic IP $ELASTIC_IP from the instance"
+# bring down the Elastic IP
+aws ec2 disassociate-address --public-ip $ELASTIC_IP
+exit 0
</programlisting>
</para>
</sect3>
The log message of master/active <productname>Pgpool-II</productname> node
will show the message of Elastic IP assignment.
<programlisting>
- LOG: I am the cluster leader node. Starting escalation process
- LOG: escalation process started with PID:23543
- LOG: watchdog: escalation started
- <emphasis>
- Assigning Elastic IP 35.163.178.3 to the instance i-0a9b64e449b17ed4b
- {
- "AssociationId": "eipassoc-39853c42"
- }
- </emphasis>
- LOG: watchdog escalation successful
- LOG: watchdog escalation process with pid: 23543 exit with SUCCESS.
+LOG: I am the cluster leader node. Starting escalation process
+LOG: escalation process started with PID:23543
+LOG: watchdog: escalation started
+<emphasis>
+ Assigning Elastic IP 35.163.178.3 to the instance i-0a9b64e449b17ed4b
+ {
+ "AssociationId": "eipassoc-39853c42"
+ }
+</emphasis>
+LOG: watchdog escalation successful
+LOG: watchdog escalation process with pid: 23543 exit with SUCCESS.
</programlisting>
</para>
<para>
Confirm to ping to the Elastic IP address.
<programlisting>
- [user@someserver]$ ping 35.163.178.3
- PING 35.163.178.3 (35.163.178.3) 56(84) bytes of data.
- 64 bytes from 35.163.178.3: icmp_seq=1 ttl=64 time=0.328 ms
- 64 bytes from 35.163.178.3: icmp_seq=2 ttl=64 time=0.264 ms
- 64 bytes from 35.163.178.3: icmp_seq=3 ttl=64 time=0.412 ms
+[user@someserver]$ ping 35.163.178.3
+PING 35.163.178.3 (35.163.178.3) 56(84) bytes of data.
+64 bytes from 35.163.178.3: icmp_seq=1 ttl=64 time=0.328 ms
+64 bytes from 35.163.178.3: icmp_seq=2 ttl=64 time=0.264 ms
+64 bytes from 35.163.178.3: icmp_seq=3 ttl=64 time=0.412 ms
</programlisting>
</para>
<para>
Try to connect <productname>PostgreSQL</productname> by "psql -h ELASTIC_IP -p port".
<programlisting>
- [user@someserver]$ psql -h 35.163.178.3 -p 9999 -l
+[user@someserver]$ psql -h 35.163.178.3 -p 9999 -l
</programlisting>
</para>
</sect2>
And the <productname>Pgpool-II</productname> log will show the below messages.
<programlisting>
- <emphasis>
- LOG: remote node "172.31.2.94:9999 [Linux ip-172-31-2-94]" is shutting down
- LOG: watchdog cluster has lost the coordinator node
- </emphasis>
- LOG: watchdog node state changed from [STANDBY] to [JOINING]
- LOG: watchdog node state changed from [JOINING] to [INITIALIZING]
- LOG: I am the only alive node in the watchdog cluster
- HINT: skiping stand for coordinator state
- LOG: watchdog node state changed from [INITIALIZING] to [MASTER]
- LOG: I am announcing my self as master/coordinator watchdog node
- LOG: I am the cluster leader node
- DETAIL: our declare coordinator message is accepted by all nodes
- LOG: I am the cluster leader node. Starting escalation process
- LOG: escalation process started with PID:23543
- LOG: watchdog: escalation started
- <emphasis>
- Assigning Elastic IP 35.163.178.3 to the instance i-0dd3e60734a6ebe14
- {
- "AssociationId": "eipassoc-39853c42"
- }
- </emphasis>
- LOG: watchdog escalation successful
- LOG: watchdog escalation process with pid: 61581 exit with SUCCESS.
+<emphasis>
+LOG: remote node "172.31.2.94:9999 [Linux ip-172-31-2-94]" is shutting down
+LOG: watchdog cluster has lost the coordinator node
+</emphasis>
+LOG: watchdog node state changed from [STANDBY] to [JOINING]
+LOG: watchdog node state changed from [JOINING] to [INITIALIZING]
+LOG: I am the only alive node in the watchdog cluster
+HINT: skiping stand for coordinator state
+LOG: watchdog node state changed from [INITIALIZING] to [MASTER]
+LOG: I am announcing my self as master/coordinator watchdog node
+LOG: I am the cluster leader node
+DETAIL: our declare coordinator message is accepted by all nodes
+LOG: I am the cluster leader node. Starting escalation process
+LOG: escalation process started with PID:23543
+LOG: watchdog: escalation started
+<emphasis>
+ Assigning Elastic IP 35.163.178.3 to the instance i-0dd3e60734a6ebe14
+ {
+ "AssociationId": "eipassoc-39853c42"
+ }
+</emphasis>
+LOG: watchdog escalation successful
+LOG: watchdog escalation process with pid: 61581 exit with SUCCESS.
</programlisting>
Confirm to ping to the Elastic IP address again.
<programlisting>
- [user@someserver]$ ping 35.163.178.3
- PING 35.163.178.3 (35.163.178.3) 56(84) bytes of data.
- 64 bytes from 35.163.178.3: icmp_seq=1 ttl=64 time=0.328 ms
- 64 bytes from 35.163.178.3: icmp_seq=2 ttl=64 time=0.264 ms
- 64 bytes from 35.163.178.3: icmp_seq=3 ttl=64 time=0.412 ms
+[user@someserver]$ ping 35.163.178.3
+PING 35.163.178.3 (35.163.178.3) 56(84) bytes of data.
+64 bytes from 35.163.178.3: icmp_seq=1 ttl=64 time=0.328 ms
+64 bytes from 35.163.178.3: icmp_seq=2 ttl=64 time=0.264 ms
+64 bytes from 35.163.178.3: icmp_seq=3 ttl=64 time=0.412 ms
</programlisting>
</para>
<para>
Try to connect <productname>PostgreSQL</productname> by "psql -h ELASTIC_IP -p port".
<programlisting>
- [user@someserver]$ psql -h 35.163.178.3 -p 9999 -l
+[user@someserver]$ psql -h 35.163.178.3 -p 9999 -l
</programlisting>
</para>
</sect2>