doc:appunti:linux:sa:cacti_122
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| doc:appunti:linux:sa:cacti_122 [2019/07/26 11:33] – [Notifiche] niccolo | doc:appunti:linux:sa:cacti_122 [2022/10/10 16:27] (current) – [Monitoraggio servizio CLAMD] niccolo | ||
|---|---|---|---|
| Line 17: | Line 17: | ||
| Spine accede direttamente al database, controllare i parametri di accesso in **/ | Spine accede direttamente al database, controllare i parametri di accesso in **/ | ||
| - | FIXME: L' | + | **ATTENZIONE**: L' |
| ==== SNMP timeout detected [500 ms], ignoring host ==== | ==== SNMP timeout detected [500 ms], ignoring host ==== | ||
| Line 23: | Line 24: | ||
| Pare che la soluzione sia quella di allungare il **SNMP Timeout** nella configurazione di ciascun host. Per dispositivi raggiungibili tramite connessione DSL, che possono essere interessati da congestioni di traffico e picchi di carico elevati (utilizzo della CPU prossimo al 100%) può essere necessario portare il timeout anche intorno ai **15000 ms** (15 secondi). | Pare che la soluzione sia quella di allungare il **SNMP Timeout** nella configurazione di ciascun host. Per dispositivi raggiungibili tramite connessione DSL, che possono essere interessati da congestioni di traffico e picchi di carico elevati (utilizzo della CPU prossimo al 100%) può essere necessario portare il timeout anche intorno ai **15000 ms** (15 secondi). | ||
| + | |||
| + | FIXME Non è chiaro come mai con il **poller Spine** gli errori **SNMP Timeout** sono frequentissimi; | ||
| + | |||
| + | < | ||
| + | SPINE: Poller[1] ... WARNING: SNMP timeout detected [60000 ms], ignoring host ... | ||
| + | </ | ||
| + | |||
| + | Impostando invece il **poller cmd.php** tali errori scompaiono. | ||
| ===== Icinga 2 ===== | ===== Icinga 2 ===== | ||
| Line 33: | Line 42: | ||
| * **Database per Icinga Web 2**. Utilizzato dall' | * **Database per Icinga Web 2**. Utilizzato dall' | ||
| - | Si devono installare i seguenti pacchetti: | + | Si devono installare i seguenti pacchetti |
| + | * **postgresql** | ||
| * **icinga2** | * **icinga2** | ||
| * **icingaweb2** | * **icingaweb2** | ||
| Line 129: | Line 139: | ||
| === Monitoring e database IDO === | === Monitoring e database IDO === | ||
| + | |||
| + | Il modulo // | ||
| + | |||
| + | Se la procedura di installazione fallisce (ad esempio perché durante l' | ||
| Quando la procedura web configura il **modulo Monitoring** si devono indicare le coordinate del backend IDO creato durante l' | Quando la procedura web configura il **modulo Monitoring** si devono indicare le coordinate del backend IDO creato durante l' | ||
| Line 190: | Line 204: | ||
| </ | </ | ||
| + | ==== Monitoraggio di un servizio TCP/IP standard ==== | ||
| + | |||
| + | In questo esempio aggiungiamo il monitoraggio di un servizio standard **POP3** sulla porta 110 TCP. | ||
| + | |||
| + | Per prima cosa si definisce un **CheckCommand** nel file **/ | ||
| + | |||
| + | < | ||
| + | object CheckCommand " | ||
| + | command = [ PluginDir + "/ | ||
| + | arguments = { | ||
| + | " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Il comando si basa su uno dei plugin standard forniti dal pacchetto **monitoring-plugins-basic**, | ||
| + | |||
| + | Quindi si definisce un servizio di nome **POP3 Service** basato sul comando appena definito; nel file **/ | ||
| + | |||
| + | < | ||
| + | apply Service "POP3 Service" | ||
| + | import " | ||
| + | check_command = " | ||
| + | check_interval = 5m | ||
| + | assign where host.vars.pop_server | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Da notare che il nome del servizio verrà usato nella visualizzazione di IcingaWeb, pertanto si usa qualcosa di descrittivo e comprensibile. Considerato che il template **generic-service** ha un **check_interval** di un solo minuto, si è preferito rilassare il controllo ad un intervallo di **cinque minuti**. | ||
| + | |||
| + | Infine si deve attivare il servizio per l'host desiderato: è sufficiente definire la variabile **pop_server** che sarà anche usata dal plugin come indirizzo remoto da testare. La definizione degli host è generalmente contenuta nel file **/ | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | ... | ||
| + | vars.pop_server = " | ||
| + | </ | ||
| ==== Monitoraggio client remoto via NRPE ==== | ==== Monitoraggio client remoto via NRPE ==== | ||
| Line 242: | Line 294: | ||
| </ | </ | ||
| + | ==== CheckCommand con parametri opzionali ==== | ||
| + | |||
| + | Si è avuto un caso particolare in cui il **server NRPE versione 2.15** (in esecuzione sull' | ||
| + | |||
| + | < | ||
| + | nrpe[9169]: Error: Could not complete SSL handshake. | ||
| + | </ | ||
| + | |||
| + | È stato necessario avviare il server NRPE con l' | ||
| + | |||
| + | < | ||
| + | object CheckCommand " | ||
| + | command = [ PluginDir + "/ | ||
| + | arguments = { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | È sufficiente definire la variabile opportuna nella sezione host: | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | address = " | ||
| + | vars.nrpe_swraid = " | ||
| + | vars.nrpe_no_ssl = true | ||
| + | } | ||
| + | </ | ||
| ===== Check passivo ===== | ===== Check passivo ===== | ||
| Normalmente Icinga 2 effettua **check attivi**, cioè interroga l'host remoto per conoscere lo stato di una specifica grandezza ed agire di consegunza. Se l'host remoto è dietro a un firewall o comunque non è possibile conoscerne lo stato con un check diretto, è possibile utilizzare i **check passivi**, cioè è l'host remoto che informa il server Icinga 2 sul proprio stato. | Normalmente Icinga 2 effettua **check attivi**, cioè interroga l'host remoto per conoscere lo stato di una specifica grandezza ed agire di consegunza. Se l'host remoto è dietro a un firewall o comunque non è possibile conoscerne lo stato con un check diretto, è possibile utilizzare i **check passivi**, cioè è l'host remoto che informa il server Icinga 2 sul proprio stato. | ||
| - | Utilizzeremo una configurazione | + | Nel nostro caso si vuole monitorare l'**esecuzione di un backup** su un host remoto. Il monitoraggio deve accorgersi non solo di un eventuale errore, ma anche della mancata esecuzione, per questo si utilizza una combinazione di **check passivi** |
| - | Anzitutto | + | * In condizioni normali l'host remoto esegue il backup e notifica Icinga 2 con un **check passivo**. |
| + | * Se l'host Icinga 2 non riceve il check passivo, esegue un **check attivo** //dummy// che restituisce lo stato 3 UNKNOWN. | ||
| + | |||
| + | Il check passivo utilizza il meccanismo **[[https:// | ||
| + | |||
| + | Per qusto si deve abilitare l' | ||
| Si verifica le //feature// abilitate, si abilita la //command// e si ricarica il servizio: | Si verifica le //feature// abilitate, si abilita la //command// e si ricarica il servizio: | ||
| Line 262: | Line 350: | ||
| < | < | ||
| template Service " | template Service " | ||
| - | | + | |
| - | check_command = " | + | check_command = " |
| - | enable_active_checks = false | + | /* Do active checks to detect missing passive updates. */ |
| - | enable_passive_checks = true | + | |
| - | check_interval = 1d | + | enable_passive_checks = true |
| - | | + | /* Use a runtime function to retrieve the last check time and more details. */ |
| - | max_check_attempts = 1 | + | vars.dummy_text = {{ |
| + | var service = get_service(macro(" | ||
| + | var lastCheck = DateTime(service.last_check).to_string() | ||
| + | return "No check results received. Last result time: " + lastCheck | ||
| + | }} | ||
| + | | ||
| + | | ||
| + | max_check_attempts = 3 /* Retry the active check some times, before notification. */ | ||
| + | vars.notification_interval = 1d | ||
| } | } | ||
| </ | </ | ||
| - | Da notare che lo stato viene controllato una sola volta al giorno (**check_interval = 1d**), in caso di problemi | + | Il // |
| + | |||
| + | In condizioni normali viene ricevuto un **check passivo** ogni 24 ore, quindi il check attivo giornaliero (// | ||
| - | Quindi si definisce un servizio associato ad un host, ad esempio nel file **/ | + | Per definire il servizio associato ad un host si aggiunge |
| < | < | ||
| Line 290: | Line 388: | ||
| Il timestamp in formato Unix si può ottenere da una shell Unix con il comando **%%date +%s%%**. | Il timestamp in formato Unix si può ottenere da una shell Unix con il comando **%%date +%s%%**. | ||
| + | |||
| + | La ricezione di un check passivo viene registrata nel log **/ | ||
| + | |||
| + | < | ||
| + | [2022-02-22 02:49:04 +0100] information/ | ||
| + | Executing external command: [1645494544] PROCESS_SERVICE_CHECK_RESULT; | ||
| + | Backup Maildir; | ||
| + | rsync Maildir da Santorini a Naxos eseguito con successo. | ||
| + | </ | ||
| + | |||
| + | ==== Ricezione check passivo via REST API ==== | ||
| + | |||
| + | Si verifica che la **[[# | ||
| + | |||
| + | Nel file **/ | ||
| + | |||
| + | < | ||
| + | // Used to submit passive checks results, e.g. from backup scripts. | ||
| + | object ApiUser " | ||
| + | password = " | ||
| + | permissions = [ " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Il client che deve inviare l' | ||
| + | |||
| + | <code bash> | ||
| + | ICINGA2_SERVER=' | ||
| + | ICINGA2_USER=' | ||
| + | ICINGA2_PASSWORD=' | ||
| + | |||
| + | SERVICE_HOST=' | ||
| + | SERVICE_NAME=" | ||
| + | EXIT_STATUS=" | ||
| + | EXIT_MESSAGE=" | ||
| + | |||
| + | curl -k -s -u " | ||
| + | -H ' | ||
| + | -X POST " | ||
| + | -d '{ " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | </ | ||
| + | |||
| + | Un servizio Icinga può essere in uno dei seguenti stati: | ||
| + | |||
| + | ^ 0 | OK | | ||
| + | ^ 1 | WARNING | ||
| + | ^ 2 | CRITICAL | ||
| + | ^ 3 | UNKNOWN | ||
| ==== Server NSCA ==== | ==== Server NSCA ==== | ||
| + | |||
| + | :!: **ATTENZIONE**: | ||
| Nell' | Nell' | ||
| Line 367: | Line 518: | ||
| Nel nostro caso la mail **%%root@localhost%%** viene inoltrata a chi di dovere tramite **/ | Nel nostro caso la mail **%%root@localhost%%** viene inoltrata a chi di dovere tramite **/ | ||
| + | |||
| + | Nel file **/ | ||
| + | |||
| + | < | ||
| + | apply Notification " | ||
| + | import " | ||
| + | user_groups = host.vars.notification.mail.groups | ||
| + | users = host.vars.notification.mail.users | ||
| + | ... | ||
| + | assign where host.vars.notification.mail | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Nello stesso file - con una sintassi praticamente identica - viene abilitata la notifica anche **per ogni servizio** che abbia definito la **host.vars.notification.mail**: | ||
| + | |||
| + | < | ||
| + | apply Notification " | ||
| + | import " | ||
| + | user_groups = host.vars.notification.mail.groups | ||
| + | users = host.vars.notification.mail.users | ||
| + | ... | ||
| + | assign where host.vars.notification.mail | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Quindi - definendo tale variabile per un host - si ottiene come risultato di ricevere notifiche per tutti gli eventi associati a tale **host** e per tutti gli eventi legati ai **servizi** che dipendono dallo stesso. Questa è la sintassi: | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | address = " | ||
| + | ... | ||
| + | vars.notification.mail = { | ||
| + | users = [ " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Frequenza delle notifiche ==== | ||
| + | |||
| + | L' | ||
| + | |||
| + | < | ||
| + | apply Notification " | ||
| + | ... | ||
| + | interval = 4h | ||
| + | } | ||
| + | |||
| + | apply Notification " | ||
| + | ... | ||
| + | interval = 8h | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Si può personalizzare l' | ||
| + | |||
| + | < | ||
| + | apply Notification " | ||
| + | import " | ||
| + | user_groups = host.vars.notification.mail.groups | ||
| + | users = host.vars.notification.mail.users | ||
| + | if (service.vars.notification_interval) { | ||
| + | interval = service.vars.notification_interval | ||
| + | } else { | ||
| + | interval = 12h | ||
| + | } | ||
| + | assign where host.vars.notification.mail | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Come si vede l' | ||
| + | |||
| + | < | ||
| + | apply Service " | ||
| + | import " | ||
| + | check_command = " | ||
| + | check_interval = 15m | ||
| + | vars.notification_interval = 1d | ||
| + | assign where host.vars.nrpe_swraid | ||
| + | } | ||
| + | </ | ||
| + | ===== Notifica custom su Host ===== | ||
| + | |||
| + | Vediamo come predisporre le notifiche per un singolo host inviando una mail ad un determinato indirizzo. Si crea un file (ad esempio **/ | ||
| + | |||
| + | < | ||
| + | apply Notification " | ||
| + | import " | ||
| + | users = host.vars.notification.mailcustomer.users | ||
| + | times.begin = 3h | ||
| + | interval = 12h | ||
| + | assign where host.vars.notification.mailcustomer | ||
| + | } | ||
| + | |||
| + | object User " | ||
| + | import " | ||
| + | display_name = "Alert for ADSL 1" | ||
| + | email = " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Le notifiche inizieranno solo **dopo 3 ore** che l'host ha il problema, e verranno ripetute **ogni 12 ore**. Quindi è sufficiente aggiungere una riga alla definizione dell' | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | address = " | ||
| + | vars.notification.mailcustomer = { users = [ " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Modifica servizi predefiniti ===== | ||
| + | |||
| + | Potrebbe essere necessario fare delle modifiche ai servizi predefiniti. Ad esempio il servizio **ping4** viene applicato ad ogni host che abbia un **address**, | ||
| + | |||
| + | I file che definiscono i servizi sono in **/ | ||
| + | |||
| + | Nel file **/ | ||
| + | |||
| + | Nel file **/ | ||
| + | |||
| + | < | ||
| + | template CheckCommand " | ||
| + | vars.ping_wrta = 160 | ||
| + | vars.ping_wpl = 18 | ||
| + | vars.ping_crta = 320 | ||
| + | vars.ping_cpl = 36 | ||
| + | } | ||
| + | |||
| + | object CheckCommand " | ||
| + | import " | ||
| + | import " | ||
| + | command += [ " | ||
| + | vars.ping_address = " | ||
| + | } | ||
| + | |||
| + | object CheckCommand " | ||
| + | import " | ||
| + | import " | ||
| + | command += [ " | ||
| + | vars.ping_address = " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | poi si modifica il **Service " | ||
| + | |||
| + | < | ||
| + | apply Service " | ||
| + | import " | ||
| + | |||
| + | if (host.vars.ping_slow) { | ||
| + | check_command = " | ||
| + | } else { | ||
| + | check_command = " | ||
| + | } | ||
| + | | ||
| + | assign where host.address | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Per applicare il ping modificato sarà sufficiente definire la variabile **ping_slow** nella definizione di host: | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | ... | ||
| + | vars.ping_slow = true | ||
| + | } | ||
| + | </ | ||
| + | ===== Controllo hostalive e IPv6 ===== | ||
| + | |||
| + | Per ogni host viene effettuato un controllo **check_command = hostalive**, | ||
| + | |||
| + | Si tratta di due controlli indipendenti per cui può accadere che il **ping6** sia disabilitato (basta non definire l'// | ||
| + | |||
| + | Per evitare questa situazione si deve sostituire **hostalive** con **hostalive4** nel template // | ||
| + | |||
| + | ===== Porta TCP alternativa per servizio standard ===== | ||
| + | |||
| + | Il servizio predefinito **ssh** viene applicato a tutti gli host che anno **vars.os = Linux** e si basa ovviamente sulla **porta 22 TCP**. Per fare il test su una porta alternativa si deve definire un servizio personalizzato: | ||
| + | |||
| + | < | ||
| + | apply Service " | ||
| + | import " | ||
| + | check_command = " | ||
| + | vars.ssh_port = 2222 | ||
| + | assign where (host.address || host.address6) && host.vars.os == " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== VirtualHost con SSL ===== | ||
| + | |||
| + | Per monitorare il funzionamento basico di un server web è sufficiente definire una variabile **vars.http_vhosts** in una sezione **object Host**: | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | address = " | ||
| + | vars.http_vhosts[" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Il nome tra parentesi quadre è solo una label utilizzata per identificare il servizio nell' | ||
| + | |||
| + | Per un moderno server web tuttavia è necessario verificare la scadenza del certificato SSL ed eventualmente verificare diversi **VirtualHost** che condividono lo stesso indirizzo IP, ma hanno **ServerName** e **certificati SSL** diversi. | ||
| + | |||
| + | In teoria non sarebbe possibile **verificare il certificato SSL di un VirtualHost basato su nome**, perché nella fase iniziale della negoziazione SSL il nome dell' | ||
| + | |||
| + | Ammettendo che il server web sia configurato opportunamente, | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | import " | ||
| + | address = " | ||
| + | vars.http_vhosts[" | ||
| + | http_address = " | ||
| + | http_vhost = " | ||
| + | http_ssl = true | ||
| + | http_sni = true | ||
| + | http_certificate = " | ||
| + | } | ||
| + | vars.http_vhosts[" | ||
| + | http_address = " | ||
| + | http_vhost = " | ||
| + | http_ssl = true | ||
| + | http_sni = true | ||
| + | http_certificate = " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Each **vars.http_vhosts** section correspond to one command invokation, of this type: | ||
| + | |||
| + | < | ||
| + | check_http -H " | ||
| + | </ | ||
| + | |||
| + | ===== Monitoraggio servizio CLAMD ===== | ||
| + | |||
| + | Il programma antivirus **[[http:// | ||
| + | |||
| + | Per impostazione predefinita clamd **non** si mette in ascolto sulla porta **TCP 3310**, è necessario aggiungere queste righe alla configurazione: | ||
| + | |||
| + | < | ||
| + | # Listen also on TCP localhost, to allow running status check. | ||
| + | TCPSocket 3310 | ||
| + | TCPAddr 127.0.0.1 | ||
| + | </ | ||
| + | |||
| + | Il binding viene fatto solo su // | ||
| + | |||
| + | < | ||
| + | command[check_clamd]=/ | ||
| + | </ | ||
| + | |||
| + | Sul server Icinga2 si deve definire il **servizio** aggiungendo in **/ | ||
| + | |||
| + | < | ||
| + | apply Service "CLAMD Service" | ||
| + | import " | ||
| + | check_command = " | ||
| + | assign where host.vars.nrpe_clamd | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Quindi si aggiunge il comando aggiungendo in **/ | ||
| + | |||
| + | < | ||
| + | object CheckCommand " | ||
| + | command = [ PluginDir + "/ | ||
| + | arguments = { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Infine nella sezione **host** relativa all' | ||
| + | |||
| + | < | ||
| + | object Host " | ||
| + | ... | ||
| + | vars.nrpe_clamd = true | ||
| + | ... | ||
| + | } | ||
| + | </ | ||
| ===== Riferimenti Web ===== | ===== Riferimenti Web ===== | ||
| Line 372: | Line 809: | ||
| * **[[https:// | * **[[https:// | ||
| * **[[https:// | * **[[https:// | ||
| + | * **[[https:// | ||
doc/appunti/linux/sa/cacti_122.1564133634.txt.gz · Last modified: by niccolo
