feat: 纳管共享 etcd 与 k3s 外 PostgreSQL 高可用及备份
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Shared PostgreSQL primary-aware full backup
|
||||
After=network-online.target
|
||||
RequiresMountsFor={{ pg_repo_path }}
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=pgbackup
|
||||
Group=pgbackup
|
||||
ExecStart=/usr/bin/pgbackrest --config=/etc/homelab-pgbackrest/repository.conf --stanza=prod --type=full backup
|
||||
TimeoutStartSec=2h
|
||||
UMask=0077
|
||||
Nice=10
|
||||
IOSchedulingClass=best-effort
|
||||
IOSchedulingPriority=7
|
||||
@@ -0,0 +1,8 @@
|
||||
[Unit]
|
||||
Description=Daily shared PostgreSQL full backup
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 03:40:00 UTC
|
||||
RandomizedDelaySec=10min
|
||||
Persistent=true
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -0,0 +1,19 @@
|
||||
# 参考 Pigsty v4.5.0 的 Patroni 角色检查与旧连接摘除行为。
|
||||
global
|
||||
maxconn 256
|
||||
log stdout format raw local0
|
||||
stats socket /tmp/homelab-pg-haproxy.sock mode 600 level admin
|
||||
defaults
|
||||
mode tcp
|
||||
timeout connect 3s
|
||||
timeout client 1h
|
||||
timeout server 1h
|
||||
timeout check 3s
|
||||
listen pg-prod
|
||||
bind {{ pg_proxy_bind }}
|
||||
option httpchk GET /primary
|
||||
http-check expect status 200
|
||||
default-server inter 2s fall 3 rise 2 on-marked-down shutdown-sessions
|
||||
{% for member in pg_proxy_members %}
|
||||
server {{ member.name }} {{ member.address }}:{{ member.port }} check port {{ member.api_port }}
|
||||
{% endfor %}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
[Unit]
|
||||
Description=Homelab PostgreSQL {{ pg_instance }}{{ ' through Patroni' if pg_instance == 'prod' else '' }}
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
RequiresMountsFor={{ pg_parent_dir }}
|
||||
[Service]
|
||||
User={{ pg_profile.user }}
|
||||
Group={{ pg_profile.user }}
|
||||
UMask=0077
|
||||
RuntimeDirectory=homelab-postgresql-{{ pg_instance }}
|
||||
RuntimeDirectoryMode=0700
|
||||
{% if pg_instance == 'prod' %}
|
||||
Type=simple
|
||||
ExecStart={{ pg_patroni_bin }} {{ pg_config_dir }}/patroni.yml
|
||||
KillMode=process
|
||||
{% else %}
|
||||
Type=simple
|
||||
ExecStart={{ pg_bin_dir }}/postgres -D {{ pg_data_dir }} -c config_file={{ pg_config_dir }}/postgresql.conf
|
||||
KillSignal=SIGINT
|
||||
{% endif %}
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=120
|
||||
MemoryHigh={{ pg_profile.memory_high }}
|
||||
MemoryMax={{ pg_profile.memory_max }}
|
||||
OOMPolicy=stop
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
ReadWritePaths={{ pg_parent_dir }} {{ pg_config_dir }} {{ pg_socket_dir }}
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,99 @@
|
||||
# 实例化部署;不引用 Pigsty 的全局 /pg 或宿主内存自动调优。
|
||||
name: {{ pg_member | to_json }}
|
||||
namespace: /homelab/patroni/
|
||||
scope: pg-prod
|
||||
restapi:
|
||||
listen: {{ pg_address }}:{{ pg_profile.api_port }}
|
||||
connect_address: {{ pg_address }}:{{ pg_profile.api_port }}
|
||||
authentication:
|
||||
username: patroni
|
||||
password: {{ pg_credentials.rest_password | to_json }}
|
||||
etcd3:
|
||||
hosts: {{ pg_etcd_endpoints | to_json }}
|
||||
protocol: https
|
||||
username: {{ pg_etcd_credentials.username | to_json }}
|
||||
password: {{ pg_etcd_credentials.password | to_json }}
|
||||
cacert: {{ pg_config_dir }}/ca.crt
|
||||
cert: {{ pg_config_dir }}/etcd.crt
|
||||
key: {{ pg_config_dir }}/etcd.key
|
||||
bootstrap:
|
||||
dcs:
|
||||
ttl: 30
|
||||
loop_wait: 10
|
||||
retry_timeout: 10
|
||||
maximum_lag_on_failover: 1048576
|
||||
check_timeline: true
|
||||
synchronous_mode: false
|
||||
failsafe_mode: false
|
||||
postgresql:
|
||||
use_pg_rewind: true
|
||||
use_slots: true
|
||||
parameters:
|
||||
max_connections: {{ pg_profile.max_connections }}
|
||||
wal_level: replica
|
||||
hot_standby: 'on'
|
||||
wal_log_hints: 'on'
|
||||
max_wal_senders: 5
|
||||
max_replication_slots: 5
|
||||
max_slot_wal_keep_size: 2GB
|
||||
max_wal_size: 1GB
|
||||
min_wal_size: 80MB
|
||||
archive_mode: 'on'
|
||||
archive_timeout: 300s
|
||||
archive_command: "pgbackrest --config={{ pg_config_dir }}/pgbackrest.conf --stanza=prod archive-push %p"
|
||||
initdb:
|
||||
- encoding: UTF8
|
||||
- locale: C.UTF-8
|
||||
- data-checksums
|
||||
postgresql:
|
||||
listen: {{ pg_address }}:{{ pg_profile.port }}
|
||||
connect_address: {{ pg_address }}:{{ pg_profile.port }}
|
||||
data_dir: {{ pg_data_dir }}
|
||||
bin_dir: {{ pg_bin_dir }}
|
||||
pgpass: {{ pg_parent_dir }}/pgpass
|
||||
use_unix_socket: true
|
||||
use_unix_socket_repl: true
|
||||
authentication:
|
||||
superuser:
|
||||
username: {{ pg_profile.user }}
|
||||
password: {{ pg_credentials.superuser_password | to_json }}
|
||||
replication:
|
||||
username: replicator
|
||||
password: {{ pg_credentials.replication_password | to_json }}
|
||||
sslmode: verify-full
|
||||
sslrootcert: {{ pg_config_dir }}/ca.crt
|
||||
parameters:
|
||||
unix_socket_directories: {{ pg_socket_dir }}
|
||||
unix_socket_permissions: '0700'
|
||||
password_encryption: scram-sha-256
|
||||
shared_buffers: {{ pg_profile.shared_buffers }}
|
||||
work_mem: 4MB
|
||||
maintenance_work_mem: 64MB
|
||||
ssl: 'on'
|
||||
ssl_cert_file: {{ pg_config_dir }}/server.crt
|
||||
ssl_key_file: {{ pg_config_dir }}/server.key
|
||||
ssl_ca_file: {{ pg_config_dir }}/ca.crt
|
||||
log_statement: none
|
||||
log_min_error_statement: panic
|
||||
pg_hba:
|
||||
- local all {{ pg_profile.user }} peer
|
||||
- local replication {{ pg_profile.user }} peer
|
||||
- local replication replicator scram-sha-256
|
||||
{% for address in pg_replication_addresses %}
|
||||
- hostssl replication replicator {{ address }} scram-sha-256
|
||||
- hostssl all {{ pg_profile.user }} {{ address }} scram-sha-256
|
||||
{% endfor %}
|
||||
{% for cidr in pg_client_cidrs %}
|
||||
- hostssl all all {{ cidr }} scram-sha-256
|
||||
{% endfor %}
|
||||
- host all all 0.0.0.0/0 reject
|
||||
- host all all ::/0 reject
|
||||
remove_data_directory_on_rewind_failure: false
|
||||
remove_data_directory_on_diverged_timelines: false
|
||||
watchdog:
|
||||
mode: 'off'
|
||||
tags:
|
||||
nofailover: false
|
||||
noloadbalance: false
|
||||
clonefrom: false
|
||||
nosync: false
|
||||
@@ -0,0 +1,6 @@
|
||||
local all {{ pg_profile.user }} peer
|
||||
{% for cidr in pg_client_cidrs %}
|
||||
hostssl all all {{ cidr }} scram-sha-256
|
||||
{% endfor %}
|
||||
host all all 0.0.0.0/0 reject
|
||||
host all all ::/0 reject
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
[global]
|
||||
{% if pg_repo_remote | default(true) %}
|
||||
repo1-host={{ pg_repo_host }}
|
||||
repo1-host-user={{ pg_repo_user }}
|
||||
repo1-host-config=/etc/homelab-pgbackrest/repository.conf
|
||||
{% endif %}
|
||||
repo1-path={{ pg_repo_path }}
|
||||
repo1-retention-full=3
|
||||
process-max=1
|
||||
compress-type=zst
|
||||
compress-level=3
|
||||
start-fast=y
|
||||
log-level-console=warn
|
||||
log-level-file=off
|
||||
lock-path={{ pg_parent_dir }}/backup-lock
|
||||
spool-path={{ pg_parent_dir }}/backup-spool
|
||||
# 不设置 archive-push-queue-max;超限丢弃 WAL 会破坏恢复链。
|
||||
[prod]
|
||||
pg1-path={{ pg_data_dir }}
|
||||
pg1-port={{ pg_profile.port }}
|
||||
pg1-socket-path={{ pg_socket_dir }}
|
||||
pg1-user={{ pg_profile.user }}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
listen_addresses = '{{ pg_address }}'
|
||||
port = {{ pg_profile.port }}
|
||||
unix_socket_directories = '{{ pg_socket_dir }}'
|
||||
unix_socket_permissions = 0700
|
||||
hba_file = '{{ pg_config_dir }}/pg_hba.conf'
|
||||
password_encryption = 'scram-sha-256'
|
||||
shared_buffers = '{{ pg_profile.shared_buffers }}'
|
||||
max_connections = {{ pg_profile.max_connections }}
|
||||
work_mem = '4MB'
|
||||
maintenance_work_mem = '32MB'
|
||||
max_wal_size = '512MB'
|
||||
ssl = on
|
||||
ssl_cert_file = '{{ pg_config_dir }}/server.crt'
|
||||
ssl_key_file = '{{ pg_config_dir }}/server.key'
|
||||
ssl_ca_file = '{{ pg_config_dir }}/ca.crt'
|
||||
archive_mode = off
|
||||
log_statement = none
|
||||
log_min_error_statement = panic
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
# 备份从仓库发起,发现实际 primary,避免切换后定时器仍依赖旧主。
|
||||
[global]
|
||||
repo1-path={{ pg_repo_path }}
|
||||
repo1-retention-full=3
|
||||
process-max=1
|
||||
compress-type=zst
|
||||
compress-level=3
|
||||
start-fast=y
|
||||
log-level-console=info
|
||||
log-level-file=off
|
||||
lock-path={{ pg_repo_path }}/lock
|
||||
[prod]
|
||||
{% for member in pg_backup_members %}
|
||||
pg{{ loop.index }}-host={{ member.address }}
|
||||
pg{{ loop.index }}-host-user=pgprod
|
||||
pg{{ loop.index }}-host-config=/etc/homelab-postgresql/prod/pgbackrest.conf
|
||||
pg{{ loop.index }}-path=/var/lib/homelab-postgresql/prod/data
|
||||
pg{{ loop.index }}-port=5432
|
||||
pg{{ loop.index }}-socket-path=/run/homelab-postgresql-prod
|
||||
pg{{ loop.index }}-user=pgprod
|
||||
{% endfor %}
|
||||
Reference in New Issue
Block a user