AlmaLinux - Monitoring - PostgreSQL - Zabbix

Gestione degli aggiornamenti di Zabbix

La gestione degli aggiornamenti di Zabbix comprende in realtà tre operazioni distinte, ognuna con le proprie implicazioni. Un aggiornamento di minor release è routine, si aggiornano i pacchetti, si riavviano i servizi, si verifica il log. Un aggiornamento major di Zabbix è più delicato perché al primo avvio il server migra automaticamente lo schema del database, operazione che su installazioni con anni di dati può richiedere diversi minuti. L’aggiornamento di PostgreSQL a una nuova major version è invece completamente separato da Zabbix, richiede una pianificazione specifica, la verifica della compatibilità con TimescaleDB e una scelta consapevole tra gli approcci disponibili in base allo spazio disco a disposizione.

Prima di ogni aggiornamento

Qualsiasi tipo di aggiornamento (minor release, major di Zabbix o major di PostgreSQL) richiede un backup preliminare del database. Fermare prima il server Zabbix ed eseguire il dump

systemctl stop zabbix-server

sudo -u postgres pg_dump --format=custom --compress=9 \
    --file=/backup/zabbix_pre_update_$(date +%Y%m%d).pgdump zabbix

Aggiornamento delle minor release

Le minor release (es. da 7.4.1 a 7.4.2, oppure da 7.0.10 a 7.0.11) contengono correzioni di bug e fix di sicurezza. Non richiedono migrazione dello schema e il processo è semplice. Dobbiamo solo aggiornare i pacchetti di Zabbix

dnf update zabbix-server-pgsql zabbix-web-pgsql zabbix-agent2 zabbix-sql-scripts

e procedere con il riavvio dei servizi

systemctl restart zabbix-server zabbix-agent2 nginx php-fpm

Infine verifichiamo che il server si sia avviato correttamente

systemctl status zabbix-server

Aggiornamento ad una major release

Un aggiornamento major (es. da 7.0 LTS a 7.4) richiede una procedura più articolata perché può includere modifiche allo schema del database. Zabbix gestisce automaticamente la migrazione dello schema al primo avvio della nuova versione, ma è indispensabile prepararsi correttamente.

Il primo passo è leggere le release notes della versione di destinazione, in particolare la sezione “Upgrade notes”: alcune versioni richiedono passi manuali aggiuntivi prima o dopo la migrazione automatica.

Il passaggio successivo è aggiornare il repository Zabbix sostituendo quello della versione corrente con quello della versione target. La URL del pacchetto cambia ad ogni versione ed è possibile recuperarla dalla pagina ufficiale https://www.zabbix.com/download, selezionando la versione di destinazione ed il sistema operativo. Nell’esempio seguente viene utilizzato il repository per AlmaLinux 9

rpm -e zabbix-release
rpm -Uvh https://repo.zabbix.com/zabbix/7.4/release/alma/9/noarch/zabbix-release-latest-7.4.el9.noarch.rpm
dnf clean all

Con il repository aggiornato, possiamo procedere con l’aggiornamento dei pacchetti

dnf update zabbix-server-pgsql zabbix-web-pgsql zabbix-agent2 zabbix-sql-scripts

All’avvio del server Zabbix, il processo rileva automaticamente che lo schema necessita di aggiornamento e applica le migrazioni necessarie. Su database di grandi dimensioni questo può richiedere alcuni minuti

systemctl start zabbix-server
tail -f /var/log/zabbix/zabbix_server.log

Attendere che nel log compaia la riga server #0 started [main process] prima di considerare la migrazione completata.

In questo esempio di upgrade la versione di partenza era la 7.0.28 e quella di destinazione 7.4.12. Al primo accesso all’interfaccia web viene visualizzato il messaggio con eventuali altre operazioni da effettuare necessarie per il completamento dell’upgrade

Zabbix upgrade process

Completato quando indicato sarà di nuovo possibile accedere al portale.

Aggiornamento di PostgreSQL

L’aggiornamento di PostgreSQL tra major version (es. da 16 a 17) richiede una procedura separata rispetto all’aggiornamento di Zabbix e non può essere fatto con un semplice dnf update. Le opzioni principali sono due:

  • pg_upgrade: migrazione in-place del cluster, più veloce ma richiede attenzione alla compatibilità delle estensioni
  • dump e restore: più lento ma più sicuro ed è la procedura consigliata in presenza di TimescaleDB, poiché l’estensione deve essere reinstallata e ricreata sul nuovo cluster

Prima di procedere, verificare che la versione di TimescaleDB per la nuova major release di PostgreSQL sia disponibile, in quanto TimescaleDB ha un proprio ciclo di release non sempre allineato con quello di PostgreSQL.

Spazio disco necessario

I due approcci hanno requisiti di spazio molto diversi. Se prendiamo come esempio un database da 100 GB.

pg_upgrade utilizza di default gli hard link: invece di copiare i file, crea riferimenti agli stessi blocchi su disco. Il nuovo cluster occupa pochissimo spazio aggiuntivo (qualche centinaio di MB per le strutture di sistema). Se ad esempio abbiamo un volume da 140 GB e un database da 100 GB c’è margine sufficiente. Il requisito è che vecchio e nuovo cluster si trovino sullo stesso filesystem, ad esempio su AlmaLinux entrambi risiedono sotto /var/lib/pgsql/, quindi la condizione è soddisfatta per default.

Dump e restore invece richiede che vecchio cluster e nuovo cluster coesistano sul volume principale durante la migrazione. Il file di backup può stare su uno storage esterno, ma raddoppia lo spazio necessario in quanto

  • vecchio cluster: ~100 GB
  • nuovo cluster (dopo il restore): ~100 GB
  • totale: ~200 GB

Quindi con un volume da 140 GB l’approccio dump/restore non è praticabile senza aggiungere storage. Eliminare il vecchio cluster prima di avviare il restore libererebbe spazio, ma se il restore fallisse il backup esterno sarebbe l’unico punto di ripristino disponibile.

pg_upgrade

pg_upgrade esegue la migrazione in-place: i dati del vecchio cluster vengono convertiti e trasferiti nel nuovo senza un dump completo, il che lo rende significativamente più veloce su database di grandi dimensioni. Installare la nuova versione di PostgreSQL e la versione corrispondente di TimescaleDB, quindi inizializzare il nuovo cluster:

dnf install postgresql17-server postgresql17-contrib timescaledb-2-postgresql-17
/usr/pgsql-17/bin/postgresql-17-setup initdb

Aggiungere TimescaleDB a shared_preload_libraries nel file di configurazione del nuovo cluster prima di eseguire la migrazione

echo "shared_preload_libraries = 'timescaledb'" >> /var/lib/pgsql/17/data/postgresql.conf

Ora possiamo fermare il vecchio PostgreSQL ed eseguire pg_upgrade

systemctl stop postgresql-16

sudo -u postgres /usr/pgsql-17/bin/pg_upgrade \
    -b /usr/pgsql-16/bin \
    -B /usr/pgsql-17/bin \
    -d /var/lib/pgsql/16/data \
    -D /var/lib/pgsql/17/data

Al termine, disabilitare il vecchio servizio, avviare il nuovo e aggiornare l’estensione TimescaleDB

systemctl disable postgresql-16
systemctl enable postgresql-17
systemctl start postgresql-17

sudo -u postgres psql -d zabbix -c "ALTER EXTENSION timescaledb UPDATE;"

Possiamo ora avviare Zabbix e verificare che nel log non siano presenti errori

systemctl start zabbix-server
tail -f /var/log/zabbix/zabbix_server.log

Dump e restore

L’approccio dump e restore è più lento ma più controllabile: il vecchio cluster rimane intatto fino al completamento della migrazione e TimescaleDB viene reinstallato da zero sul nuovo cluster, eliminando problemi di compatibilità delle strutture interne dell’estensione.

Installare la nuova versione di PostgreSQL e TimescaleDB, inizializzare il cluster e configurare shared_preload_libraries

dnf install postgresql17-server postgresql17 timescaledb-2-postgresql-17
/usr/pgsql-17/bin/postgresql-17-setup initdb
echo "shared_preload_libraries = 'timescaledb'" >> /var/lib/pgsql/17/data/postgresql.conf

Fermare il vecchio PostgreSQL e avviare il nuovo

systemctl stop postgresql-16
systemctl enable postgresql-17
systemctl start postgresql-17

Creare l’utente e il database sul nuovo cluster, quindi abilitare TimescaleDB

sudo -u postgres psql -c "CREATE USER zabbix WITH PASSWORD 'password';"
sudo -u postgres psql -c "CREATE DATABASE zabbix OWNER zabbix TEMPLATE template0;"
sudo -u postgres psql -d zabbix -c "CREATE EXTENSION IF NOT EXISTS timescaledb;"

Prima di avviare il restore, mettere il database in modalità ripristino TimescaleDB per disabilitare i trigger e i controlli interni che altrimenti bloccherebbero l’importazione dei dati storici

sudo -u postgres psql -d zabbix -c "SELECT timescaledb_pre_restore();"

Eseguire il restore dal backup creato in precedenza

sudo -u postgres pg_restore --format=custom --no-acl --no-owner \
    --dbname=zabbix /backup/zabbix_pre_pg_upgrade_$(date +%Y%m%d).pgdump

Completato il restore, riabilitare TimescaleDB e aggiornare l’estensione

sudo -u postgres psql -d zabbix -c "SELECT timescaledb_post_restore();"
sudo -u postgres psql -d zabbix -c "ALTER EXTENSION timescaledb UPDATE;"

Possiamo ora disabilitare il vecchio servizio, avviare Zabbix e verificare il log

systemctl disable postgresql-16

systemctl start zabbix-server
tail -f /var/log/zabbix/zabbix_server.log

Pulizia dopo l’aggiornamento

Una volta verificato che Zabbix funziona correttamente sulla nuova versione di PostgreSQL, rimuovere i pacchetti della versione precedente e la relativa directory dati

dnf remove postgresql16-server postgresql16 timescaledb-2-postgresql-16
rm -rf /var/lib/pgsql/16/

Se è stato usato pg_upgrade, sono disponibili due script generati automaticamente nella home di postgres durante la migrazione. Il primo sostituisce il comando rm -rf manuale

sudo -u postgres /var/lib/pgsql/delete_old_cluster.sh

Il secondo aggiorna le statistiche del query planner sul nuovo cluster in quanto pg_upgrade trasferisce i dati ma non le statistiche

sudo -u postgres /var/lib/pgsql/analyze_new_cluster.sh

L’elenco degli articoli di questa serie può essere consultato qui