terça-feira, 4 de novembro de 2014

LLD no Zabbix com Shell Script - Entendendo e utilizando esse recurso

Introdução

O recurso de LLD (Low Level Discovery) tem ganhado cada vez mais importância, uma vez que teoricamente é possível monitorar qualquer coisa utilizando esse recurso, apesar da documentação oficial, de artigos nacionais e internacionais, mensagens no fórum oficial, etc. O recurso continua desconhecido por muitos, eu queria compilar um pouco de tudo que encontrei, e da minha própria experiência e criar um artigo onde as pessoas entendessem a lógica do LLD e pudessem se basear para criar seus próprios LLDs.

Termos Técnicos

Antes de entrarmos na solução propriamente dita, precisamos entender alguns termos e soluções envolvidas nesse recurso.

LLD - Low Level Discovery: Função do Zabbix responsável por detectar determinadas características de um objeto, de forma dinâmica. Por exemplo, o Zabbix vai achar sozinho (dinamicamente) todas as partições da sua máquina (o objeto são as partições), e coletar dados como tamanho da partição, espaço livre, espaço utilizado (essas são as características do objeto).

JSON - JavaScript Object Notation: É uma formatação para intercâmbio de dados computacionais, que para seres humanos é fácil de ler e escrever e, para as máquinas é fácil de interpretar e gerar. Se você entende como um XML funciona, entende como um JSON funciona ;-)

PARSER: Em Português conhecemos como Análise Sintática, mas a maioria das pessoas usa o termo em inglês, de maneira simples, significa ler uma entrada de dados, nesse caso um arquivo JSON, e interpretar a sua estrutura gramatical. O software jq, no nosso caso, vai receber um arquivo texto com marcações específicas que ele sabe interpretar e extrair os dados.

Como funciona o LLD no Zabbix

O LLD no Zabbix de maneira muito resumida funciona da seguinte forma:
Você gera um arquivo no formato JSON com a entrada de dados utilizando o padrão de macros do Zabbix "{#VAR}", essas macros serão os objetos, por exemplo, a lista de placas de rede, a lista de partições, a lista de base de dados, a lista de tabelas de uma base de dados, a lista de antenas sem fio, etc. Isso é a Regra de Descoberta.
Em seguida você tem que dizer ao Zabbix o que coletar de cada um desses objetos da lista, isso é o Protótipo de itens. Por exemplo, para cada partição do sistema colete o tamanho da partição, o espaço livre e o espaço utilizado. Com esses itens gerados, podemos criar outros protótipos como Triggers e Gráficos.
Isso pode ser feito utilizando as Chaves suportadas pelo Zabbix, OIDs SNMP ou Scripts Personalizados.

Pré-requisitos

O único pré-requisito no Servidor Zabbix é a instalação do jq, que é um parser de JSON. No CentOS:
# yum -y install jq

Objetivo

Eu procurei criar a solução da maneira mais simples possível, para isso eu usei apenas Shell Script, nada de Perl, Python, Ruby, Awk, Expressões Regulares, apesar de tudo isso ser muito importante, eu queria que um administrador de redes iniciante tivesse condições de entender a solução, queria que pessoas que possuem ambientes críticos pudessem utilizar a solução tendo que realizar o mínimo possível de alterações no ambiente, apenas instalar o jq.

Arquivos envolvidos na solução

lld_passwd.sh: Script responsável por coletar os dados, neste exemplo, esses dados serão coletados do /etc/passwd, gerar o arquivo JSON com as macros que o Zabbix precisa e gerar um arquivo JSON comum de onde extrairemos os dados com o jq.
/tmp/lld_passwd.txt: Arquivo no formato JSON com as macros que o Zabbix necessita para interpretá-lo.
/tmp/lld_passwd_2.txt: Arquivo no formato JSON de onde extrairemos os dados para alimentar o Zabbix.

Estrutura da solução

O script coleta os dados do arquivo /etc/passwd e gera um aquivo JSON com as entradas "{#USER}", "{#NOME}", "{#HOME}" e "{#SHELL}" para cada um dos registros encontrados. No nosso exemplo, para o Zabbix só interessa a entrada "{#USER}", pois em cima da lista de usuários, solicitaremos os outros dados, o Nome do usuário "{#USER}", o Home do usuário "{#USER}", o Shell do usuário "{#USER}".

Você deve estar se perguntando: Se para o Zabbix só interessa a entrada "{#USER}" por que eu criei as outras entradas, certo? E também porque eu gerei o arquivo lld_passwd_2.txt se os dados já estão no /etc/passwd? Calma jovem gafanhoto...

O objetivo do artigo é ensinar a criar uma solução para qualquer tipo de dados, certo? Imagine que para coletar os dados que você precisa seja necessário executar um comando qualquer, nesse caso você precisaria executar o comando uma vez para montar o JSON, e depois executar o mesmo comando (ou outro) para coletar cada um dos dados referentes aos objetos do JSON, isso vai onerar o Servidor Zabbix e também o equipamento de onde os dados estão sendo coletados. Na solução aqui proposta nós vamos coletar todos os dados de uma única vez (podem ser necessários vários comandos para gerar o arquivo inteiro), e depois coletar os dados referentes aos objetos de um arquivo texto que está no próprio Servidor Zabbix, o que é muito menos custoso.

Variáveis do Script

O script foi projetado para receber as variáveis via passagem de parâmetros, porque o Zabbix vai passar esses parâmetros para ele.

Alguns detalhes devem ser observados nas variáveis do script:
Não podemos acrescentar " (aspas) ao arquivo JSON, a não ser as que ele espera encontrar e onde ele espera encontrar, então na variável $NOME, utilizei o comando tr -d \"`, para remover qualquer " (aspas) do arquivo /etc/passwd. Elas existem no user saslauth, como pode ser conferido abaixo:

# cat /etc/passwd | grep saslauth
saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin


Outro detalhe importante é referente às "/", elas precisam ser escapadas assim "\/", para isso usei o sed (eu sei que falei que não ia usar Expressões Regulares, mas é só um sed de nada..) nas variáveis $HOME e $SHELL.

A variável $LINHAS é utilizada para sabermos o número de entradas que serão geradas no arquivo JSON, isso porque todas as entradas acabam com uma ",", com exceção da última entrada. Por esse mesmo motivo o "for" foi configurado para ser executado até o "i<$LINHAS" e não "i<=$LINHAS".

Opções do Script

O script possui 4 opções, mas você pode adaptá-lo para ter quantas opções forem necessárias ao seu cenário. São elas:
discovery: Gera o arquivo lld_passwd.txt que será utilizado pela regra de descoberta do Zabbix.
Você pode (e deve) validar seus arquivos JSON no JSONLint.

user: Dado determinado usuário retorna o seu usuário, sim ela é inútil, foi apenas uma piadinha nerd para relaxar, qual será o user do user root?

nome: Dado determinado usuário retorna o nome do usuário.

home: Dado determinado usuário retorna o diretório home do usuário.

shell: Dado determinado usuário retorna o shell do usuário.

Arquivo lld_passwd_2.txt

Depois de montar o arquivo lld_passwd.txt, eu utilizo o sed para trocar todas as ocorrências de macros para itens normais de um arquivo JSON:
{#USER} -> user, {#NOME} -> nome, {#HOME} -> home e {#SHELL} -> shell.
E armazeno tudo nesse arquivo, quando eu realizo as operações user, nome, home e shell, o comando jq é invocado, entende o conteúdo do arquivo JSON e faz a extração dos dados que nos interessa.

Configuração no Zabbix Server

O script deve estar no seu diretório "ExternalScripts", se você estiver na dúvida, veja no arquivo /usr/local/etc/zabbix_server.conf  a localização do mesmo. Ele também deve possuir permissão para ser executado pelo usuário zabbix, que também deve ser capaz de criar os arquivos no /tmp.

Configuração na Interface Gráfica do Zabbix Server

 Crie um novo template com o nome LLD Passwd, depois na linha do nome do template clique em Autobusca // Criar regra de descoberta, preencha os dados da regra.
Regra de Descoberta

Na linha da regra clique em Protótipos de itens // Criar protótipo de item, preencha os dados dos protótipos.

Protótipo de Item Home

Protótipo de Item Nome

Protótipo de Item Shell

Protótipo de Item Usuário
 Clone o seu host Zabbix server com o nome de Zabbix server LLD.
Zabbix server LLD
 Vincule o template LLD Passwd no host.
Template LLD Passwd
Espere 5 minutos e acesse Configuração // Hosts, observe os itens criados automaticamente. Na figura abaixo eu usei um filtro para mostrar apenas os itens do usuário root.
Itens criados dinamicamente pelo LLD
Acesse Monitoramento // Dados recentes e visualize a leitura dos dados, neste exemplo eu filtrei apenas os itens do root.

Dados recentes

 

Conclusão

Com as explicações acima e os código disponíveis acredito que você seja capaz de entender o funcionamento do LLD no Zabbix, gerar seus próprios scripts e tirar o máximo proveito desse recurso fantástico.


Anexos

lld_passwd.sh
Template LLD_Passwd

 

Agradecimentos

Queria deixar aqui meus agradecimentos ao Ronei Xavier da Silva e Ederson Frasnelli Ribeiro que me deram uma força para entender o funcionamento do JSON!

Referências

Zabbix Manual
json.org
JSON Wikipedia
Análise Sintática Wikipedia
jsonlint.com
XModulo
JQ Manual
JQ FAQ