Skip to content

Commit 450d556

Browse files
authored
Merge pull request #819 from wireapp/move-repmgr-secret-to-k8s
Move secret configuration for postgresql cluster to a seperate playbook
2 parents c70451b + c16937a commit 450d556

File tree

10 files changed

+707
-250
lines changed

10 files changed

+707
-250
lines changed

ansible/inventory/offline/99-static

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,13 @@
7777
# cassandra_network_interface = enp1s0
7878
# setting either cassandra backup directive to 'True' below requires a valid s3 bucket name as well
7979
# also, enabling backups will install `awscli` via pip, which requires an internet connection
80-
# cassandra_backup_enabled = False
80+
# cassandra_backup_enabled = False
8181
# cassandra_incremental_backup_enabled = False
8282
# cassandra_backup_s3_bucket = <bucketname>
8383

8484
[postgresql:vars]
8585
postgresql_network_interface = enp1s0
86-
wire_dbname = wire-server
87-
wire_user = wire-server
88-
wire_namespace = default # Kubernetes namespace for secret storage
86+
8987

9088
[elasticsearch:vars]
9189
# elasticsearch_network_interface = enp1s0

ansible/inventory/offline/group_vars/postgresql/postgresql.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,25 @@ postgresql_version: 17
33
postgresql_data_dir: /var/lib/postgresql/{{ postgresql_version }}/main
44
postgresql_conf_dir: /etc/postgresql/{{ postgresql_version }}/main
55

6+
# wire-server database configuration
7+
wire_dbname: wire-server
8+
wire_user: wire-server
9+
wire_namespace: default # Kubernetes namespace for secret storage
10+
611
# repmgr HA configuration
712
repmgr_user: repmgr
8-
repmgr_password: "securepassword"
913
repmgr_database: repmgr
14+
# Note: repmgr_password is NOT defined here - it's dynamically set by postgresql-secrets.yml
15+
# The password is fetched from K8s secret or auto-generated during deployment.
16+
# To manually pre-create: kubectl create secret generic repmgr-postgresql-secret -n <namespace> --from-literal=password=<your-password>
17+
18+
# Kubernetes Secret configuration for repmgr
19+
repmgr_secret_name: "repmgr-postgresql-secret"
20+
repmgr_namespace: "{{ wire_namespace | default('default') }}"
21+
22+
# Kubernetes Secret configuration for wire-server PostgreSQL user
23+
# This is managed alongside repmgr credentials in postgresql-secrets.yml
24+
wire_pg_secret_name: "wire-postgresql-external-secret"
1025

1126
# Node configuration for repmgr
1227
repmgr_node_config:

ansible/postgresql-deploy.yml

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,60 @@
1+
# ===================================================================
2+
# PostgreSQL Deployment Pipeline
3+
# ===================================================================
4+
# This playbook orchestrates PostgreSQL cluster deployment.
5+
# Playbooks run in strict order due to dependencies.
6+
#
7+
# Dependency Chain:
8+
# secrets → primary → replica → verify → wire-setup → monitoring
9+
# (cleanup/install are independent but should run first)
10+
#
11+
# Tag Strategy:
12+
# - Use --skip-tags to exclude specific steps
13+
# - Do NOT use --tags to run individual steps (will break dependencies)
14+
# - Recommended: Run full playbook or use skip-tags
15+
#
16+
# Usage Examples:
17+
# Full deployment(Cleans up the previous state if any, sets up HA pg cluster, deploy the guard against split-brain issues and sets up wire-server DB): ansible-playbook -i <inventory_file> postgresql-deploy.yml
18+
# Skip cleanup(cleans up the previous repmgr state and re-initializes the database as new state): ansible-playbook -i <inventory_file> postgresql-deploy.yml --skip-tags cleanup
19+
# Skip monitoring(In general this step should not be skipped as it sets up the guard against split-brain issues): ansible-playbook -i <inventory_file> postgresql-deploy.yml --skip-tags monitoring
20+
# Skip wire-setup (sets up the wire-server database and user): ansible-playbook -i <inventory_file> postgresql-deploy.yml --skip-tags wire-setup
21+
#
22+
#
23+
# To run from a specific point, comment out earlier playbooks.
24+
# ===================================================================
25+
126
- name: Clean previous deployment state
227
import_playbook: postgresql-playbooks/clean_existing_setup.yml
3-
tags:
4-
- postgresql
5-
- cleanup
28+
tags: [postgresql, cleanup]
629

730
- name: Install PostgreSQL packages
831
import_playbook: postgresql-playbooks/postgresql-install.yml
9-
tags:
10-
- postgresql
11-
- install
32+
tags: [postgresql, install]
33+
34+
- name: Setup PostgreSQL passwords from Kubernetes Secrets
35+
import_playbook: postgresql-playbooks/postgresql-secrets.yml
36+
tags: [postgresql, secrets]
37+
# Sets facts: repmgr_password, wire_pass (required by all following playbooks)
1238

1339
- name: Deploy PostgreSQL primary node
1440
import_playbook: postgresql-playbooks/postgresql-deploy-primary.yml
15-
tags:
16-
- postgresql
17-
- primary
41+
tags: [postgresql, primary]
42+
# Requires: repmgr_password
1843

1944
- name: Deploy PostgreSQL replica nodes
2045
import_playbook: postgresql-playbooks/postgresql-deploy-replica.yml
21-
tags:
22-
- postgresql
23-
- replica
46+
tags: [postgresql, replica]
47+
# Requires: repmgr_password
2448

2549
- name: Verify PostgreSQL deployment
2650
import_playbook: postgresql-playbooks/postgresql-verify-HA.yml
27-
tags:
28-
- postgresql
29-
- verify
51+
tags: [postgresql, verify]
3052

3153
- name: Setup wire-server postgresql database and user
3254
import_playbook: postgresql-playbooks/postgresql-wire-setup.yml
33-
tags:
34-
- postgresql
35-
- wire-setup
55+
tags: [postgresql, wire-setup]
56+
# Requires: wire_pass
3657

3758
- name: Deploy cluster monitoring
3859
import_playbook: postgresql-playbooks/postgresql-monitoring.yml
39-
tags:
40-
- postgresql
41-
- monitoring
60+
tags: [postgresql, monitoring]

ansible/postgresql-playbooks/postgresql-deploy-primary.yml

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,33 @@
99
replica_node2: "{{ hostvars[(groups.get('postgresql_ro', []) | last) | default('postgresql3')]['ansible_default_ipv4']['address'] | default(hostvars[(groups.get('postgresql_ro', []) | last) | default('postgresql3')]['ansible_host'] | default((groups.get('postgresql_ro', []) | last) | default('postgresql3'))) }}"
1010
pg_service_name: "postgresql@{{ postgresql_version }}-main.service"
1111
tasks:
12+
# ===== PREREQUISITE VALIDATION =====
13+
- name: Validate required secrets are available
14+
ansible.builtin.assert:
15+
that:
16+
- repmgr_password is defined
17+
- repmgr_password | length > 0
18+
fail_msg: |
19+
❌ PREREQUISITE FAILED: repmgr_password is not available!
20+
21+
This playbook requires the repmgr password to be set as an Ansible fact.
22+
23+
Solution:
24+
Run the complete deployment pipeline:
25+
ansible-playbook postgresql-deploy.yml
26+
27+
OR run with the postgresql tag to include secrets:
28+
ansible-playbook postgresql-deploy.yml --tags postgresql
29+
30+
OR run secrets playbook first:
31+
ansible-playbook postgresql-playbooks/postgresql-secrets.yml
32+
ansible-playbook postgresql-playbooks/postgresql-deploy-primary.yml
33+
34+
The postgresql-secrets.yml playbook fetches/creates passwords from Kubernetes
35+
and sets them as Ansible facts for use by deployment playbooks.
36+
success_msg: "✅ Prerequisites validated: repmgr_password is available"
37+
run_once: true
38+
1239
- name: Ensure repmgr scripts directory exists
1340
ansible.builtin.file:
1441
path: /opt/repmgr/scripts
@@ -103,11 +130,18 @@
103130
when: repmgr_user_check.stdout.strip() == "0"
104131
register: create_repmgr_user
105132

133+
- name: Update repmgr user password (if user already exists)
134+
ansible.builtin.shell: |
135+
sudo -u postgres psql -c "ALTER USER {{ repmgr_user }} WITH PASSWORD '{{ repmgr_password }}';"
136+
when: repmgr_user_check.stdout.strip() != "0"
137+
register: update_repmgr_password
138+
no_log: true
139+
106140
- name: Display user creation result
107141
ansible.builtin.debug:
108142
msg: |
109-
repmgr user status: {{ 'CREATED' if repmgr_user_check.stdout.strip() == "0" else 'ALREADY EXISTS' }}
110-
when: create_repmgr_user is defined
143+
repmgr user status: {{ 'CREATED' if repmgr_user_check.stdout.strip() == "0" else 'ALREADY EXISTS (password updated)' }}
144+
when: create_repmgr_user is defined or update_repmgr_password is defined
111145

112146
- name: Check if repmgr database exists
113147
ansible.builtin.shell: |
@@ -201,13 +235,33 @@
201235
PGPASSWORD: "{{ repmgr_password }}"
202236
register: repmgr_connection_test
203237

204-
- name: Start repmgrd service
238+
- name: Determine if repmgrd needs restart
239+
ansible.builtin.set_fact:
240+
repmgrd_needs_restart: >-
241+
{{
242+
(update_repmgr_password is defined and update_repmgr_password.changed) or
243+
primary_conf_result.changed
244+
}}
245+
246+
- name: Restart repmgrd if password or config changed
247+
ansible.builtin.systemd:
248+
name: "repmgrd@{{ postgresql_version }}-main"
249+
state: restarted
250+
enabled: yes
251+
daemon_reload: yes
252+
when:
253+
- repmgr_connection_test is succeeded
254+
- repmgrd_needs_restart
255+
256+
- name: Start repmgrd service (if not restarted)
205257
ansible.builtin.systemd:
206258
name: "repmgrd@{{ postgresql_version }}-main"
207259
state: started
208260
enabled: yes
209261
daemon_reload: yes
210-
when: repmgr_connection_test is succeeded
262+
when:
263+
- repmgr_connection_test is succeeded
264+
- not repmgrd_needs_restart
211265

212266
- name: Verify repmgrd is running
213267
ansible.builtin.systemd:

ansible/postgresql-playbooks/postgresql-deploy-replica.yml

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,33 @@
99
current_replica: "{{ ansible_default_ipv4.address | default(ansible_host) }}"
1010
pg_service_name: "postgresql@{{ postgresql_version }}-main.service"
1111
tasks:
12+
# ===== PREREQUISITE VALIDATION =====
13+
- name: Validate required secrets are available
14+
ansible.builtin.assert:
15+
that:
16+
- repmgr_password is defined
17+
- repmgr_password | length > 0
18+
fail_msg: |
19+
❌ PREREQUISITE FAILED: repmgr_password is not available!
20+
21+
This playbook requires the repmgr password to be set as an Ansible fact.
22+
23+
Solution:
24+
Run the complete deployment pipeline:
25+
ansible-playbook postgresql-deploy.yml
26+
27+
OR run with the postgresql tag to include secrets:
28+
ansible-playbook postgresql-deploy.yml --tags postgresql
29+
30+
OR run secrets playbook first:
31+
ansible-playbook postgresql-playbooks/postgresql-secrets.yml
32+
ansible-playbook postgresql-playbooks/postgresql-deploy-replica.yml
33+
34+
The postgresql-secrets.yml playbook fetches/creates passwords from Kubernetes
35+
and sets them as Ansible facts for use by deployment playbooks.
36+
success_msg: "✅ Prerequisites validated: repmgr_password is available"
37+
run_once: true
38+
1239
# ===== INITIAL STATUS CHECK =====
1340
- name: Check replica configuration status
1441
block:
@@ -57,6 +84,7 @@
5784
group: postgres
5885
mode: "{{ item.mode }}"
5986
backup: yes
87+
register: replica_conf_result
6088
loop:
6189
- src: ../templates/postgresql/pg_hba.conf.j2
6290
dest: "{{ postgresql_conf_dir }}/pg_hba.conf"
@@ -276,12 +304,28 @@
276304
sudo -u postgres repmgr node status
277305
when: (verify_replica_reg.query_result[0].cnt | int) != 1
278306

279-
- name: Start repmgrd service
307+
- name: Determine if repmgrd needs restart
308+
ansible.builtin.set_fact:
309+
repmgrd_needs_restart: >-
310+
{{
311+
replica_conf_result.changed
312+
}}
313+
314+
- name: Restart repmgrd if config changed
315+
ansible.builtin.systemd:
316+
name: "repmgrd@{{ postgresql_version }}-main"
317+
state: restarted
318+
enabled: yes
319+
daemon_reload: yes
320+
when: repmgrd_needs_restart
321+
322+
- name: Start repmgrd service (if not restarted)
280323
ansible.builtin.systemd:
281324
name: "repmgrd@{{ postgresql_version }}-main"
282325
state: started
283326
enabled: yes
284327
daemon_reload: yes
328+
when: not repmgrd_needs_restart
285329

286330
- name: Verify repmgrd is running
287331
ansible.builtin.systemd:

0 commit comments

Comments
 (0)