Zabbix – Send alerts to Slack

Today I’ve configured my Zabbix Server to automatically send alerts to the #alerting channel of my slack team.

To to this, you have to create un new Incoming WebHook in your slack Team.

  • Click on your team, select App and Integration.
  • Search for Incoming Webhook
  • Click « Add a configuration »
  • Configure the webhook with the default destination topic, etc..
  • Copy the generated URL in your clipboard, you will need it later. The webhook url is something like https://hooks.slack.com/services/ABCDEFGHIJKJMNOPQRSTUVWXYZ

Next Go to your Zabbix Server.

Edit the /etc/zabbix/zabbix_server.conf file to specify a correct Path for AlertScriptPath, for example :

AlertScriptsPath=/usr/share/zabbix/alertscripts

Then go to the /usr/share/zabbix/alertscripts directory and create a tiny shell script post_to_slack.sh :

#!/bin/sh

webhook_url=$1
message=$2

curl -k -X POST -d "payload={\"username\":\"zabbix\", \"text\":\"$message\"}" $webhook_url

Then Go to The Zabbix IHM and add a new media type of type script, with the script name you created before (Administration > Media Types > create media type)

Add 2 parameters for your script :

  1. The first one is the Slack Webhook URL you generated in step 1,
  2. the second is the Alert Subject.

Then, Configure a Zabbix Actions (Configuration > Actions) to send a message to slack media for the admin user.

Set a correct Subject message to get all the information you need. For example :

[{HOST.HOST}] {TRIGGER.SEVERITY}: {TRIGGER.NAME}

Finaly edit the Zabbix admin user and add a new media of type slack.

That’s It !

Now all your Zabbix Alerts are sent to your slack #alerting Channel \o/

PS : You can configure multiple slack media type to send alerts to multiple webhooks, according to the Host group.

 

 

Ansible pour déployer des agents Zabbix + auto-registration

ansible_logo-360x288+ zabbix_logo_500x131

Depuis quelques temps, j’utilise Ansible au boulot, et je doit dire c’est un outil super classe !

Je vais décrire ici comment déployer des agents Zabbix sur un ensemble de serveurs grâce à Ansible.

Rôle zabbix_agent

Voici le playbook zabbix_agent :

zabbix_agent.yml

---
- hosts: all:!localhost

  roles:
    - role: zabbix_agent

roles/zabbix_agent/task/main.yml

---
- name: "[zabbix_agent - linux] Installation agent zabbix"
  yum: name={{ item }} state=present
  with_items:
    - "zabbix-2.4.2-1.el6.x86_64.rpm"
    - "zabbix-agent-2.4.2-1.el6.x86_64.rpm"
  sudo: yes

- name: "[zabbix_agent - linux] Configuration de l'agent zabbix"
  template:
    src: "etc/zabbix/zabbix_agentd.conf.j2"
    dest: "/etc/zabbix/zabbix_agentd.conf"
    mode: 0644
  register: zabbix_config_updated
  sudo: yes


- name: "[zabbix_agent - linux] Demarrage de l'agent"
  service: name="zabbix-agent" state="restarted"
  when: zabbix_config_updated|changed
  sudo: yes

Il est bien sur possible d’étendre ce rôle pour qu’il puisse déployer des agents sur d’autres types de serveur (debian, aix, etc..)

roles/zabbix_agent/templates/etc/zabbix/zabbix_agentd.conf.j2

---
LogFileSize=0
Server={{ zabbix_server }}
ServerActive={{ zabbix_server }}
Hostname={{ inventory_hostname }}
HostMetadata={{ zabbix_metadata if zabbix_metadata is defined else "" }},{{ ansible_system }}
Include=/etc/zabbix/zabbix_agentd.d/

roles/zabbix_agent/vars/main.yml

---
zabbix_server: "IP DU SERVEUR ZABBIX"

Configuration Zabbix

Host Groups

Il faut d’abord créer des hosts groups dans Zabbix pour pouvoir « ranger » les équipements.
Par exemple, créer un host group « Recette » dans lequel on va ranger tous les serveurs de recette.

Actions

Une étape indispensable avant de lancer le playbook zabbix_agent est de configurer les règles d’auto-registration dans Zabbix.
Pour cela, aller dans le menu Config->Actions et sélectionner « auto-registration » dans le menu déroulant.
Puis, cliquer sur créer une nouvelle règle.

Dans le premier onglet Action, choisir un nom sympa pour cette règle. Par exemple « Linux auto-registration Recette »
Dans le second onglet Conditions, choisir les options « host metadata » like « recette » et host metadata like « linux »
Dans le troisième onglet Operations, choisir :

  • Add Host
  • Add host to host group Recette
  • Link host to template « Template OS Linux »

Lancement du playbook

Enfin, il ne reste plus qu’à lancer le playbook zabbix_agent en lui spécifiant le fichier d’inventaire de recette et les options zabbix_metadata qui vont bien :

ansible-playbook zabbix_agent.yml -i inventory/recette --extra-vars="zabbix_metadata=Recette"

Et voila !
Si tout se passe bien ansible va déployer un agent zabbix sur le serveur, configurer celui-ci avec la bonne IP du serveur zabbix et les méta données qu’on a fourni en paramètres.
Ensuite, le serveur Zabbix va auto ajouter les équipements en les classant dans les bons groupes et y associer les bons templates.

Petite astuce :
* Ne pas hésiter à créer plein de groupes zabbix pour ranger les équipements (un host peut bien évidement appartenir à plusieurs groupes)
* Utiliser le bouton « Cloner » dans la configuration des actions pour créer plein de règles en fonction des méta données (Linux + Recette, Aix + Recette, Linux + Préprod, Aix + Préprod, Linux + préprod + backup, etc…)

Provisionning Zabbix en Perl

zabbix
Juste un petit script pratique que j’avais développé il y a quelques temps pour provisionner un Zabbix en utilisant l’API Zabbix en perl :

Ça s’utilise super facilement :

perl add-host-to-zabbix.pl [long options...]
        --host               host
        --group              Specify the host group.
        --template           Link a template to this host.
        --interface          add an interface to host (format :
                             "type:ip:dns:useip:port:main",
                where type can
                             be 1 for AGENT, 2 for SNMP, 3 for JMX or 4 for
                             IPMI)
        --csv                CVS file to load. The format should be like

                "host:groups (comma separated):templates
                             (comma
                             separated):interface-type:interface-ip:interface-dns:useip:interface-port:main"
        --zabbix-config      where to find the Zabbix::API configuration file.
        --l4p-config         Log::Log4perl configuration file

Il faut avoir un fichier de conf zabbix avec les identifiants pour se connecter au zabbix que l’on fourni avec l’option –zabbix :

host: http://127.0.0.1/zabbix
user: apiuser
password: apipass

Bref, ça peut être utile pour des gens qui bossent sur Zabbix et qui ne veulent pas se prendre la tête a ajouter tous les équipements 1 par 1.

Reportings Zabbix avec Jasper

zabbixJasper studio
Aujourd’hui au boulot, je leur ai proposé de faire des rapport sur l’utilisation de Zabbix via l’outil Open source Jasper.
Je vais donc décrire ici les différentes étapes permettant de générer de beaux rapports Jasper pour Zabbix !
J’utilise pour cela jasper Studio en version community (la version open source gratuite).

    • Etape 1 : Création du rapport

On va d’abord créer un nouveau rapport Jasper, ainsi qu’un Data Adapter (une connexion a la base de données).
On va utiliser pour cela une connexion jdbc. Il faut alors télécharger le connecteur jdbc correspondant à notre type de base de données (Mysql / Postgres / Oracle, etc..) et renseigner l’url de connexion (ici posgtresql):
JDBC Driver : org.postgresql.Driver
JDBC url : jdbc:postgresql:///zabbix
Username : zabbix
Password :

Attention, il ne faut pas oublier d’ajouter le répertoire dans lequel est stocké le Driver jdbc .jar dans l’onget « Driver Classpath », sinon, ça ne marchera pas.
DataAdapter

    • Etape 2 : Création du Data Set principal

Ensuite, on va créer le Data Set principal, qui servira a dérouler l’ensemble du rapport.
On sélectionne pour cela le Data Adpater que l’on a créé précédemment et on écrit la requête principale pour le rapport.
Voici ce que j’ai mis pour pouvoir lister toutes les alertes Acquittées pendant la semaine :

SELECT DISTINCT
   h.name as host,
   g.name as host_group,
   t.description as trigger,
   a.message,
   u.alias
FROM 
    groups g,
    hosts_groups hg,
    hosts h,
    triggers t,
    items i,
    functions f,
    events e,
    acknowledges a,
    users u
WHERE 
    AND g.groupid = hg.groupid
    AND hg.hostid = h.hostid
    AND e.objectid = t.triggerid
    AND t.triggerid = f.triggerid
    AND f.itemid = i.itemid
    AND i.hostid = h.hostid
    AND e.eventid = a.eventid
    AND a.userid = u.userid
    AND e.value = 1 
    AND TIMESTAMP 'epoch' + e.clock * INTERVAL '1 second' BETWEEN $P{date_start} AND $P{date_end}
ORDER BY g.name, h.name, t.description

DataSet1

Il faut également penser à ajouter les 2 paramètres date_start et date_end de type java.util.Date dans l’onglet parameters.

    • Etape 3 : Layout

Ensuite, on commence par faire un peut de mise en page, avec un titre, un logo, et les dates de début et fin du rapport. J’ai mis un tableau pour contenir le Top 10 des alertes générées, ainsi qu’un camembert pour avoir la répartition des alertes par host.
Ensuite dans les Entêtes de Groupe, de Host, on place les champs $F{host_group} et $F{host} de la requête principale.
Et dans la zone Detail, j’ai mis 3 colonnes avec le nom du trigger, le message d’acquittement et le nom du user qui a acquitté l’alerte.

layout

    • Etape 4 : Top 10 des Triggers

Pour le Top 10 des alertes, voici ma requête SQL, qu’il faut placer dans un nouveau Data Set :

SELECT 
	count(DISTINCT e.eventid) as nb, 
	h.hostid,
	h.name as host,
	t.triggerid,
	t.description
 FROM 
 	events e
 		INNER JOIN triggers t ON t.triggerid = e.objectid
 		INNER JOIN functions f ON t.triggerid = f.triggerid
 		INNER JOIN items i ON i.itemid = f.itemid
 		INNER JOIN hosts h ON h.hostid = i.hostid
 WHERE 
 	e.source = 0 
 	AND e.value = 0 
 	AND h.status = 0
 	AND t.status = 0
 	AND TIMESTAMP 'epoch' + e.clock * INTERVAL '1 second' BETWEEN $P{date_start} AND $P{date_end}
 GROUP BY 
 	h.hostid, h.name, t.triggerid, t.description
ORDER BY nb DESC
LIMIT 10;

Ici aussi, il ne faut pas oublier d’ajouter les parametres date_start et date_end dans l’onglet parameters.

    • Etape 5 : Cammembert

Et pour le Pie Chart (le cammembert), j’ai utlisé la requête SQL suivante (encore dans un nouveau Data Set :

SELECT
    count(DISTINCT e.eventid) as nb,
    h.name as host
FROM
    events e
    INNER JOIN triggers t ON t.triggerid = e.objectid
    INNER JOIN functions f ON t.triggerid = f.triggerid
    INNER JOIN items i ON i.itemid = f.itemid
    INNER JOIN hosts h ON h.hostid = i.hostid
    INNER JOIN hosts_groups hg ON hg.hostid = h.hostid
    INNER JOIN groups g ON g.groupid = hg.groupid
WHERE
    e.source = 0
    AND e.value = 1
    AND h.status = 0
    AND t.status = 0
    AND TIMESTAMP 'epoch' + e.clock * INTERVAL '1 second' BETWEEN $P{date_start} AND $P{date_end}
GROUP BY h.hostid,h.name;

Ici aussi, il ne faut pas oublier d’ajouter les paramètres date_start et date_end dans l’onglet parameters.

Libre a vous d’ajouter des filtre par host group, par user group ou whatever..

    • Etape 6 : Mapping des paramètres

Enfin, il ne reste plus qu’a mapper les paramètres de la requête principale dans les Data Set secondaires pour qu’ils soient pris en compte partout. Pour cela, on sélectionne Paramètre dans le menu en bas à droite du tableau ou dans le formulaire Wizard du camembert.
il faut alors associer date_start à $P{date_start} et date_end à $P{date_end}

parameters

Et voilà ! Il ne reste plus qu’a prévisualiser le tout pour vérifier que cela fonctionne (en général, on a au moins 3 ou 4 java.WTF.Exception) et il faut s’y reprendre a plusieurs fois avant d’arriver a faire marcher le truc.

  • Dernière étape : Automatisation !!/li>Comme j’ai pas envie de me prendre la tête avec un jasper Server, et que j’ai juste besoin de lancer mon rapport une fois par semaine, j’ai téléchargé jasperstarter que j’ai installé sur le serveur ou il y a la BDD et il suffit ensuite de le cronner avec les bons paramètres !

    Voici les lignes de commande que j’utilise pour compiler et générer le rapport :
    Compilation :

    ./jasperstarter/bin/jasperstarter compile path/to/zabbix_A4.jrxml

    Génération :

    ./jasperstarter/bin/jasperstarter process path/to/zabbix_A4.jasper -t postgres -H 127.0.0.1 -u zabbix -p password -n zabbix --db-port 5432 -f pdf -P date_start=2014-02-24 date_end=2014-02-31

    Et voila, on obtient un beau PDF avec plein de stats dedans !