Per chi non lo conoscesse in dettaglio, Zabbix è formato, per la parte server, da tre componenti: il server vero e proprio (il software che esegue i controlli e i calcoli, scritto in C); il database, nel quale vengono salvati sia i dati di configurazione che quelli di monitoraggio (può essere MySQL/MariaDB o Postgres, più raramente Oracle) e il frontend, la parte grafica che permette l’accesso per la visualizzazione (scritta in PHP su webserver Apache o Nginx)
Se all’inizio le tre componenti possono stare su una singola macchina, fisica o virtuale, al crescere delle infrastrutture da monitorare è necessario separarle per migliorare le performance.
Il primo componente che di solito viene separato è il database, mantenendo frontend e server su una singola macchina. Resta inteso che, in situazioni di particolare grandezza o complessità, le tre componenti possono stare anche ognuna su un server differente.
La separazione dei componenti è spesso l’occasione per rendere più resistente l’infrastruttura creandone una in alta disponibilità.
A questo proposito esiste un bell’articolo di Edmund Vesmanis sul blog di Zabbix, tratto da una sua presentazione allo Zabbix Summit 2019. Lo potete trovare qua. https://blog.zabbix.com/zabbix-ha-cluster-setups/8264/
La soluzione descritta nell’articolo presenta, due punti a mio avviso rivedibili:
L’infrastruttura è esageratamente ridondante, prevedendo i tre componenti separati e, per ognuno di essi, tre VM, per un totale di nove server;
La replica tra i DB viene effettuata in maniera asincrona, quando usando MariaDB e Galera (software di clustering nativo) è possibile farla in maniera sincrona.
Ho quindi pensato di procedere alla realizzazione di un cluster di soli quattro nodi, due per server e frontend (assieme) e due per il DB con MariaDB/Galera.
Ogni gruppo di server avrà tre IP: due fisici, assegnati alle vm che compongono il cluster e un VIP gestito dal software di alta disponibilità.
I sistemi sono tutti Ubuntu Bionic (18.04)
Cluster Zabbix server-frontend:
Nodo 1: 10.32.2.55
Nodo 2: 10.32.2.49
VIP: 10.32.2.52
Cluster DB
Nodo 1: 10.32.4.17
Nodo 2: 10.32.4.20
VIP: 10.32.4.18
Prima di tutto editiamo i file /etc/hosts dei singoli nodi, inserendo nome e IP dei due nodi che compongono il cluster, ad esempio come in questo esempio:
10.32.4.13 zabbix-db-p01 10.32.4.14 zabbix-db-p02
Iniziamo dall’installazione del DB.
Aggiungiamo la chiave del repository:
apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
Poi il repository vero e proprio e aggiorniamo:
add-apt-repository 'deb [arch=amd64,arm64,ppc64el] https://mirror.mva-n.net/mariadb/repo/10.5/ubuntu bionic main' apt update -y
Ora installiamo MariaDB e Galera
apt-get install mariadb-server rsync -y
Securizziamo l’installazione:
mysql_secure_installation
Cambiare la password e rispondere “Y” a tutte le altre risposte.
Ripetere i passi appena fatti sul nodo 2
Ora configuriamo Galera:
nano /etc/mysql/conf.d/galera.cnf
Inserire queste righe sul primo nodo:
[mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name="galera_cluster" wsrep_cluster_address="gcomm://10.32.4.17,10.32.4.20" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address="10.32.4.17" wsrep_node_name="zabbix-db-p01"
Ripetere le operazioni analogamente sul secondo nodo, cambiando le ultime due voci in fondo in accordo con i parametri della macchina (quelle che iniziano con “wsrep”).
Avviamo il cluster: per fare questo è necessario che MariaDB sia spento su tutti i nodi:
systemctl stop mysql
Andiamo sul nodo 1 e avviamo il cluster:
galera_new_cluster
Verifichiamo se il cluster funziona correttamente:
mysql -u root -p -e "show status like 'wsrep_cluster_size'"
Un output come questo denota il corretto funzionamento:
+———————–+——-+
| Variable_name | Value |
+———————–+——-+
| wsrep_cluster_size | 1 |
+————————+——+
Andiamo sul nodo 2 e avviamo MariaDB:
systemctl start mysql
Verifichiamo che il secondo nodo sia inserito nel cluster:
mysql -u root -p -e "show status like 'wsrep_cluster_size'"
Un output come questo denota il corretto funzionamento:
+———————–+——-+
| Variable_name | Value |
+———————–+——-+
| wsrep_cluster_size | 2 |
+————————+——+
Infine testiamo la replica del DB. Entriamo su MariaDB e creiamo un database:
mysql -u root -p MariaDB [(none)]> create database test_db; MariaDB [(none)]> show databases;
+——————–+
| Database |
+——————–+
| test_db |
+——————–+
Accediamo al secondo nodo e verifichiamo:
mysql -u root -p MariaDB [(none)]> show databases;
+——————–+
| Database |
+——————–+
| test_db |
+——————–+
La replica funziona correttamente.
Passiamo ora alla realizzazione del cluster HA per il database.
Installiamo i pacchetti:
apt install -y pcs corosync
Creiamo l’utente per il cluster e impostiamo la password
useradd hacluster
passwd <CLUSTER_PASSWORD>
Autentichiamo i nodi del cluster
pcs cluster auth NODI
username: hacluster
password: <CLUSTER_PASSWORD>
zabbix-ha-db1: Authorized
zabbix-ha-db2: Authorized
Creiamo il cluster
pcs cluster setup --name zabbix_db_cluster zabbix-db-p01 zabbix-db-p02 --force
Creiamo la risorsa IP
pcs resource create virtual_ip ocf:heartbeat:IPaddr2 \ ip=10.32.4.18 op monitor interval=5s −−group zabbix_db_cluster
Stoppiamo il cluster e facciamolo ripartire. Poi verifichiamo lo stato
pcs cluster stop −−all && pcs cluster start −−all pcs status
Impostiamo il blocco dello spostamento delle risorse dopo un ripristino. Poi disabilitiamo STONHIT
pcs resource defaults resource−stickiness=100 pcs property set stonith−enabled=false
A questo punto il cluster dei due nodi condivide l’IP inserito, che è quello che dovrà essere utilizzato per contattare il Database, composto di due nodi replicati tra di loro in maniera sincrona tramite Galera.
Passiamo ora al cluster dei due nodi con server e frontend
Prima di tutto inseriamo nel file /etc/hosts le seguenti righe
10.32.2.55 zabbix-mon-p01 10.32.2.49 zabbix-mon-p02
Passiamo ora alla realizzazione del cluster HA per il server/frontend.
Installiamo i pacchetti:
apt install -y pcs corosync
Creiamo l’utente per il cluster e impostiamo la password
useradd hacluster passwd <CLUSTER_PASSWORD>
Autentichiamo i nodi del cluster
pcs cluster auth NODI
username: hacluster
password: <CLUSTER_PASSWORD>
zabbix-ha-db1: Authorized
zabbix-ha-db2: Authorized
Creiamo il cluster
pcs cluster setup --name zabbix_server_cluster zabbix-mon-p01 zabbix-mon-p02 --force
Installiamo lo zabbix serve rsu entrambi i nodi:
yum install −y zabbix−server
Editiamo il file di configurazione (/etc/zabbix/zabbix_server.conf) modificando come segue le righe:
SourceIP=10.32.2.52 (IP del VIP)
DBHost=10.32.4.18 (VIP del cluster DB)
DBName=zabbix
DBUser=zabbix
DBPassword=<DB_ZABBIX_PASS>
Impostiamo il blocco dello spostamento delle risorse dopo un ripristino. Poi disabilitiamo STONHIT
pcs resource defaults resource−stickiness=100 pcs property set stonith−enabled=false
Riavviamo il cluster e controlliamo
pcs cluster stop −−all && pcs cluster start −−all pcs status
Ora passiamo alle risorse, iniziando dal VIP
pcs resource create virtual_ip_server ocf:heartbeat:IPaddr2 ip=10.32.2.52 op monitor interval=5s −−group zabbix_server_cluster
Poi lo Zabbix Server
pcs resource create ZabbixServer systemd:zabbix−server op monitor interval=10s −−group zabbix_server_cluster
Ultimi settaggi, per essere certi che il server Zabbix sia attivo su un solo nodo alla volta
pcs constraint colocation add virtual_ip_server ZabbixServer INFINITY −-force
Facciamo in modo che il server Zabbix parta sempre dopo il VIP
pcs constraint order virtual_ip_server then ZabbixServer
Impostiamo alcuni timeout
pcs resource op add ZabbixServer start interval=0s timeout=60s pcs resource op add ZabbixServer stop interval=0s timeout=120s
Riavviamo di nuovo e controlliamo
pcs cluster stop −−all && pcs cluster start −−all pcs status
A questo punto il server Zabbix è attivo sul cluster, su un nodo alla volta, connesso al cluster del DB MariaDB/Galera e utilizza il VIP come IP
Passiamo ora al front end, che condivide le stesse VM dello Zabbix server. Ovviamente sarebbe possibile (come fatto nell’articolo di Edmund) separare anche questa funzionalità e dedicare ad essa un paio di VM in un cluster dedicato, ma abbiamo preferito tenere basso il numero dei server coinvolti e accorparla con lo Zabbix server.
Iniziamo con l’installare il front end di Zabbix (Apache e PHP necessari per il funzionamento saranno installati automaticamente dal gestore di pacchetti)
apt install zabbix-web-mysql
Andiamo ad editare il file di configurazione del front end:
$DB['TYPE'] = 'MYSQL'; $DB['SERVER'] = '10.32.4.18'; <-- IP DEL CLUSTER MYSQL $DB['PORT'] = '0'; $DB['DATABASE'] = 'zabbix'; $DB['USER'] = 'zabbix'; $DB['PASSWORD'] = '<DB_ZABBIX_PASS>'; <-- PASSWORD DELL'UTENTE ZABBIX SUL DB ... $ZBX_SERVER = '10.32.2.52'; $ZBX_SERVER_PORT = '10051'; $ZBX_SERVER_NAME = 'ZABBIX-HA';
Per controllare lo stato di Apache creiamo un virtualhost che ci mostri la pagina server-status.
Abilitiamo il modulo:
a2enmod server-status
Poi creiamo nella directory sites available un file denominato serverstatus.conf:
Listen 8080 <VirtualHost *:8080> DocumentRoot "/var/www/html" #ServerName localhost <IfModule mod_status.c> <Location /server-status> SetHandler server-status Order deny,allow Allow from all </Location> </IfModule> <Directory "/var/www/html"> #allow from all #Options None #Require all granted AllowOverride All DirectoryIndex index.html </Directory> </VirtualHost>
Forziamo Apache a rispondere sull’IP del VIP. Editiamo il file /etc/apache2/ports.conf con questa modifica:
Listen 10.32.2.52:80
Poiché il frontend condividele risorse con lo Zabbix server sarà sufficiente aggiungere una risorsa al cluster esistente:
pcs resource create zabbix_fe ocf:heartbeat:apache configfile=/etc/apache2/apache2.conf \ statusurl="http://localhost:8080/server-status" op monitor interval=30s --group zabbix_server_cluster
Forziamo il frontend a stare sullo stesso nodo del VIP
pcs constraint colocation add virtual_ip_server zabbix-fe INFINITY --force
Il front end deve partire dopo lo Zabbix Server:
pcs constraint order virtual_ip_server then zabbix-fe
Infine due timeout:
pcs resource op add zabbix_fe start interval=0s timeout=60s pcs resource op add zabbix_fe stop interval=0s timeout=120s
Ora anche il frontend è gestito dal cluster in HA
Attenzione: i servizi gestiti dal cluster vanno disabilitati da systemd (sysctl disable apache2 zabbix-server) perché deve essere il cluster a gestirne l’avvio.
L’ultima cosa che rimane da fare è la sincronizzazione di alcuni file (script e files di configurazione) tra i due nodi. Per risolvere il problema ho fatto uno script che tramite rsync e ssh copia dal nodo 1 al 2 questi oggetti:
- directory /usr/lib/zabbix (che contiene gli script per l’alerting e gli external check)
- directory /var/lib/zabbix (che contiene altre configurazioni aggiuntive)
- file /etc/zabbix/zabbix_server.conf
Lo script gira con cron ogni 8 ore con l’utente root (previo scambio delle chiavi SSH tra il nodo 1 e il 2)
Il sistema di alta disponibilità ha anche un’interfaccia grafica, raggiungibile all’indirizzo <IP_DEL_NODO:2224> con utente hacluster e password <CLUSTER_PASSWORD>