Ok, sei que parece uma tema batido, antigo, que todos já sabem, mas ainda temos muitas empresas que estão no mercardo sem uma visão completa (parcial) do seu ambiente, sistemas e componentes e que ainda sofrem e somente são notificadas de problemas quando um usuário reclama diretamente ou pior ainda, nos tempos atuais nas redes sociais.
Existem diversas ferramentas de mercado, pagas com suporte com diversos recursos e muitas de código aberto sem custo de aquisição, mas que requerem algum trabalho de administração e customização, as pagas também tem e muitas vezes pagamos por algo que nunca é entregue.
Aqui vamos falar de uma de código aberto que amplamente utilizada, com diversos recursos que facilitam a vida dos administradores de sistemas, o Zabbix.
O que é Zabbix
Segundo o site oficial “Zabbix is professionally developed free and open-source software with no limits or hidden costs“, traduzindo ao pé da letra:
Zabbix é um software livre e de código aberto desenvolvido profissionalmente, sem limites ou custos ocultos
https://www.zabbix.com/features
Concordo, é livre e de código aberto e praticamente não existe limites do que podemos fazer com ele, basta um pouco de criatividade e um pouco de conhecimento do uso de API (Interface de Programação de Aplicativos) para conseguir extrair o melhor dele.
Existem diversos roteiros de instalação e em geral todos seguem a instalação da distribuição, eu só muito fã do Debian e seu padrão com o conjunto de comandos apt, e fortemente eu recomendo o seu uso.
Aqui vamos ter um outro foco, não vamos falar sobre a instalação e vamos ser mais práticos usando recursos que facilitam o dia-a-dia.
Basicamente
o Zabbix é formado por um servidor de banco de dados, um servidor da aplicação e um servidor web e podemos ter todos estes componentes no mesmo servidor instalado, mas um outro componente importante é Zabbix Proxy.
O proxy (Zabbix proxy) é um componente que atua como um recebedor e executor de comandos removendo a carga de executar as tarefas de consulta de estados e recebimento de eventos do servidor principal. Podemos ter proxies em diferentes redes, datacenter, namespaces, etc, ou seja, a definição do escopo é bem livre.

fonte: https://www.zabbix.com/forum/filedata/fetch?id=360921&d=1543849726
O trapper
O Zabbix Trapper é uma monitoração feita recebendo dados enviados ao invés de ir busca-los. (https://www.zabbix.com/documentation/current/pt/manual/config/items/itemtypes/trapper)
Simples, né?
Sim e extremamente barato sobre o custo do processamento e permite uma grande flexibilidade para os administradores e desenvolvedores criarem rotinas para monitorar os seus sistemas e componentes, pois pegamos um resultado esperado, criamos um template com items que receberão os eventos desejados, algo bem flexível e dinâmico.
Nesse site https://www.zabbix.com/documentation/current/pt/manual/config/items/itemtypes/trapper temos um exemplo prático de como preparar um template com um item do tipo trapper.
Aqui temos um pequeno exemplo de como monitorar a expiração de certificados web e notificar a expiração para o Zabbix:
#!/bin/sh
# lista de dominios com certificado
# zabbix
GRP_ID="67"
TEMPLATE_ID="10321"
DOMS=$(cat /usr/local/bin/monits/lista-dominios.txt)
# Variaveis gerais
LIMITDAY_WARN="60"
LIMITDAY_CRIT="30"
## Agente de envio
ZBXPRX="zbxtrapper01.intranet"
ZBXSND=$(which zabbix_sender)
PRX_ID="10334"
# criado o item no zabbix
fn_make_item()
{
JSON_AUTH=`mktemp --suffix=-ZABBIX-CERT-AUTH`
JSON_ITEM=`mktemp --suffix=-ZABBIX-CERT-ITEM`
# Endpoint do Zabbix
ZABBIX_API="http://zabbix.intranet/zabbix/api_jsonrpc.php"
# Usuari0 e senha no zabbix e rundeck
USER="svc_monit"
PASS="a_sua_senha" # recomendo o uso de um vault
cat > $JSON_AUTH <<END
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "$USER",
"password": "$PASS"
},
"id": 1,
"auth": null
}
END
# Fazendo o post e salvando o cookie
COOKIE=$(curl -s -i -X POST -H 'Content-Type:application/json' -d@$JSON_AUTH $ZABBIX_API | grep jsonrpc | jq -r .result)
# Agora criamos o item
cat > $JSON_ITEM <<END
{
"jsonrpc": "2.0",
"method": "host.create",
"params": {
"host": "$name",
"interfaces": [
{
"type": 1,
"main": 1,
"useip": 1,
"ip": "127.0.0.1",
"dns": "$name",
"port": "10050"
}
],
"groups": [
{
"groupid": "$GRP_ID"
}
],
"templates": [
{
"templateid": "$TEMPLATE_ID"
}
]
},
"id": 1,
"auth": "$COOKIE"
}
END
# Criando o item
curl -s -i -H 'Content-Type: application/json-rpc' -d@$JSON_ITEM $ZABBIX_API
sleep 1
# como zabbix nao tem criacao com o proxy - update na seq
WS_UPDATE="http://zabbix.intranet/zabbix-balancer/ws/update-zabbix-proxy.php"
# Executando o update
curl -s --data "proxy_hostid=$PRX_ID&host=$name" -X POST $WS_UPDATE
sleep 1
}
fn_send_zabbix()
{
MSG="$name IP - $endip exp $expiry_days dias - $LEVEL"
$ZBXSND -z $ZBXPRX -s $name -k validade_cert -o "$MSG"
}
fn_check_cert()
{
now_epoch=$( date +%s )
expiry_date=$( echo | openssl s_client -showcerts -servername $name -connect $endip:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2 )
echo -n " $expiry_date"
expiry_epoch=$( date -d "$expiry_date" +%s )
expiry_days="$(( ($expiry_epoch - $now_epoch) / (3600 * 24) ))"
if [ $expiry_days -lt $LIMITDAY_CRIT ]
then
LEVEL="CRIT"
fn_send_zabbix
elif [ $expiry_days -gt $LIMITDAY_CRIT ] && [ $expiry_days -lt $LIMITDAY_WARN ]
then
LEVEL="WARN"
fn_send_zabbix
else
LEVEL="OK"
fn_send_zabbix
fi
}
# chamo o for
for name in `echo $DOMS`
do
endip=$(host $name | grep has | grep -v "IPv6" | tail -n 1 | awk '{ print $NF }')
echo "exit" | nc -w 3 $endip 443 > /dev/null
if [ `echo $?` == 0 ]
then
fn_make_item
fn_check_cert
fi
done
###
rm -f /tmp/*-ZABBIX-CERT-*
Observações:
- cat /usr/local/bin/monits/lista-dominios.txt – um site/dominio por linha, exemplo:
- www.google.com
- www.microsoft.com
- vou documentar o código “update-zabbix-proxy.php”, pois ele não é nativo do Zabbix
- e como obter os “IDs” dos itens do Zabbix como Templates, Items, Grupos, etc
O update-zabbix-proxy.php
Bom, não se se todos sabem, mas a API do Zabbix no método de criação de um novo host (aqui vai ter outra explicação sobre algo que uso) não permite indicar qual será o proxy responsável pela monitoria: https://www.zabbix.com/documentation/current/manual/api/reference/host/create
No passado eu usava uma rotina via banco de dados para corrigir esta configuração, porém era bem ruim.
Com isso em mente, tempos atrás consegui um código com um amigo, “Nilton Souza” ( ele precisa autorizar colocar o e-mail dele aqui), que é responsável por receber a requisição para que logo após do uso o método de criação de um novo host a gente consiga alterar o proxy.
O código é em php, segue:
<?php
define('MYSQL_HOST', '127.0.0.1');
define('MYSQL_PORT', 3306);
define('MYSQL_USER', 'root');
define('MYSQL_PASS', '');
define('MYSQL_DB', 'zabbix');
if (!empty($_POST['proxy_hostid']) && !empty($_POST['host'])) {
$connStr = 'mysql:host=' . MYSQL_HOST . ';port=' . MYSQL_PORT . ';dbname=' . MYSQL_DB;
try {
$conn = new PDO($connStr, MYSQL_USER, MYSQL_PASS);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$update = "UPDATE hosts
SET proxy_hostid = '{$_POST['proxy_hostid']}'
WHERE host = '{$_POST['host']}'";
$conn->exec($update);
} catch (Exception $e) {
http_response_code(500);
echo "ERRO: {$e->getMessage()}\n";
}
}
Esse código deve ficar publicado no seu servidor web (preferencialmente no FE do Zabbix), nesse exemplo estamos usando um servidor Apache Httpd:
pwd
/etc/httpd/conf.d
cat zabbix-update.conf
Alias /zabbix-balancer "/var/www/html/zabbix-balancer"
<Directory /var/www/html/zabbix-balancer>
Options Indexes FollowSymLinks MultiViews ExecCGI
AllowOverride All
Order allow,deny
Allow from all
DirectoryIndex smokeping.fcgi
</Directory>
Dessa forma conseguimos usar via método POST, conforme nosso script anterior:
WS_UPDATE="http://zabbix.intranet/zabbix-balancer/ws/update-zabbix-proxy.php"
# Executando o update
curl -s --data "proxy_hostid=$PRX_ID&host=$name" -X POST $WS_UPDATE
Como obter os “IDs” dos itens do Zabbix como Templates, Items, Grupos, etc
Agora vou explicar a maneira mais fácil de obter os IDs que vamos usar nos nossos scripts.
Existem duas maneiras de fazer isso:
1a – via banco de dados, já usei, funciona, mas requer mais tempo
2a – via interface do Zabbix, bem simples
Vamos seguir com a segunda opção!!!
Vou considerar que você já tem o seu template pronto, se não faça um agora mesmo, lembre-se de adicionar um item do tipo trapper.

Faça uma busca pelo nome do seu template no Zabbix:

O seu template deverá ser mostrado na seleção conforme abaixo:

Clique no nome do template
Será apresentada a tela abaixo:

Repare na tela que eu coloquei o cursor do mouse sobre o nome do template e na barra de status do navegador foi exibida uma URI com o templateid, no nosso caso é o 35833.
Esse ID será usado no nosso script para que quando ocorrer a criação de um novo hosts, já ocorra a indicação de qual será o template utilizado.
Esse recurso, pode ser feito para grupos, itens, gráficos, ou seja, se é um objeto no Zabbix podemos consultar o seu ID de uma maneira rápida é fácil
Sobre “host”
Um pouco antes, eu indiquei que falaria sobre o host criado no Zabbix, eu particularmente gosto de falar que é um agregador ou agregação, pois um host pode ser um equipamento físico, um servidor virtual ou até mesmo um conjunto de identificação de sistemas e componentes, ou seja, não um equipamento ou um servidor.
É melhor eu dar um exemplo.
Digamos que você tem um sistema de entrada de dados, aqui vamos chamá-lo de “cadastro” e esse sistema tem componentes que são servidos em servidores físicos/virtuais, cloud, switchs, roteadores, fw e caso um destes recursos cause problema nos seus componentes o seu sistema “cadastro” poderá apresentar falhas.
Então podemos adicionar um novo hosts no Zabbix com o nome de “Cadastro”, fazer o relacionamento dele com um Template com itens o tipo trapper e passar a monitorar o “estado” do seu “Cadastro”, veja, não vamos relacionar o sistema em um outro servidor, isso será monitorado pelo Zabbix usando o Agent, mas sim, vamos ter um “status” dinâmico bastando coletar outras métricas e usar relacionamentos que indique a saúde do seu sistema.
Um exemplo que uso é a monitoria do Health da AWS, veja, no meu ambiente eu não tenho um servidor chamado AWS, mas a minha empresa depende dela, então nos criamos um programa que pega o status da página de status da AWS e envia o resultado para o Zabbix que trata dentro de uma trigger, basicamente fazendo isso no final:
/usr/bin/zabbix_sender -z zbxtrapper01.intranet -s AWS_HEALTH -k status -o 0
A minha trigger trata o codigo “0” – se for 0 é ok, se não é incidente.
No Zabbix eu criei um “host” (agregação) com o nome de AWS_HEALTH

E nesta agregação (viu, mudei aqui) eu tenho um template relacionado com um item do tipo trapper

Obs: vou publicar esse script.