Skip to content

Commit

Permalink
Implement a default value for --nodename. (#16)
Browse files Browse the repository at this point in the history
It is not always possible to obtain a default value for --nodename, because
of the way Postgres HBA rules matching is implemented. We need to have an
hostname for the local server that resoves in DNS to an IP that is on the
same server.

So in this patch we find which interface is used to connect to an external
service, either the pg_auto_failover monitor or the Google 8.8.8.8:53
service, and then do a reverse DNS lookup for our local routed IP. If we get
a candidate --nodename, we then do a DNS lookup of it and check that we get
back an IP address that we have on the local server. When all those
conditions are met then we take this hostname as a default --nodename.

When we fail to do DNS lookups (reverse and then forward), keep the local IP
address we found as the default --nodename, it might just work. Users can
still easily override the discovered default by using the --nodename option
if needed.

When a --nodename is provided, we also check that we can resolve it with the
current DNS setup, and WARN the user when that's not the case. It might be
that we don't have enough information in our tests, so we continue with the
--nodename.
  • Loading branch information
DimCitus committed May 23, 2019
1 parent 91b7655 commit 82f7c5d
Show file tree
Hide file tree
Showing 22 changed files with 1,075 additions and 149 deletions.
79 changes: 70 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ Once the building and installation is done, follow those steps:
1. Install and start a pg_auto_failover monitor on your monitor machine:

~~~ bash
$ pg_autoctl create monitor --pgdata /path/to/pgdata \
--nodename `hostname --fqdn`
$ pg_autoctl create monitor --pgdata /path/to/pgdata
~~~

Once this command is done, you should have a running PostgreSQL
Expand All @@ -87,17 +86,33 @@ Once the building and installation is done, follow those steps:

You may change the port using `--pgport`.

The Postgres instance created will listen by default on all its network
interfaces, and the monitor nodename is determined automatically by
`pg_autoctl` by having a look at the network interfaces on the machine
and doing some reverse then forward DNS queries. You may force the
regitered nodename used with the `--nodename` option.

The command also creates a `autoctl` user and database, and a
`autoctl_node` user for the other nodes to use. In the `pg_auto_failover`
database, the extension `pgautofailover` is installed, and some *background
worker* jobs are active already, waiting until a PostgreSQL node gets
registered to run health-checks on it.

2. Install and start a primary PostgreSQL instance:
2. Get the Postgres URI (connection string) for the monitor node:

~~~ bash
$ pg_autoctl show uri
postgres://autoctl_node@host/pg_auto_failover
~~~

The following two steps are going to use the option `--monitor` which
expects that connection string. So copy/paste your actual Postgres URI
for the monitor in the next steps.

3. Install and start a primary PostgreSQL instance:

~~~ bash
$ pg_autoctl create postgres --pgdata /path/to/pgdata \
--nodename `hostname --fqdn` \
--monitor postgres://autoctl_node@host/pg_auto_failover
~~~

Expand All @@ -109,10 +124,37 @@ Once the building and installation is done, follow those steps:
and if not given as an command line option then the environment
variable `PGDATA` is used, when defined.

- `--nodename` is used by other nodes to connect to this one, so it
should be a hostname or an IP address that is reachable by the
- The nodename of this server is automatically discovered by
`pg_autoctl`, and used by the other nodes to then connect to the
newly created node: the monitor connects for running its
health-checks, and the secondary instance connects using the
replication protocol.

To determine your nodename `pg_autoctl` implements the following
three steps:

1. open a connection to the monitor and looks the TCP/IP client
address that has been used to make that connection.

2. Do a reverse DNS lookup on this IP address to fetch a
hostname for our local machine.

3. If the reverse DNS lookup is successfull , then `pg_autoctl`
does with a forward DNS lookup of that hostname.

When the forward DNS lookup repsonse in step 3. is an IP address
found in one of our local network interfaces, then `pg_autoctl`
uses the hostname found in step 2. as the default `--nodename`.
Otherwise it uses the IP address found in step 1.

You may use the `--nodename` command line option to bypass the
whole DNS lookup based process and force the local node name to a
fixed value.

The `--nodename` is used by other nodes to connect to this one, so
it should be a hostname or an IP address that is reachable by the
other members (localhost probably won't work).

The provided `--nodename` is going to be used by pg_auto_failover
to grant connection privileges in the Postgres HBA file. When using
a hostname rather than an IP address, please make sure that reverse
Expand Down Expand Up @@ -149,11 +191,10 @@ Once the building and installation is done, follow those steps:
~~~


3. Install and start a secondary PostgreSQL instance:
4. Install and start a secondary PostgreSQL instance:

~~~ bash
$ pg_autoctl create postgres --pgdata /path/to/pgdata \
--nodename `hostname -fqdn` \
--monitor postgres://autoctl_node@host/pg_auto_failover
~~~

Expand Down Expand Up @@ -191,6 +232,26 @@ is named *default* and the default group id is zero (0).
It's possible to add other services to the same running monitor by using
another formation.

## Application and Connection Strings

To retrieve the connection string to use at the application level, use the
following command:

~~~ bash
$ pg_autoctl show uri --formation default --pgdata ...
postgres://nodea:7020,nodeb:7010/citus?target_session_attrs=read-write
~~~

You can use that connection string from within your application, adjusting
the username that is used to connect. By default, pg_auto_failover edits the
Postgres HBA rules to allow the `--username` given at `pg_autoctl create
postgres` time to connect to this URI from the database node itself.

To allow application servers to connect to the Postgres database, edit your
`pg_hba.conf` file as documented in [the pg_hba.conf
file](https://www.postgresql.org/docs/current/auth-pg-hba-conf.html) chapter
of the PostgreSQL documentation.

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to
Expand Down
9 changes: 3 additions & 6 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. _postgres_quickstart:

High Availability Quick Start
=============================
pg_auto_failover Quick Start
============================

In this guide we’ll create a primary and secondary Postgres node and set
up pg_auto_failover to replicate data between them. We’ll simulate failure in
Expand Down Expand Up @@ -52,8 +52,7 @@ distinctive port (6000):
pg_autoctl create monitor \
--pgdata ./monitor \
--pgport 6000 \
--nodename `hostname --fqdn`
--pgport 6000
This command initializes a PostgreSQL cluster at the location pointed
by the ``--pgdata`` option. When ``--pgdata`` is omitted, ``pg_autoctl``
Expand Down Expand Up @@ -84,7 +83,6 @@ we’ll store the primary node’s data files in a small temporary filesystem.
pg_autoctl create postgres \
--pgdata /mnt/node_a/data \
--pgport 6010 \
--nodename 127.0.0.1 \
--pgctl /usr/pgsql-11/bin/pg_ctl \
--monitor postgres://autoctl_node@127.0.0.1:6000/pg_auto_failover
Expand Down Expand Up @@ -117,7 +115,6 @@ created the primary:
pg_autoctl create postgres \
--pgdata ./node_b \
--pgport 6011 \
--nodename 127.0.0.1 \
--pgctl /usr/pgsql-11/bin/pg_ctl \
--monitor postgres://autoctl_node@127.0.0.1:6000/pg_auto_failover
Expand Down
48 changes: 41 additions & 7 deletions docs/ref/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ used to find the Postgres connection URI string to use as the ``--monitor``
option to the ``pg_autoctl create`` command for the other nodes of the
formation.

.. _pg_autoctl_create_monitor:

pg_auto_failover Monitor
^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -77,9 +79,9 @@ commands are dealing with the monitor:

- ``pg_autoctl create monitor``

This command initializes a PostgreSQL cluster and installs the pg_auto_failover
extension so that it's possible to use the new instance to monitor
PostgreSQL services::
This command initializes a PostgreSQL cluster and installs the
`pgautofailover` extension so that it's possible to use the new
instance to monitor PostgreSQL services::

$ pg_autoctl create monitor --help
pg_autoctl create monitor: Initialize a pg_auto_failover monitor node
Expand All @@ -95,8 +97,28 @@ commands are dealing with the monitor:
``--pgctl`` option defaults to the first ``pg_ctl`` entry found in your
`PATH`.

The ``--nodename`` option is mandatory and must be set to the hostname
that the other nodes of the cluster will use to access to the monitor.
The ``--nodename`` option allows setting the hostname that the other
nodes of the cluster will use to access to the monitor. When not
provided, a default value is computed by running the following
algorithm:

1. Open a connection to the 8.8.8.8:53 public service and looks the
TCP/IP client address that has been used to make that connection.

2. Do a reverse DNS lookup on this IP address to fetch a hostname for
our local machine.

3. If the reverse DNS lookup is successfull , then `pg_autoctl` does
with a forward DNS lookup of that hostname.

When the forward DNS lookup repsonse in step 3. is an IP address found
in one of our local network interfaces, then `pg_autoctl` uses the
hostname found in step 2. as the default `--nodename`. Otherwise it
uses the IP address found in step 1.

You may use the `--nodename` command line option to bypass the whole
DNS lookup based process and force the local node name to a fixed
value.

- ``pg_autoctl run``

Expand Down Expand Up @@ -207,6 +229,8 @@ commands can be used, from any node in the setup.
For details about the options to the command, see above in the ``pg_autoctl
show events`` command.

.. _pg_autoctl_create_postgres:

pg_auto_failover Postgres Node Initialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -254,8 +278,8 @@ corresponding to as many implementation strategies.

This happens when ``--pgdata`` (or the environment variable ``PGDATA``)
points to an non-existing or empty directory. Then the given
``--nodename`` is registered to the pg_auto_failover ``--monitor`` as a member of
the ``--formation``.
``--nodename`` is registered to the pg_auto_failover ``--monitor`` as a
member of the ``--formation``.

The monitor answers to the registration call with a state to assign to
the new member of the group, either *SINGLE* or *WAIT_STANDBY*. When
Expand Down Expand Up @@ -293,6 +317,10 @@ Currently, ``pg_autoctl create`` doesn't know how to initialize from an already
running PostgreSQL standby node. In that situation, it is necessary to
prepare a new secondary system from scratch.

When `--nodename` is omitted, it is computed as above (see
:ref:`_pg_autoctl_create_monitor`), with the difference that step 1 uses the
monitor IP and port rather than the public service 8.8.8.8:53.

.. _pg_autoctl_configuration:

pg_autoctl configuration and state files
Expand Down Expand Up @@ -492,3 +520,9 @@ commands, only available in debug environments::
init Initialize the standby server using pg_basebackup
rewind Rewind a demoted primary server using pg_rewind
promote Promote a standby server to become writable

pg_autoctl do show
ipaddr Print this node's IP address information
cidr Print this node's CIDR information
lookup Print this node's DNS lookup information
nodename Print this node's default nodename
1 change: 1 addition & 0 deletions src/bin/pg_autoctl/cli_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "cli_common.h"
#include "commandline.h"
#include "ipaddr.h"
#include "keeper.h"
#include "keeper_config.h"
#include "log.h"
Expand Down

0 comments on commit 82f7c5d

Please sign in to comment.