PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Configurazione e manutenzione della replica PostgreSQL utilizzando Ansible

La replica è una funzionalità chiave per la maggior parte delle configurazioni ed è supportata dalla maggior parte delle tecnologie di database sul mercato. La comunità di PostgreSQL ha introdotto la replica nella versione 9.0 (denominata Streaming Replication o SR), da allora la replica in PostgreSQL si è evoluta con funzionalità aggiuntive come Cascading Replication, Logical Decoding e molte altre ottimizzazioni.

In questo blog, esamineremo l'utilizzo del ruolo Ansible postgresql sviluppato da "Demonware" (un fork del ruolo "ANXS/postgresql"). Avevo già parlato dell'utilizzo del ruolo "ANXS/postgresql" nel mio blog precedente ma non ho discusso della funzionalità di replica. Il ruolo Ansible "postgresql" aggiunge la possibilità di impostare la replica PostgreSQL utilizzando repmgr.

Informazioni su Repmgr

Repmgr è uno strumento da riga di comando open source sviluppato e mantenuto da 2ndQuadrant. Lo strumento automatizza la maggior parte delle attività relative alla gestione del cluster di replica PostgreSQL. Di seguito è riportato l'elenco delle attività che possono essere eseguite senza problemi utilizzando il comando repmgr e il demone repmgrd.

  • Avvio del cluster di replica PostgreSQL.
  • Eseguire il failover automatico e il passaggio manuale dell'istanza principale.
  • Aggiunta e rimozione delle istanze di standby (lettura-replica).

Preparazione del nodo controller

Prepara il nodo controller con il ruolo Ansible PostgreSQL, i playbook, gli inventari e la replica PostgreSQL personalizzata.

$ mkdir demo
$ pushd demo
$ mkdir roles
$ git clone https://github.com/Demonware/postgresql roles/postgresql
$ pushd roles/postgresql
$ git checkout add-repmgr-extension

Nel ruolo scaricato sono presenti due file di variabili di default main.yml e repmgr.yml. Tuttavia, Ansible considererà solo il file main.yml. Per fare in modo che Ansible utilizzi anche il file repmgr.yml, stiamo spostando entrambi i file nella directory defaults/main.

$ mkdir defaults/main
$ mv defaults/main.yml defaults/repmgr.yml defaults/main
$ popd

File di inventario Ansible

Per la demo, configureremo il cluster di replica PostgreSQL su tre nodi. Ho creato tre macchine virtuali CentOS vm-01, vm-02 e vm-03, tutte elencate nel gruppo postgres_cluster nel file development.yaml.

$ cat development.yaml
all:
  children:
    postgres_cluster:
      hosts:
        vm-01:
        vm-02:
        vm-03:
      vars:
        ansible_user: "vagrant"

Esegui il ping Ansible e assicurati di poter raggiungere tutti gli host nel gruppo postgres_cluster.

$ ansible -i development.yaml -m ping  postgres_cluster
vm-01 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
vm-03 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
vm-02 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

File di variabili personalizzate

Nel file della variabile personalizzata custom-vars.yaml, definiremo le seguenti cose:

  • Versione di PostgreSQL da installare e codifica da utilizzare
  • Modificando la configurazione di PostgreSQL per abilitare la replica, modificheremo parametri come wal_level, max_wal_senders, max_replication_slots, hot_standby, archive_mode, archive_command
  • Creazione degli utenti e del database necessari
  • Modifica del file pg_hba.conf per consentire la connessione necessaria dall'applicazione e la replica repmgr
  • Alcune variabili relative a repmgr
$ cat custom-vars.yaml 
# Basic settings
postgresql_version: 11
postgresql_encoding: "UTF-8"
postgresql_locale: "en_US.UTF-8"
postgresql_ctype: "en_US.UTF-8"
postgresql_admin_user: "postgres"
postgresql_default_auth_method: "peer"
postgresql_listen_addresses: "*"
postgresql_wal_level: "replica"
postgresql_max_wal_senders: 10
postgresql_max_replication_slots: 10
postgresql_wal_keep_segments: 100
postgresql_hot_standby: on
postgresql_archive_mode: on
postgresql_archive_command: "/bin/true"
postgresql_shared_preload_libraries:
  - repmgr

postgresql_users:
  - name: "{{repmgr_user}}"
    pass: "password"
postgresql_databases:
  - name: "{{repmgr_database}}"
    owner: "{{repmgr_user}}"
    encoding: "UTF-8"
postgresql_user_privileges:
  - name: "{{repmgr_user}}"
    db: "{{repmgr_database}}"
    priv: "ALL"
    role_attr_flags: "SUPERUSER,REPLICATION"
postgresql_pg_hba_custom:
  - { type: "host", database: "all", user: "all", address: "192.168.0.0/24", method: "md5" }
  - { type: "host", database: "replication", user: "repmgr", address: "192.168.0.0/24", method: "md5" }  
  - { type: "host", database: "replication", user: "repmgr", address: "127.0.0.1/32", method: "md5" }  

# repmgr related variables
postgresql_ext_install_repmgr: yes
repmgr_target_group: "postgres_cluster"
repmgr_target_group_hosts: "{{ groups[repmgr_target_group] }}"
repmgr_master: "vm-03"

Di seguito sono riportate alcune delle variabili degne di nota definite in custom-vars.yaml:

  • postgresql_version:11 - Installa PostgreSQL versione 11
  • postgresql_ext_install_repmgr:yes - Installa l'estensione repmgr sul cluster PostgreSQL
  • repmgr_target_group:"postgres_cluster" - Repmgr funziona sugli host definiti nel gruppo "postgres_cluster" definito nel file di inventario
  • repmgr_master:"vm-03" - L'host vm-03 sarà l'istanza primaria di PostgreSQL, vm-01 e vm--02 verranno replicati da vm-03

Playbook Ansible

Nel playbook postgres-play.yaml di seguito, ho assegnato il ruolo postgresql contro il gruppo host postgres_cluster. Ho anche incluso il file di variabili personalizzate custom-vars.yaml che ha la configurazione per PostgreSQL e repmgr.

$ cat postgres-play.yaml 
- hosts: postgres_cluster
  become: yes
  vars_files:
    - ./custom-vars.yaml
  roles:
    - postgresql

Esecuzione di Ansible Playbook

Ora abbiamo creato i seguenti artefatti Ansible e siamo pronti per eseguire il playbook Ansible.

  • ruoli/postgresql, directory dei ruoli Ansible.
  • custom-vars.yaml, file di variabili Ansible.
  • development.yaml, file di inventario Ansible.
  • postgres-play.yam, file del playbook di Ansible.

Esegui il comando ansible-playbook di seguito dal nodo controller. Poiché il ruolo postgresql prevede l'accesso sudo del controller, stiamo specificando l'opzione -K nel comando, che a sua volta ci chiede di inserire la password SUDO del nodo controller.

$ ansible-playbook -Ki development.yaml postgres-play.yaml 
SUDO password: 

PLAY [postgres_cluster] ********************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************************************************
ok: [vm-01]
ok: [vm-02]
ok: [vm-03]
...
...
PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
vm-01                      : ok=41   changed=4    unreachable=0    failed=0
vm-02                      : ok=41   changed=5    unreachable=0    failed=0
vm-03                      : ok=43   changed=5    unreachable=0    failed=0

Controlla PLAY RECAP nell'output del comando e assicurati che il conteggio fallito sia 0.

Controlla la replica PostgreSQL

Con il seguente comando repmgr cluster show possiamo controllare lo stato del cluster di replica PostgreSQL. Mostra il ruolo, lo stato, la sequenza temporale di tutte le istanze PostgreSQL nel cluster di replica.

$ sudo -u postgres /usr/pgsql-11/bin/repmgr -f /etc/postgresql/11/data/repmgr.conf cluster show
 ID | Name  | Role    | Status    | Upstream | Location | Priority | Timeline | Connection string                                     
----+-------+---------+-----------+----------+----------+----------+----------+--------------------------------------------------------
 1  | vm-01 | standby |   running | vm-03    | default  | 100      | 1        | host=vm-01 user=repmgr dbname=repmgr connect_timeout=2
 2  | vm-02 | standby |   running | vm-03    | default  | 100      | 1        | host=vm-02 user=repmgr dbname=repmgr connect_timeout=2
 3  | vm-03 | primary | * running |          | default  | 100      | 1        | host=vm-03 user=repmgr dbname=repmgr connect_timeout=2

Dall'output del comando precedente, vm-03 è l'istanza primaria e vm-01, vm02 sono l'istanza standby che replica dal nodo upstream vm-03. Tutte le istanze di PostgreSQL sono in esecuzione.

Controllo della vista pg_stat_replication sulla vm-03 primaria per confermare che sia la vm-01 che la vm-02 stanno replicando correttamente.

$ sudo -iu postgres /usr/pgsql-11/bin/psql -h vm-03 -c 'select * from pg_stat_replication'
Password for user postgres: 
 pid  | usesysid | usename | application_name |  client_addr  | client_hostname | client_port |         backend_start         | backend_xmin |   state   | sent_lsn  | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | replay_lag | sync_priority | sync_state 
------+----------+---------+------------------+---------------+-----------------+-------------+-------------------------------+--------------+-----------+-----------+-----------+-----------+------------+-----------+-----------+------------+---------------+------------
 8480 |    16384 | repmgr  | vm-02            | 192.168.0.122 |                 |       59972 | 2019-07-18 09:04:44.315859+00 |              | streaming | 0/A000870 | 0/A000870 | 0/A000870 | 0/A000870  |           |           |            |             0 | async
 8481 |    16384 | repmgr  | vm-01            | 192.168.0.121 |                 |       35598 | 2019-07-18 09:04:44.336693+00 |              | streaming | 0/A000870 | 0/A000870 | 0/A000870 | 0/A000870  |           |           |            |             0 | async
(2 rows)

Aggiunta di un altro nodo di standby al cluster

Per aggiungere un altro nodo PostgreSQL al cluster, dobbiamo semplicemente rieseguire il playbook Ansible dopo aver aggiunto il particolare host nell'inventario. Nei passaggi seguenti, aggiungo vm-04 al mio cluster di replica Repmgr Postgresql esistente.

  1. Aggiunta di vm-04 al file di inventario Ansible developermeb
    $ cat development.yaml
    all:
      children:
        postgres_cluster:
          hosts:
            vm-01:
            vm-02:
            vm-03:
            vm-04:
          vars:
            ansible_user: "vagrant"
  2. Esegui playbook Ansible
    $ ansible-playbook -Ki development.yaml postgres-play.yaml
    SUDO password:
    
    PLAY [postgres_cluster] ********************************************************************************************************************************************************************************************************************************************************
    
    TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************************************************
    ok: [vm-01]
    ok: [vm-04]
    ok: [vm-03]
    ok: [vm-02]
    ...
    ...
    RUNNING HANDLER [postgresql : restart postgresql] ******************************************************************************************************************************************************************************************************************************
    changed: [vm-04]
    changed: [vm-02]
    changed: [vm-01]
    changed: [vm-03]
    
    PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
    vm-01                      : ok=41   changed=4    unreachable=0    failed=0
    vm-02                      : ok=41   changed=5    unreachable=0    failed=0
    vm-03                      : ok=43   changed=5    unreachable=0    failed=0
    vm-04                      : ok=46   changed=32   unreachable=0    failed=0
  3. Controlla il cluster di replica
    $ sudo -u postgres /usr/pgsql-11/bin/repmgr -f /etc/postgresql/11/data/repmgr.conf cluster show
     ID | Name  | Role    | Status    | Upstream | Location | Priority | Timeline | Connection string                                     
    ----+-------+---------+-----------+----------+----------+----------+----------+--------------------------------------------------------
     1  | vm-01 | standby |   running | vm-03    | default  | 100      | 1        | host=vm-01 user=repmgr dbname=repmgr connect_timeout=2
     2  | vm-02 | standby |   running | vm-03    | default  | 100      | 1        | host=vm-02 user=repmgr dbname=repmgr connect_timeout=2
     3  | vm-03 | primary | * running |          | default  | 100      | 1        | host=vm-03 user=repmgr dbname=repmgr connect_timeout=2
     4  | vm-04 | standby |   running | vm-03    | default  | 100      | 1        | host=vm-04 user=repmgr dbname=repmgr connect_timeout=2

Conclusione

Finora abbiamo visto come configurare il cluster di replica Repmgr PostgreSQL utilizzando Ansible. Una volta che il cluster repmgr è stato configurato, possiamo utilizzare il comando repmgr per eseguire altre operazioni di manutenzione sul cluster di replica, ad esempio eseguire il failover e il passaggio del nodo primario e impostare la replica a cascata. Si prega di controllare la documentazione di repmgr per maggiori dettagli.