From 885d226dac84e5d59032ba2095180ad03a6b7a0d Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Mon, 28 Sep 2020 11:05:07 +0200 Subject: [PATCH] Add support of raft bind_add and password (#1713) Close https://github.com/zalando/patroni/issues/1705 --- docs/ENVIRONMENT.rst | 4 +++- docs/SETTINGS.rst | 4 +++- patroni/config.py | 2 +- patroni/dcs/raft.py | 11 +++++++---- requirements.txt | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/ENVIRONMENT.rst b/docs/ENVIRONMENT.rst index 7b415e3f..7743fe16 100644 --- a/docs/ENVIRONMENT.rst +++ b/docs/ENVIRONMENT.rst @@ -109,9 +109,11 @@ Kubernetes Raft ---- -- **PATRONI\_RAFT\_SELF\_ADDR**: ``ip:port`` to listen on for Raft connections. If not set, the node will not participate in consensus. +- **PATRONI\_RAFT\_SELF\_ADDR**: ``ip:port`` to listen on for Raft connections. The ``self_addr`` must be accessible from other nodes of the cluster. If not set, the node will not participate in consensus. +- **PATRONI\_RAFT\_BIND\_ADDR**: (optional) ``ip:port`` to listen on for Raft connections. If not specified the ``self_addr`` will be used. - **PATRONI\_RAFT\_PARTNER\_ADDRS**: list of other Patroni nodes in the cluster in format ``"'ip1:port1','ip2:port2'"``. It is important to quote every single entity! - **PATRONI\_RAFT\_DATA\_DIR**: directory where to store Raft log and snapshot. If not specified the current working directory is used. +- **PATRONI\_RAFT\_PASSWORD**: (optional) Encrypt Raft traffic with a specified password, requires ``cryptography`` python module. PostgreSQL ---------- diff --git a/docs/SETTINGS.rst b/docs/SETTINGS.rst index 74175c23..26c91e49 100644 --- a/docs/SETTINGS.rst +++ b/docs/SETTINGS.rst @@ -183,9 +183,11 @@ Kubernetes Raft ---- -- **self\_addr**: ``ip:port`` to listen on for Raft connections. If not set, the node will not participate in consensus. +- **self\_addr**: ``ip:port`` to listen on for Raft connections. The ``self_addr`` must be accessible from other nodes of the cluster. If not set, the node will not participate in consensus. +- **bind\_addr**: (optional) ``ip:port`` to listen on for Raft connections. If not specified the ``self_addr`` will be used. - **partner\_addrs**: list of other Patroni nodes in the cluster in format: ['ip1:port', 'ip2:port', 'etc...'] - **data\_dir**: directory where to store Raft log and snapshot. If not specified the current working directory is used. +- **password**: (optional) Encrypt Raft traffic with a specified password, requires ``cryptography`` python module. Short FAQ about Raft implementation diff --git a/patroni/config.py b/patroni/config.py index aea866ef..456692f4 100644 --- a/patroni/config.py +++ b/patroni/config.py @@ -316,7 +316,7 @@ class Config(object): logger.exception('Exception when parsing list %s', value) return None - _set_section_values('raft', ['data_dir', 'self_addr', 'partner_addrs']) + _set_section_values('raft', ['data_dir', 'self_addr', 'partner_addrs', 'password', 'bind_addr']) if 'raft' in ret and 'partner_addrs' in ret['raft']: ret['raft']['partner_addrs'] = _parse_list(ret['raft']['partner_addrs']) diff --git a/patroni/dcs/raft.py b/patroni/dcs/raft.py index 97ddb3d4..3a9dab2a 100644 --- a/patroni/dcs/raft.py +++ b/patroni/dcs/raft.py @@ -274,12 +274,15 @@ class Raft(AbstractDCS): if self_addr: partner_addrs.append(self_addr) self_addr = None - template = os.path.join(config.get('data_dir', ''), self_addr or '') - files = {'journalFile': template + '.journal', 'fullDumpFile': template + '.dump'} if self_addr else {} ready_event = threading.Event() - conf = SyncObjConf(commandsWaitLeader=False, appendEntriesUseBatch=False, onReady=ready_event.set, - dynamicMembershipChange=True, **files) + file_template = os.path.join(config.get('data_dir', ''), (self_addr or '')) + conf = SyncObjConf(password=config.get('password'), appendEntriesUseBatch=False, + bindAddress=config.get('bind_addr'), commandsWaitLeader=False, + fullDumpFile=(file_template + '.dump' if self_addr else None), + journalFile=(file_template + '.journal' if self_addr else None), + onReady=ready_event.set, dynamicMembershipChange=True) + self._sync_obj = KVStoreTTL(self_addr, partner_addrs, conf, self._on_set, self._on_delete) while True: ready_event.wait(5) diff --git a/requirements.txt b/requirements.txt index 8e568c9f..098616bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,6 @@ python-consul>=0.7.1 click>=4.1 prettytable>=0.7 python-dateutil -pysyncobj>=0.3.5 +pysyncobj>=0.3.7 psutil>=2.0.0 ydiff>=1.2.0