[Watchers] Desafios (que você vai passar) ao implementar o Watcher da Elastic em Produção — Parte 01
(Jeito bonito de falar que da trabalho)
Fala pessoal! Como estão?
Nesse artigo vou apresentar pra vocês os desafios reais ao implementar o Watcher da Elastic em produção, o que a principio parece ser bem simples olhando a solução “por cima”, mas, na prática é algo bem “cabuloso”.
A ideia é que ao implementar os seus Watchers você não tenha que passar por tantos desafios e tretas e tenha um desenvolvimento mais tranquilo!
Nosso cronograma:
- O que é o Watcher e quais as possíbilidades de configuração/integração (Esse artigo);
- Vivendo a prática — Como funciona para implementar o Watcher para gerar alertas de um servidor — Parte 02;
- Vivendo a prática — Como otimizar o seu Watcher e torna-lo mais inteligente — Parte 03;
- Solução final — O que você deve pensar ao implementar Watchers em produção — Parte 04.
Watcher — É de comer?
Watcher é uma das soluções de alarmística fornecido pela empresa Elastic em sua suíte de produtos, sendo a única solução G.A (não beta com suporte garantido pela Elastic) de geração de alertas, tendo como único ponto de observação o fato de ser uma feature licenciada.
A ideia é simples, o Watcher serve para gerar um alarme com base em um evento. Um caso comum é, por exemplo, gerar um alerta de consumo de memória de um servidor caso o mesmo passe um determinado valor limite.
Em termos gerais, o Watcher (igual outras ferramentas) deveria observar um objeto (servidor) e calcular com base nos valores recebidos se ele ultrapassou um limite definido, e caso isso seja válido, gerar uma notificação (como por exemplo mandar um email). Lembre que eu disse deveria.
Para isso, a lógica do Watcher é dividida em 3 seções principais, sendo elas:
- Input — Aqui é a parte que você define os valores a serem analisados e o método de análise;
- Condition — Já aqui é onde dizemos se o valor x é maior que y, para que assim possamos gerar um alarme;
- Action — Para finalizar, com base do resultado da condition, é definido qual ação será gerada (email, webhook, registro em índice, slack).
E antes de continuarmos, vou deixar aqui as especificações dos laboratórios:
- Máquina virtual ou física tanto linux quanto windows
- Elasticsearch rodando local na porta 9200 sem segurança com licença trial habilitada.
- Kibana rodando local na porta 5601.
- Metricbeat rodando local coletando apenas métricas de Sistema Operacional.
- Indice que será utilizado: metricbeat-*
Observações
Não entrarei muito em detalhes em termos de ambientes e outros conceitos, mas, caso se interesse eu tenho um material completo com mais de 35 artigos e 26 vídeos todos gratuitos que te leva do iniciante ao começo do avançado que é o Guia Completo da Elastic Stack, da uma conferida por lá :D
Para habilitar a licença trial, no seu Kibana acesse:
Stack Management > License Management > Enable Trial Licence
Voltando ao assunto…
Tendo em mente como funciona a estrutura do Watcher, vamos iniciar a criação de um. No kibana, em Stack Management > Watchers, você verá que existem duas opções de criação de Watchers, “Create Threshold Alert” e “Create Advanced Watch”, vamos falar um pouco sobre cada uma delas:
“Create Threshold Alert”
Minha opinião sincera? Não me atendeu desde os primeiros 5 minutos em projetos mais complexos e exigiu que eu fosse pra segunda opção. (cômico porém trágico kkkk)
Brincadeiras a parte, vou apresentar o meu ponto:
Ele através do seu formulário torna muito simples a interação com o que precisamos analisar, como por exemplo:
“Quero monitorar MEMÓRIA de todos os meus 50 servidores do parque e gerar um alerta se passar de 90% .”
De maneira prática, sairia assim:
Minha conclusão sincera é a seguinte, atende? Sim. Atende bem? Talvez não, veja bem…
Primeiro ponto é que esse Watcher irá alarmar se qualquer um dos TOP 50 servidores alarmarem, sendo que pode ser 1 ou todos os 50, o que só seria efetivamente um problema se isso comprometesse o nosso Output que também funciona, mas dessa forma:
..."transform": { "script": { "source": "HashMap result = new HashMap(); ArrayList arr = ctx.payload.aggregations.bucketAgg.buckets; ArrayList filteredHits = new ArrayList(); for (int i = 0; i < arr.length; i++) { HashMap filteredHit = new HashMap(); filteredHit.key = arr[i].key; filteredHit.value = arr[i]['metricAgg'].value; if (filteredHit.value > params.threshold) { filteredHits.add(filteredHit); } } result.results = filteredHits; return result;", "params": { "threshold": 0.9 } } }, "actions": { "logging_1": { "logging": { "text": "O Watcher [{{ctx.metadata.name}}] estourou o threshold de memoria :(" } ...
Tem quem goste dessa solução, na minha visão é um exagero de lógica e em nível de sustentação e operação real dessa solução muitas vezes o time não terá o expertise de alterar esse código.
Segundo ponto, estamos agrupando em apenas um único nível sendo ele o campo “host.name”, ou seja, o nome do servidor. Agora vamos imaginar se estivéssemos olhando dois níveis, como por exemplo filesystem no linux e servidores onde temos n filesystems dentro de cada servidor…
Já de cara não seria possível porque via interface não é habilitado descer dois níveis (ou mais) de buckets aggregations.
Ou seja, o que pegou com a solução? Baixa customização em termos de output e exige alto nível de código para modifica-la, tornando difícil para os times que geralmente não tem skill técnico alto de código sustentar, além de não permitir mais de um nível de agregação de termos.
“Create Advanced Watch”
Se o meu argumento fez sentido pra você de que a interface visual não atende (para a maioria dos casos), vamos mergulhar fundo para entender de como funciona o “Advanced Watch”.
Como base, vamos utilizar o próprio payload que geramos pela interface visual, onde destacarei as 3 seções que mencionei acima:
- Aqui temos a seção input, que contém uma query para limitar o dataset para apenas os últimos 5min desde o acionamento do Watcher…
- E aqui dentro ainda do input temos a agregação que busca a média do consumo de memória de cada servidor (Agregação bucketAggs com uma sub-agregação metricAgg).
- Aqui já temos a clausula condition que em resumo faz um for buscando algum resultado que excede o threshold de 0.9.
- O transform precede a action para formatar os resultados contendo todos os servidores que alarmaram.
- A action em si é bem simples, é apenas um log contendo o nome do Watcher como variavel.
Essa é a estrutura avançada do Watcher, é praticamente o JSON que resume tudo que geramos via interface gráfica.
Ele normalmente vai conter a análise dos dados que muitas vezes exigirá o uso de agregações para cálculo de campos, além da query de filtro do dataset como um todo (imagina ficar rodando o Watcher em uma massa com bilhões de documento o tempo todo? — Já te antecipo que não é uma boa), teremos uma condição que pode ser simplificada de algumas maneiras, mas em resumo será um condicional logico (< > = !=), e por fim as ações que serão feitas.
Como foi mencionado anteriormente, dentro das actions temos as seguintes possibilidades:
Mas no nosso exemplo padrão utilizamos o Logging.
Reflexões
Agora o grande ponto é, como tornar esse Watcher mais eficiente e manipular melhor esse JSON?
Como escrever uma agregação que permita mais de um term-bucket para análise e na sequência como analisa-lo na condition?
Como criar uma regra de condition ou de geração de evento que não exija tanta complexidade de código?
Como não criar armadilhas de performance ao criar os Watchers?
E caso compartilhe das mesmas (ou outras) reflexões e curiosidades, te convido a acompanhar os próximos artigos dessa série que eu te garanto que será a mais completa da história.
Conto contigo nessa?
Conclusão
É isso! Espero que tenha conseguido transmitir a mensagem nesse primeiro artigo dessa série, onde quis de maneira prática e didática os fundamentos e aplicações — além de uma dose de realidade — sobre como funciona essa ferramenta poderosa da Elastic para geração de alertas.
Te vejo nos próximos artigos.
Escrito por:
Felipe Queiroz - Tech Lipe com a coprodução de Vitor Costa de Sousa para o portal Techlipe.