patroni --generate-config hba rules
What happened?
While converting an existing PG instance to patroni, the generate config writes HBA rules under the top-level postgresql key. The patroni configuration manual page states that the local configuration file has precedence over configuration stored in DCS.
As a result, any subsequent calls of patronictl edit-config correctly modify hba entries in DCS, while the configuration file (used the default, otherwise patronni will not manage pg_hba configuration as per the manual) is kept untouched, because it matches the local configuration file.
Therefore, following the conversion manual instructions using generate-config ends up in a setup that does not allow editing pg_hba.conf file using patronictl/REST API.
How can we reproduce it (as minimally and precisely as possible)?
Install Patroni on a host where a PostgreSQL cluster is running and issue:
PATRONI_POSTGRESQL_BIN_DIR=/usr/pgsql-16/bin/
patroni --generate-configAdjust the variable PATRONI_POSTGRESQL_BIN_DIR based on your installation.
What did you expect to happen?
For converting an existing PG isntance to Patroni, I'd expect
pg_hba key to be placed under bootstrap.dcs.postgresql key. That way, it'll be imported to DCS, and subsequent HBA changes in DCS will be reflected on the patroni nodes.
This is based on the expectation that an existing PG instance is being converted to "patroni-managed" with the aim of managing the PostgreSQL instance by patroni (ctl / REST API), therefore, placing HBA configuration in the local yaml configuration file by the generate-config command persists the state, and the central management in DCS does not apply its changes (change requires editing local yaml and reloading patroni).
At the end of the existing instance conversion, I'd expect (hopefully correctly) that the instance will be fully managed by patronictl/RESTAPI.
Patroni/PostgreSQL/DCS version
- Patroni version: 4.0.6
- PostgreSQL version: 16.6
- DCS (and its version): 3.6.1
- OS: AlmaLinux 9
Patroni configuration file
# not yet exists while converting the existing instancepatronictl show-config
# not yet exists while converting the existing instance
# added --generate-config output instead
scope: test_cluster_01
name: pgsql-patroni-node-2
log:
format: '%(asctime)s %(levelname)s: %(message)s'
level: INFO
max_queue_size: 1000
traceback_level: ERROR
type: plain
restapi:
connect_address: 10.36.0.202:8008
listen: 10.36.0.202:8008
# The bootstrap configuration. Works only when the cluster is not yet initialized.
# If the cluster is already initialized, all changes in the `bootstrap` section are ignored!
bootstrap:
# This section will be written into <dcs>:/<namespace>/<scope>/config after initializing
# new cluster and all other cluster members will use it as a `global configuration`.
# WARNING! If you want to change any of the parameters that were set up
# via `bootstrap.dcs` section, please use `patronictl edit-config`!
dcs:
loop_wait: 10
retry_timeout: 10
ttl: 30
postgresql:
parameters:
DateStyle: ISO, MDY
TimeZone: Europe/Prague
archive_mode: 'on'
archive_timeout: 15min
autovacuum: 'on'
autovacuum_analyze_scale_factor: '0.05'
autovacuum_naptime: 10s
autovacuum_vacuum_cost_limit: '5000'
autovacuum_vacuum_scale_factor: '0.05'
bgwriter_delay: 100ms
bgwriter_lru_maxpages: '300'
checkpoint_completion_target: '0.9'
checkpoint_timeout: 30min
client_connection_check_interval: 10s
cron.database_name: bench
default_statistics_target: '2500'
default_text_search_config: pg_catalog.english
dynamic_shared_memory_type: posix
effective_cache_size: 4GB
effective_io_concurrency: '100'
full_page_writes: 'on'
hot_standby: 'on'
hot_standby_feedback: 'on'
huge_pages: 'on'
icu_validation_level: error
idle_in_transaction_session_timeout: 5min
jit: 'off'
jit_provider: llvmjit
lc_messages: en_US.UTF-8
lc_monetary: en_US.UTF-8
lc_numeric: en_US.UTF-8
lc_time: en_US.UTF-8
log_autovacuum_min_duration: '0'
log_checkpoints: 'on'
log_connections: 'on'
log_destination: stderr, jsonlog
log_directory: log
log_disconnections: 'on'
log_filename: postgresql.log
log_line_prefix: '%m, [%p], [%P], [%c], [%l], [%s], [%b], [%x], %q[%d], [%u],
[%r], [%a], [%Q], [%i], '
log_lock_waits: 'on'
log_min_duration_sample: 1ms
log_min_duration_statement: 500ms
log_min_error_statement: warning
log_recovery_conflict_waits: 'on'
log_rotation_age: '0'
log_rotation_size: '0'
log_statement: ddl
log_statement_sample_rate: '0.001'
log_temp_files: '0'
log_timezone: Europe/Prague
log_transaction_sample_rate: '0.001'
log_truncate_on_rotation: 'off'
logging_collector: 'on'
maintenance_work_mem: 64MB
max_connections: '500'
max_locks_per_transaction: '64'
max_logical_replication_workers: '12'
max_prepared_transactions: '0'
max_replication_slots: '25'
max_stack_depth: 4MB
max_wal_senders: '30'
max_wal_size: 1GB
max_worker_processes: '32'
min_wal_size: 1GB
old_snapshot_threshold: 8h
password_encryption: md5
pg_stat_kcache.track: all
pg_stat_kcache.track_planning: 'on'
pg_stat_statements.max: '10000'
pg_stat_statements.track: all
pg_wait_sampling.profile_pid: 'off'
primary_conninfo: dbname=postgres user=app_patroni_replication host=10.36.0.201
port=5432 sslmode=prefer application_name=pgsql-patroni-node-2 gssencmode=prefer
channel_binding=prefer
primary_slot_name: pgsql_patroni_node_2
random_page_cost: '1'
reserved_connections: '20'
shared_buffers: 1GB
shared_preload_libraries: pg_stat_statements, pg_stat_kcache, pg_qualstats, pg_cron,
pg_partman_bgw, pg_wait_sampling, plpgsql_check
tcp_keepalives_count: '0'
tcp_keepalives_idle: '0'
tcp_keepalives_interval: '0'
temp_buffers: 16MB
track_activities: 'on'
track_activity_query_size: 4kB
track_commit_timestamp: 'on'
track_counts: 'on'
track_functions: all
track_io_timing: 'on'
track_wal_io_timing: 'on'
unix_socket_directories: /run/postgresql, /tmp
vacuum_buffer_usage_limit: 512MB
wal_decode_buffer_size: 256MB
wal_keep_size: 2GB
wal_level: logical
wal_log_hints: 'on'
wal_receiver_timeout: 15min
wal_sender_timeout: 15min
work_mem: 4MB
use_slots: true
postgresql:
authentication:
replication:
password: '#FIXME'
username: '#FIXME'
superuser:
password: ''
username: postgres
bin_dir: /usr/pgsql-16/bin
connect_address: 10.36.0.202:5432
data_dir: /pgsql/cluster/16/data
listen: '*:5432'
parameters:
archive_command: pgbackrest --stanza=uat_patroni_test archive-push "%p"
config_file: /pgsql/cluster/16/data/postgresql.conf
hba_file: /pgsql/cluster/16/data/pg_hba.conf
ident_file: /pgsql/cluster/16/data/pg_ident.conf
restore_command: pgbackrest --stanza=uat_patroni_test archive-get %f "%p"
pg_hba:
- local all all peer
- host all all 127.0.0.1/32 md5
- host all all ::1/128 md5
- host replication app_patroni_replication 10.36.0.0/15 md5
- 'local replication all peer #
pg_basebackup stream mode using socket'
- 'host replication all 127.0.0.1/32 md5 #
postgres user without password won''t be able to connect to localhost (even for
basebackup)'
- 'host replication all ::1/128 md5 #
same as above'
- 'host all +legacy_users samenet md5 # Allow
connections from any address in any subnet that the server is directly connected
to.'
- host all all 0.0.0.0/0 reject
- host all all ::0/0 reject
pg_ident:
- testmap1 root postgres
tags:
clonefrom: true
failover_priority: 1
noloadbalance: false
nostream: false
nosync: falsePatroni log files
# not yet exists while converting the existing instancePostgreSQL log files
No errorsHave you tried to use GitHub issue search?
- Yes
Anything else we need to know?
Removing the postgresql.pg_hba key from the local configuration file makes patronictl edit-config work as expected, even for HBA file entries.
Might it be that all the postgresql.parameters shall be under the bootstrap.dcs key, but I do not have enough knowledge/context to suggest such a change globally for the generate-config command.
Out of curiosity, is the fact that the generate-config command also creates
postgresql.parameters.hba_file, but as it matches the default location in my test case, it does not prevent Patroni from properly managing HBA file entries.
Source: patroni/patroni