active_postgres 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +87 -5
- data/lib/active_postgres/components/core.rb +2 -7
- data/lib/active_postgres/components/extensions.rb +40 -35
- data/lib/active_postgres/components/monitoring.rb +91 -4
- data/lib/active_postgres/components/pgbackrest.rb +38 -2
- data/lib/active_postgres/components/pgbouncer.rb +43 -4
- data/lib/active_postgres/components/repmgr.rb +431 -62
- data/lib/active_postgres/configuration.rb +59 -2
- data/lib/active_postgres/connection_pooler.rb +3 -12
- data/lib/active_postgres/credentials.rb +3 -3
- data/lib/active_postgres/direct_executor.rb +91 -0
- data/lib/active_postgres/generators/active_postgres/install_generator.rb +1 -0
- data/lib/active_postgres/generators/active_postgres/templates/postgres.yml.erb +18 -1
- data/lib/active_postgres/health_checker.rb +24 -17
- data/lib/active_postgres/rollback_manager.rb +4 -8
- data/lib/active_postgres/secrets.rb +23 -5
- data/lib/active_postgres/ssh_executor.rb +36 -14
- data/lib/active_postgres/version.rb +1 -1
- data/lib/active_postgres.rb +1 -0
- data/lib/tasks/postgres.rake +10 -4
- data/lib/tasks/rotate_credentials.rake +4 -16
- data/templates/pg_hba.conf.erb +4 -1
- data/templates/pgbackrest.conf.erb +28 -0
- data/templates/pgbouncer-follow-primary.service.erb +8 -0
- data/templates/pgbouncer-follow-primary.timer.erb +11 -0
- data/templates/pgbouncer.ini.erb +2 -0
- data/templates/pgbouncer_follow_primary.sh.erb +34 -0
- data/templates/postgresql.conf.erb +4 -0
- data/templates/repmgr.conf.erb +7 -3
- data/templates/repmgr_dns_failover.sh.erb +49 -0
- metadata +7 -2
|
@@ -16,6 +16,21 @@ repo1-s3-endpoint=s3.<%= pgbackrest_config[:s3_region] || 'us-east-1' %>.amazona
|
|
|
16
16
|
repo1-s3-key=<%= secrets_obj.resolve('s3_access_key') %>
|
|
17
17
|
repo1-s3-key-secret=<%= secrets_obj.resolve('s3_secret_key') %>
|
|
18
18
|
<% end %>
|
|
19
|
+
<% elsif pgbackrest_config[:repo_type] == 'gcs' %>
|
|
20
|
+
repo1-type=gcs
|
|
21
|
+
repo1-path=<%= pgbackrest_config[:repo_path] || '/backups' %>
|
|
22
|
+
repo1-gcs-bucket=<%= pgbackrest_config[:gcs_bucket] %>
|
|
23
|
+
<% if secrets_obj.resolve('gcs_key_file') %>
|
|
24
|
+
repo1-gcs-key=<%= secrets_obj.resolve('gcs_key_file') %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<% elsif pgbackrest_config[:repo_type] == 'azure' %>
|
|
27
|
+
repo1-type=azure
|
|
28
|
+
repo1-path=<%= pgbackrest_config[:repo_path] || '/backups' %>
|
|
29
|
+
repo1-azure-container=<%= pgbackrest_config[:azure_container] %>
|
|
30
|
+
<% if secrets_obj.resolve('azure_account') %>
|
|
31
|
+
repo1-azure-account=<%= secrets_obj.resolve('azure_account') %>
|
|
32
|
+
repo1-azure-key=<%= secrets_obj.resolve('azure_key') %>
|
|
33
|
+
<% end %>
|
|
19
34
|
<% else %>
|
|
20
35
|
# Local storage
|
|
21
36
|
repo1-path=<%= pgbackrest_config[:repo_path] || '/var/lib/pgbackrest' %>
|
|
@@ -35,9 +50,22 @@ repo1-cipher-type=aes-256-cbc
|
|
|
35
50
|
repo1-cipher-pass=<%= secrets_obj.resolve('backup_encryption_key') %>
|
|
36
51
|
<% end %>
|
|
37
52
|
|
|
53
|
+
# Logging
|
|
54
|
+
log-level-console=info
|
|
55
|
+
log-level-file=detail
|
|
56
|
+
log-path=/var/log/pgbackrest
|
|
57
|
+
|
|
58
|
+
# Process settings
|
|
59
|
+
process-max=<%= pgbackrest_config[:process_max] || 2 %>
|
|
60
|
+
|
|
61
|
+
# Start/Stop (for consistent backups)
|
|
62
|
+
start-fast=y
|
|
63
|
+
stop-auto=y
|
|
64
|
+
|
|
38
65
|
[main]
|
|
39
66
|
pg1-path=/var/lib/postgresql/<%= config.version %>/main
|
|
40
67
|
pg1-port=5432
|
|
41
68
|
pg1-socket-path=/var/run/postgresql
|
|
69
|
+
pg1-user=<%= config.postgres_user %>
|
|
42
70
|
|
|
43
71
|
|
data/templates/pgbouncer.ini.erb
CHANGED
|
@@ -49,8 +49,10 @@ log_pooler_errors = <%= pgbouncer_config[:log_pooler_errors] || 1 %>
|
|
|
49
49
|
client_tls_sslmode = require
|
|
50
50
|
client_tls_key_file = /etc/pgbouncer/server.key
|
|
51
51
|
client_tls_cert_file = /etc/pgbouncer/server.crt
|
|
52
|
+
<% if has_ca_cert %>
|
|
52
53
|
client_tls_ca_file = /etc/pgbouncer/ca.crt
|
|
53
54
|
<% end %>
|
|
55
|
+
<% end %>
|
|
54
56
|
|
|
55
57
|
# Process management
|
|
56
58
|
<% if pgbouncer_config[:pidfile] %>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPMGR_CONF="<%= repmgr_conf %>"
|
|
5
|
+
PGBOUNCER_INI="/etc/pgbouncer/pgbouncer.ini"
|
|
6
|
+
PGBOUNCER_SERVICE="pgbouncer"
|
|
7
|
+
LOG_TAG="pgbouncer-follow-primary"
|
|
8
|
+
|
|
9
|
+
cluster_csv=$(/usr/bin/sudo -u <%= postgres_user %> env HOME=/var/lib/postgresql \
|
|
10
|
+
repmgr -f "$REPMGR_CONF" cluster show --csv 2>/dev/null || true)
|
|
11
|
+
if [[ -z "$cluster_csv" ]]; then
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
primary_conninfo=$(printf "%s\n" "$cluster_csv" | awk -F',' 'NR>1 && tolower($3) ~ /primary/ {print $NF; exit}')
|
|
16
|
+
if [[ -z "$primary_conninfo" ]]; then
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
primary_host=$(printf "%s" "$primary_conninfo" | sed -n 's/.*host=\\([^ ]*\\).*/\\1/p')
|
|
21
|
+
if [[ -z "$primary_host" ]]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
current_host=$(awk -F'host=' '/^\\* = host=/{print $2}' "$PGBOUNCER_INI" | awk '{print $1}')
|
|
26
|
+
if [[ -z "$current_host" ]]; then
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [[ "$current_host" != "$primary_host" ]]; then
|
|
31
|
+
/usr/bin/sed -i -E "s/^(\\* = host=)[^ ]+/\\1${primary_host}/" "$PGBOUNCER_INI"
|
|
32
|
+
/usr/bin/systemctl reload "$PGBOUNCER_SERVICE"
|
|
33
|
+
/usr/bin/logger -t "$LOG_TAG" "Updated PgBouncer primary target to ${primary_host}"
|
|
34
|
+
fi
|
|
@@ -44,9 +44,13 @@ wal_compression = <%= pg_config[:wal_compression] %>
|
|
|
44
44
|
<% end %>
|
|
45
45
|
<% if pg_config[:archive_mode] %>
|
|
46
46
|
archive_mode = <%= pg_config[:archive_mode] %>
|
|
47
|
+
<% elsif config.component_enabled?(:pgbackrest) %>
|
|
48
|
+
archive_mode = on
|
|
47
49
|
<% end %>
|
|
48
50
|
<% if pg_config[:archive_command] %>
|
|
49
51
|
archive_command = '<%= pg_config[:archive_command] %>'
|
|
52
|
+
<% elsif config.component_enabled?(:pgbackrest) %>
|
|
53
|
+
archive_command = 'pgbackrest --stanza=main archive-push %p'
|
|
50
54
|
<% end %>
|
|
51
55
|
<% if pg_config[:shared_memory_type] %>
|
|
52
56
|
shared_memory_type = <%= pg_config[:shared_memory_type] %>
|
data/templates/repmgr.conf.erb
CHANGED
|
@@ -15,14 +15,14 @@ node_name='<%= node_label %>'
|
|
|
15
15
|
# conninfo describes how OTHER nodes connect to THIS node
|
|
16
16
|
repmgr_host = config.replication_host_for(host)
|
|
17
17
|
%>
|
|
18
|
-
conninfo='host=<%= repmgr_host %> user=<%= config.repmgr_user %> dbname=<%= config.repmgr_database %>
|
|
18
|
+
conninfo='host=<%= repmgr_host %> user=<%= config.repmgr_user %> dbname=<%= config.repmgr_database %> connect_timeout=2'
|
|
19
19
|
data_directory='/var/lib/postgresql/<%= config.version %>/main'
|
|
20
20
|
|
|
21
21
|
<% if host == config.primary_host %>
|
|
22
|
-
failover
|
|
22
|
+
failover=<%= repmgr_config[:auto_failover] == false ? 'manual' : 'automatic' %>
|
|
23
23
|
priority=<%= repmgr_config[:priority] || 100 %>
|
|
24
24
|
<% else %>
|
|
25
|
-
failover
|
|
25
|
+
failover=<%= repmgr_config[:auto_failover] == false ? 'manual' : 'automatic' %>
|
|
26
26
|
priority=<%= repmgr_config[:priority] || 100 %>
|
|
27
27
|
promote_command='repmgr standby promote -f /etc/repmgr.conf'
|
|
28
28
|
follow_command='repmgr standby follow -f /etc/repmgr.conf --upstream-node-id=%n'
|
|
@@ -38,3 +38,7 @@ log_file='/var/log/postgresql/repmgr.log'
|
|
|
38
38
|
monitoring_history=yes
|
|
39
39
|
monitor_interval_secs=5
|
|
40
40
|
|
|
41
|
+
<% if repmgr_config[:dns_failover] && repmgr_config[:dns_failover][:enabled] %>
|
|
42
|
+
event_notification_command='/usr/local/bin/active-postgres-dns-failover'
|
|
43
|
+
event_notifications='<%= repmgr_config[:dns_failover][:events] || 'repmgrd_failover_promote,standby_promote,standby_switchover,standby_follow' %>'
|
|
44
|
+
<% end %>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPMGR_CONF="/etc/repmgr.conf"
|
|
5
|
+
DNS_USER="<%= dns_user %>"
|
|
6
|
+
DNS_SERVERS=(<%= dns_servers.map(&:to_s).join(' ') %>)
|
|
7
|
+
DNS_SSH_KEY="<%= dns_ssh_key_path %>"
|
|
8
|
+
DNSMASQ_FILE="/etc/dnsmasq.d/active_postgres.conf"
|
|
9
|
+
PRIMARY_RECORD="<%= primary_record %>"
|
|
10
|
+
REPLICA_RECORD="<%= replica_record %>"
|
|
11
|
+
SSH_STRICT_HOST_KEY="<%= ssh_strict_host_key %>"
|
|
12
|
+
SSH_KNOWN_HOSTS="/var/lib/postgresql/.ssh/known_hosts"
|
|
13
|
+
LOG_TAG="active_postgres_dns"
|
|
14
|
+
|
|
15
|
+
cluster_csv=$(repmgr -f "$REPMGR_CONF" cluster show --csv 2>/dev/null || true)
|
|
16
|
+
if [[ -z "$cluster_csv" ]]; then
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
primary_host=$(printf "%s\n" "$cluster_csv" | awk -F',' 'NR>1 && tolower($3) ~ /primary/ {print $NF; exit}' | sed -n 's/.*host=\\([^ ]*\\).*/\\1/p')
|
|
21
|
+
standby_hosts=$(printf "%s\n" "$cluster_csv" | awk -F',' 'NR>1 && tolower($3) ~ /standby/ {print $NF}' | sed -n 's/.*host=\\([^ ]*\\).*/\\1/p' | sort -u)
|
|
22
|
+
|
|
23
|
+
if [[ -z "$primary_host" ]]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
content=$'# Managed by active_postgres\n'
|
|
28
|
+
printf -v content '%saddress=/%s/%s\n' "$content" "$PRIMARY_RECORD" "$primary_host"
|
|
29
|
+
|
|
30
|
+
if [[ -n "$standby_hosts" ]]; then
|
|
31
|
+
for host in $standby_hosts; do
|
|
32
|
+
printf -v content '%saddress=/%s/%s\n' "$content" "$REPLICA_RECORD" "$host"
|
|
33
|
+
done
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
ssh_opts=(-i "$DNS_SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking="$SSH_STRICT_HOST_KEY" -o UserKnownHostsFile="$SSH_KNOWN_HOSTS")
|
|
37
|
+
|
|
38
|
+
for server in "${DNS_SERVERS[@]}"; do
|
|
39
|
+
if [[ -z "$server" ]]; then
|
|
40
|
+
continue
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if ! /usr/bin/ssh "${ssh_opts[@]}" "${DNS_USER}@${server}" \
|
|
44
|
+
"sudo bash -c 'cat > ${DNSMASQ_FILE} << \"EOF\"\\n${content}EOF\\n' && (sudo systemctl reload dnsmasq || sudo systemctl restart dnsmasq)"; then
|
|
45
|
+
/usr/bin/logger -t "$LOG_TAG" "Failed updating dnsmasq on ${server}"
|
|
46
|
+
fi
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
/usr/bin/logger -t "$LOG_TAG" "Updated DNS records for ${PRIMARY_RECORD} and ${REPLICA_RECORD} (primary=${primary_host})"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_postgres
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BoringCache
|
|
@@ -169,6 +169,7 @@ files:
|
|
|
169
169
|
- lib/active_postgres/connection_pooler.rb
|
|
170
170
|
- lib/active_postgres/credentials.rb
|
|
171
171
|
- lib/active_postgres/deployment_flow.rb
|
|
172
|
+
- lib/active_postgres/direct_executor.rb
|
|
172
173
|
- lib/active_postgres/error_handler.rb
|
|
173
174
|
- lib/active_postgres/failover.rb
|
|
174
175
|
- lib/active_postgres/generators/active_postgres/install_generator.rb
|
|
@@ -194,9 +195,13 @@ files:
|
|
|
194
195
|
- lib/tasks/rotate_credentials.rake
|
|
195
196
|
- templates/pg_hba.conf.erb
|
|
196
197
|
- templates/pgbackrest.conf.erb
|
|
198
|
+
- templates/pgbouncer-follow-primary.service.erb
|
|
199
|
+
- templates/pgbouncer-follow-primary.timer.erb
|
|
197
200
|
- templates/pgbouncer.ini.erb
|
|
201
|
+
- templates/pgbouncer_follow_primary.sh.erb
|
|
198
202
|
- templates/postgresql.conf.erb
|
|
199
203
|
- templates/repmgr.conf.erb
|
|
204
|
+
- templates/repmgr_dns_failover.sh.erb
|
|
200
205
|
homepage: https://github.com/boringcache/active_postgres
|
|
201
206
|
licenses:
|
|
202
207
|
- MIT
|
|
@@ -220,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
220
225
|
- !ruby/object:Gem::Version
|
|
221
226
|
version: '0'
|
|
222
227
|
requirements: []
|
|
223
|
-
rubygems_version: 3.
|
|
228
|
+
rubygems_version: 3.6.9
|
|
224
229
|
specification_version: 4
|
|
225
230
|
summary: PostgreSQL High Availability for Rails, made simple
|
|
226
231
|
test_files: []
|