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

Distribuzione e manutenzione di PostgreSQL con Ansible

Ansible è uno degli strumenti di automazione IT più conosciuti e ampiamente utilizzati, ci aiuta ad automatizzare attività operative IT come...

  • Avvio dell'host (VM o macchina bare-metal) da zero
  • Configurazione di host e servizi
  • Gestione delle implementazioni e degli aggiornamenti del software
  • Ansible ha anche il supporto per l'orchestrazione dell'infrastruttura cloud, ad esempio la creazione di un gruppo di istanze EC2 e RDS per le tue applicazioni su cloud pubblici (AWS, GCP, Azure). Ulteriori informazioni sul provisioning cloud sono disponibili qui

Poiché questo blog riguarda principalmente la gestione di PostgreSQL utilizzando Ansible, non entreremo nel dettaglio degli utilizzi di Ansible, tuttavia, analizzeremo alcune nozioni di base di Ansible. Ti consiglio di consultare il link del documento Ansible se desideri saperne di più.

Nozioni di base su Ansible

Ansible è un progetto open source scritto in Python il cui codice sorgente è disponibile su GitHub. Poiché si tratta di un pacchetto python, possiamo facilmente installare Ansible usando pip.

Ansible deve essere installato su un solo host da cui orchestreremo le nostre attività operative utilizzando i comandi Ansible (Ansible, Ansible-playbook). Chiamiamo questo host di orchestrazione il nodo di controllo.

I comandi Ansible utilizzano le librerie OpenSSH per accedere agli host di destinazione per l'esecuzione di attività operative, chiamiamo questi host di destinazione Managed Node. Il nome host o l'IP del nodo gestito sono menzionati in un file chiamato Inventory, questo nome file di inventario viene quindi specificato come input per i comandi Ansible.

Nel file di inventario, possiamo elencare più host in un unico gruppo, questo eviterà di ripetere le stesse attività più volte per host diversi. Maggiori dettagli sull'utilizzo del file di inventario sono disponibili qui.

Poiché il comando Ansible utilizza SSH per l'accesso, non è necessario installare Ansible su tutto l'host, deve solo essere installato sul nodo di controllo. Tuttavia, tutti i nodi di controllo e i nodi gestiti dovrebbero avere python e tutte le librerie python necessarie installate. Maggiori informazioni sull'installazione di Ansible sono disponibili qui.

Per la demo, utilizzerò un laptop come nodo di controllo e una VM CentOS-7 guest come nodo gestito. È stato eseguito il provisioning della VM CentOS-7 utilizzando Vagrant sul provider VirtualBox.

Installazione di Ansible sul nodo di controllo

Installeremo Ansible usando pip come indicato nella pagina del documento Ansible. I seguenti comandi sono stati eseguiti come utente "Ansible".

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py --user

Usando l'opzione --user, i comandi pip e Ansible vengono installati nella directory HOME e dobbiamo aggiungere il percorso bin alla nostra variabile d'ambiente PATH.

$ echo 'export PATH=$HOME/Library/Python/2.7/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile

Il seguente comando pip ha installato Ansible versione 2.8.0 (che è l'ultima versione stabile al momento della stesura di questo blog.)

$ pip install --user ansible 
$ which ansible
/Users/Ansible/Library/Python/2.7/bin/Ansible
$ ansible --version
Ansible 2.8.0
...
... 

Controllo Nodo e Nodo Gestito Preverifica

Assicurati di disporre di una connessione di rete adeguata tra il nodo di controllo e il nodo gestito.

Controlla il tuo firewall per eventuali regole che potrebbero bloccare le connessioni in entrata e in uscita sulla porta SSH, in tal caso apri la porta SSH per fornire l'accesso sia sul controllo che sui nodi gestiti.

Innanzitutto, prova a connetterti tramite SSH al nodo gestito. Dovresti essere in grado di accedere al nodo gestito dal nodo di controllo.

È possibile configurare l'accesso SSH senza password ai nodi gestiti in base alle politiche di sicurezza dell'organizzazione. Per questa demo, ho configurato senza password per SSH sul mio nodo gestito "pg01" (CentOS-7) per l'utente "vagabondo". Questo fa sì che il nodo gestito abbia il potere sudo, la maggior parte delle attività di installazione e configurazione dell'host verranno eseguite come utente "vagabondo" con "sudo".

Sul nodo di controllo abbiamo il file di configurazione ansible.cfg che verrà utilizzato dai comandi Ansible. Di seguito sono riportate alcune opzioni di configurazione che sono definite nel file di configurazione. Per saperne di più sulle altre opzioni di configurazione disponibili, controlla il file di configurazione di esempio.

  • porta_remota - Se il server SSH sul nodo gestito viene eseguito su una porta diversa da quella predefinita 22, possiamo cambiarla
  • utente_remoto - Il nome utente di accesso che verrà utilizzato da Ansible per connettere il nodo gestito, per eseguire le attività
  • file_chiave_privata - Chiave privata SSH che verrà utilizzata per l'accesso di Ansible

Poiché la suddetta configurazione si applica globalmente a tutti i nodi gestiti, se vogliamo avere una configurazione diversa per uno specifico host o gruppo host possiamo specificarli nel file di inventario. Puoi vederne un esempio di seguito nel file di inventario "development.yaml".

Esecuzione di una corsa a secco Ansible

Crea un file di inventario "development.yaml" come mostrato di seguito.

$ pwd
/Users/Ansible/postgres-setup

$ cat development.yaml 
all:
  hosts:
  children:
    postgres_clusters:
      hosts:
        pg01:
      vars: 
        ansible_port: 22
        ansible_user: "vagrant"
        ansible_private_key_file: "/Users/Ansible/postgres-setup/private_key"

Nel file di inventario sopra l'host pg01 è uno dei membri del gruppo host postgres_clusters. Le variabili ansible_port, ansible_user e ansible_private_key_file si applicano solo agli host del gruppo postgres_clusters.

Verificheremo ora per vedere se Ansible può eseguire le attività sul nodo gestito. Nell'esempio seguente il comando ansible esegue il ping del modulo sul nodo gestito pg01, se Ansible è stato in grado di eseguire il ping del modulo, dovresti vedere SUCCESS come risposta.

$ ansible -i development.yaml -m ping pg01
pg01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

Quando esegue Ansible sul nodo gestito come prima attività, raccoglie informazioni come nome host, indirizzo IP e memoria del nodo gestito. Per verificarli possiamo chiamare l'impostazione del modulo che restituirebbe un JSON di grandi dimensioni. Possiamo utilizzare qualsiasi di questi nel nostro playbook Ansible.

$ ansible -i development.yaml -m setup pg01 
pg01 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.100.4", 
            "10.0.2.15"
        ], 
        "ansible_all_ipv6_addresses": [
            "fe80::a00:27ff:fe29:ac89", 
            "fe80::5054:ff:fe26:1060"
        ],

Ruolo Ansible

Ansible Role è un modo per raggruppare un determinato insieme di attività correlate e impostazioni di configurazione in un'unica unità semplicemente assegnando un ruolo a un particolare host o gruppo host. Ansible applicherà tutta la configurazione e le attività correlate. Ciò evita di ripetere le attività più volte per ciascun host o gruppo host diverso.

Ogni ruolo è rappresentato come una directory e all'interno della directory del ruolo ci saranno sottodirectory come file predefiniti, gestori, meta, attività, modelli, test, vars. Lo scopo di queste directory può essere trovato qui.

I comandi Ansible, per impostazione predefinita, cercano nella directory dei ruoli sotto i percorsi menzionati in DEFAULT_ROLES_PATH.

$ ansible-config list | grep -A2 '^DEFAULT_ROLES_PATH'
DEFAULT_ROLES_PATH:
  default: ~/.Ansible/roles:/usr/share/Ansible/roles:/etc/Ansible/roles
  description: Colon separated paths in which Ansible will search for Roles.

Galassia Ansible

Ansible Galaxy è un portale in cui le persone della comunità condividono il repository GitHub dei loro ruoli Ansible. Possiamo navigare attraverso il portale della galassia per i ruoli Ansible richiesti. Usando il comando ansible-galaxy, potremmo scaricare e riutilizzare il ruolo. Prima di utilizzare un ruolo, esamina in dettaglio tutti i file Ansible YAML nelle directory defaults, vars, task, templates, handler e sii consapevole di come funziona il ruolo.

Per la nostra distribuzione di PostgreSQL, utilizzeremo il ruolo "postgresql" sviluppato dall'autore ANXS e il repository GitHub.

Installazione del ruolo Ansible "anxs.postgresql"

$ ansible-galaxy  install anxs.postgresql
- downloading role 'postgresql', owned by anxs
- downloading role from https://github.com/ANXS/postgresql/archive/v1.10.1.tar.gz
- extracting anxs.postgresql to /Users/ansible/.Ansible/roles/anxs.postgresql
- anxs.postgresql (v1.10.1) was installed successfully

Il comando precedente installa la directory dei ruoli "anxs.postgresql" nella directory "/Users/ansible/.Ansible/roles", questa è una delle directory in DEFAULT_ROLES_PATH e il comando ansible cercherà in questa directory tutti i ruoli.

Playbook Ansible

Un Ansible Playbook è un file YAML in cui elencheremo le attività o i ruoli che devono essere eseguiti su un particolare host o gruppo host. Puoi leggere ulteriori informazioni sullo sviluppo di playbook e apprendere la definizione di tag come host, attività, ruoli, variabili qui.

Per impostazione predefinita, tutte le attività vengono eseguite come l'utente ansible che ha effettuato l'accesso. Per eseguire attività particolari con un utente diverso (o con privilegio 'root') possiamo utilizzare la funzione. Come utilizzare questo comando può essere trovato qui.

Nel playbook di seguito (postgres-play.yaml), ho elencato il ruolo "anxs.postgresql" nel gruppo host "postgres_clusters", quindi tutte le attività nel ruolo anxs.postgresql verranno eseguite per tutti gli host del gruppo “postgres_clusters”.

$ cat postgres-play.yaml 
---
- hosts: postgres_clusters
  become: yes
  roles: 
    - role: anxs.postgresql

diventa:yes in YAML definisce che questo ruolo verrà eseguito con privilegi più elevati utilizzando il DEFAULT_BECOME_METHOD "sudo"

$ ansible-config list | grep -A2 '^DEFAULT_BECOME_METHOD'
DEFAULT_BECOME_METHOD:
  default: sudo
  description: Privilege escalation method to use when `become` is enabled.

Eseguiremo questo playbook come utente "vagabondo" e all'utente è già stato fornito sudo power.

[[email protected] ~]$ sudo cat /etc/sudoers.d/vagrant
%vagrant ALL=(ALL) NOPASSWD: ALL
Diversinines DevOps Guide to Database ManagementScopri cosa devi sapere per automatizzare e gestire i tuoi database open sourceScarica gratuitamente

Distribuzione di PostgreSQL utilizzando Ansible

Ora eseguiremo il playbook "postgres-play.yaml" che installerà tutti i pacchetti relativi a PostgreSQL e lo configurerà utilizzando le impostazioni predefinite.

Per questo esempio, Ansible installerà PostgreSQL 9.6 sulla porta 5432, con postgres max_connections impostato su 100. Tutte le impostazioni predefinite possono essere trovate nel file /Users/ansible/.Ansible/roles/anxs.postgresql/defaults/main.yml .

$ grep -E '^postgresql_(version|port|max_connections):' ~/.Ansible/roles/anxs.postgresql/defaults/main.yml 
postgresql_version: 9.6
postgresql_port: 5432
postgresql_max_connections: 100

Esecuzione del playbook

$ ansible-playbook -i development.yaml postgres-play.yaml
PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [pg01]
...
...


PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01                       : ok=21   changed=14   unreachable=0    failed=0    skipped=32   rescued=0    ignored=0 

Una volta che Ansible ha eseguito tutte le attività, un riepilogo delle esecuzioni delle attività verrà mostrato in PLAY RECAP.

  • ok=21, 21 attività eseguite senza modifiche.
  • changed=14, 14 task ha apportato modifiche all'host, come l'installazione di postgres, la creazione di directory, file, l'avvio di postgres.
  • skipped=32, 32 attività sono state ignorate, potrebbero essere dovute a alcune funzionalità non abilitate. Poiché stiamo installando su entOS, le attività relative a Ubuntu sono state saltate.

Controlla lo stato e la configurazione del servizio PostgreSQL.

[[email protected] ~]$ systemctl status postgresql-9.6
● postgresql-9.6.service - PostgreSQL 9.6 database server
   Loaded: loaded (/usr/lib/systemd/system/postgresql-9.6.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/postgresql-9.6.service.d
           └─custom.conf
   Active: active (running) since Wed 2019-05-29 07:15:25 UTC; 24min ago
     Docs: https://www.postgresql.org/docs/9.6/static/
  Process: 7559 ExecStartPre=/usr/pgsql-9.6/bin/postgresql96-check-db-dir /var/lib/pgsql/9.6/data (code=exited, status=0/SUCCESS)
 Main PID: 7564 (postmaster)
   CGroup: /system.slice/postgresql-9.6.service
           ├─7564 /usr/pgsql-9.6/bin/postmaster -D /etc/postgresql/9.6/data
           ├─7567 postgres: checkpointer process   
           ├─7568 postgres: writer process   
           ├─7569 postgres: wal writer process   
           ├─7570 postgres: autovacuum launcher process   
           └─7571 postgres: stats collector process   

[[email protected] ~]$ psql -U postgres
psql (9.6.13)
Type "help" for help.

postgres=# show max_connections ;
 max_connections 
-----------------
 100
(1 row)

postgres=# show statement_timeout ;
 statement_timeout 
-------------------
 
(1 row)

postgres=# show log_min_duration_statement ;
 log_min_duration_statement 
----------------------------
 -1
(1 row)

Ora abbiamo installato PostgreSQL sull'host gestito "pg01" utilizzando la configurazione predefinita.

Modifica della configurazione di PostgreSQL

Ora riconfiguriamo l'istanza PostgreSQL utilizzando le nostre impostazioni personalizzate.

Ho creato il file custom.yaml (come mostrato di seguito) che contiene l'elenco delle variabili definite per modificare le impostazioni di PostgreSQL come listen_addresses, max_connections, wal_level, hot_standby, statement_timeout, log_checkpoint, log_lock_waits, log_destination, log_min_duration_statement.

$ pwd
/Users/ansible/postgres-setup
$ cat custom.yaml 
postgresql_listen_addresses: "*"
postgresql_max_connections: 300
postgresql_wal_level: "hot_standby"
postgresql_hot_standby: "on"
postgresql_statement_timeout: 60000
postgresql_log_lock_waits: "on"
postgresql_log_destination: "csvlog"
postgresql_log_min_duration_statement: 0

Ora cambieremo il nostro playbook postgres-play.yaml per usare questo custom.yaml.

$ cat postgres-play.yaml  
---
- hosts: postgres_clusters
  become: yes
  vars_files:
    - ./custom.yaml
  roles: 
    - role: anxs.postgresql

Utilizzando i tag vars_files, ho specificato il file di configurazione personalizzato custom.yaml, che sovrascriverà la configurazione predefinita specificata nel ruolo anxs.postgresql. Maggiori dettagli sulla precedenza delle variabili sono disponibili qui.

Ora potremmo eseguire nuovamente lo stesso comando ansible-playbook che avevamo eseguito in precedenza, ma questo eseguirà tutte le attività come l'installazione di PostgreSQL, la configurazione, la creazione di utenti e database. Per questo dovremmo limitare Ansible a eseguire solo le attività relative alla configurazione di PostgreSQL usando l'opzione --tags .

Per conoscere l'elenco dei tag supportati, potremmo eseguire il comando con --list-tags.

$ ansible-playbook -i development.yaml postgres-play.yaml --list-tags
playbook: postgres-play.yaml
  play #1 (postgres_clusters): postgres_clusters        TAGS: []
      TASK TAGS: [always, postgresql, postgresql-configure, postgresql-databases, postgresql-extensions, postgresql-install, postgresql-monit, postgresql-users]

Dai tag precedenti specificheremo solo il tag postgresql-configure per modificare le impostazioni di postgresql.

$ ansible-playbook  -i development.yaml postgres-play.yaml --tags postgresql-configure

PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [pg01]
...
...

TASK [anxs.postgresql : PostgreSQL | Update configuration - pt. 2 (postgresql.conf)] ***************************************************************************************************************************
changed: [pg01]
...
...
TASK [anxs.postgresql : PostgreSQL | Reload all conf files] ****************************************************************************************************************************************************
changed: [pg01]

PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01                       : ok=13   changed=2    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0

Come si vede nel PLAY RECAP, solo 2 modifiche si sono propagate al nodo gestito pg01. Il primo sta aggiornando la configurazione e il secondo sta ricaricando le configurazioni.

Verificare che le modifiche alla configurazione abbiano avuto effetto sul nodo gestito.

postgres=# show listen_addresses ;
 listen_addresses
------------------
 localhost
(1 row)

postgres=# show max_connections ;
 max_connections 
-----------------
 100
(1 row)

postgres=# show wal_level ;
 wal_level 
-----------
 minimal
(1 row)

postgres=# show hot_standby ;
 hot_standby 
-------------
 off
(1 row)

postgres=# show statement_timeout;
 statement_timeout 
-------------------
 1min
(1 row)

postgres=# show log_lock_waits ;
 log_lock_waits 
----------------
 on
(1 row)

postgres=# show log_destination ;
 log_destination 
-----------------
 csvlog
(1 row)

postgres=# show log_min_duration_statement;
 log_min_duration_statement 
----------------------------
 
(1 row)

Come puoi vedere, alcune configurazioni cambiano come listen_addresses, max_connections, wal_level, hot_standby non hanno ancora avuto effetto. Queste modifiche alla configurazione richiedono un riavvio di PostgreSQL e il ruolo anxs.postgresql ha solo ricaricato il servizio stesso.

Per evitare un riavvio improvviso di PostgreSQL durante le ore di produzione, l'autore originale potrebbe non aver aggiunto l'attività di riavvio al ruolo. Possiamo riavviare manualmente il servizio postgresql, durante il downtime programmato.

[[email protected] ~]$ sudo systemctl restart postgresql-9.6

[[email protected] ~]$ psql -U postgres
psql (9.6.13)

postgres=# show listen_addresses ;
 listen_addresses 
------------------
 
(1 row)

postgres=# show max_connections ;
 max_connections 
-----------------
 300
(1 row)

postgres=# show wal_level;
 wal_level 
-----------
 replica
(1 row)

postgres=# show hot_standby;
 hot_standby 
-------------
 on
(1 row)

Creazione di utenti e database PostgreSQL

Creeremo ora gli utenti “app1” e “app2” e i database “app1_db” e “app2_db” di proprietà rispettivamente degli utenti “app1” e “app2”.

Ho aggiunto due nuove variabili, postgresql_users e postgresql_database a custom.yaml, che contiene l'elenco di utenti e database che devono essere creati. Il ruolo anxs.postgresql utilizza il modulo Ansible postgresql_users e postgresql_db per creare l'utente e il database. Puoi fare riferimento a questi documenti per aggiungere le variabili.

$ cat custom.yaml 
...
...
postgresql_users:
  - name: app1
    pass: md5bb0592c05941d14c231da96950c71b60
    encrypted: yes
  - name: app2
    pass: md5bbb1e4d09b64ca54a237727af46cba7c
    encrypted: yes

postgresql_databases:
  - name: app1_db
    owner: app1 
  - name: app2_db
    owner: app2 

Ora eseguiremo solo le attività associate ai tag postgresql-users e postgresql-databases.

$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-users,postgresql-databases

PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************
...
...
TASK [anxs.postgresql : PostgreSQL | Make sure the PostgreSQL users are present] *******************************************************************************************************************************
changed: [pg01] => (item=None)
changed: [pg01] => (item=None)
changed: [pg01]
...
...
TASK [anxs.postgresql : PostgreSQL | Make sure the PostgreSQL databases are present] ***************************************************************************************************************************
changed: [pg01] => (item={u'owner': u'app1', u'name': u'app1_db'})
changed: [pg01] => (item={u'owner': u'app2', u'name': u'app2_db'})
...
...
PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01                       : ok=6    changed=2    unreachable=0    failed=0    skipped=9    rescued=0    ignored=0

Verifica che gli utenti e i database siano stati creati sull'host gestito.

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 app1      |                                                            | {}
 app2      |                                                            | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 app1_db   | app1     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 app2_db   | app2     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(5 rows)

Consentire agli host esterni di connettersi al server PostgreSQL

Ora consentiremo agli host esterni di connettere il servizio PostgreSQL aggiungendo la variabile postgresql_pg_hba_custom a custom.yaml

$ cat custom.yaml
...
...
postgresql_pg_hba_custom:
  - {type: "host", database: "all", user: "all", address: "0.0.0.0/0", method: "md5" }

Esecuzione delle attività contrassegnate con postgresql-configure, per applicare la configurazione.

$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-configure

Verifica se riesco a connettermi al server PostgreSQL dal mio nodo di controllo.

$ PGPASSWORD=password psql -h pg01 -U app1 -d app1_db -c 'Select true'
 bool
------
 
(1 row)

Conclusione

Questo blog dovrebbe fornirti le nozioni di base che devi sapere per utilizzare Ansible per la distribuzione e la gestione di PostgreSQL. Tuttavia, abbiamo coperto solo alcune attività di amministrazione di PostgreSQL. A seconda dell'infrastruttura della tua organizzazione, potresti dover sovrascrivere molte delle configurazioni predefinite e aggiungere ancora più attività al ruolo Ansible.