Monitorando um cluster Swarm com a stack TICKS

Monitoramento free, open source e fácil de usar.

Murillo Peteffi
CWI Software

--

Um sistema em produção demanda atenção constante. É necessário ter consciência do que acontece com nossas aplicações o tempo todo e, o quanto antes identificamos algo fora do esperado, maiores as chances de corrigirmos sem que isso se torne um problema de verdade.

Embora seja praticamente consensual o que foi dito acima, há ainda muitos sistemas e servidores que não contam com uma estrutura mínima de monitoramento e de alertas em tempo real. Isso se deve, algumas vezes, à uma crença falha de que isso é caro ou complexo de implementar.

O objetivo deste artigo é apresentar uma das soluções para este problema. Através do uso da stack TICKS, implementaremos uma estrutura completa de visualização e processamento de métricas. Entenderemos o que ela é e veremos como funciona, desde a extração dos dados até o uso destes no monitoramento proativo, através de alertas. E tudo isso com ferramentas gratuitas e open source.

1. TICK+S

A denominação TICKS vem da junção das iniciais dos componentes da stack TICK, da InfluxData e do Slack, aplicativo escolhido para auxiliar na última etapa do processo. É importante entender o papel de cada um deles antes de prosseguir.

Telegraf: É o agente responsável pela coleta e exportação dos dados. Atua em todas as máquinas que compõem o cluster do Swarm e pode extrair informações referentes ao host em que está e aos outros serviços que estão rodando nele.
InfluxDB: É um banco de dados de séries temporais escalável e de alta performance. No contexto da stack, atua como centralizador de todas as informações. Recebe e armazena o que é extraído pelo Telegraf e fornece dados para serem consumidos pelos gráficos e pelo motor de alertas.
Chronograf: É a interface gráfica da stack TICK. Através dele é feito o acompanhamento das métricas do sistema, por meio de dashboards e gráficos. Além disso, é a porta de acesso às configurações do Kapacitor.
Kapacitor: É o motor de processamento de métricas e alertas. Atua com a responsabilidade de analisar dados temporais do InfluxDB e enviar os avisos em tempo real para os destinos configurados.
Slack: É um dos mais famosos aplicativos de mensagens em tempo real para times de trabalho. Nesse contexto, o utilizamos para receber os alertas do Kapacitor.

2. Stack Setup

Nesta sessão demonstraremos uma estrutura para configuração da stack TICKS, tanto em termos de definição da arquitetura quanto de configurações dos componentes e uso dos mesmos.

Daqui em diante, consideraremos um contexto onde já existe um cluster Swarm em operação e um workspace funcional do Slack. No entanto, o não cumprimento desses pré-requisitos não é impeditivo para o entendimento do que vem a seguir.

2.1. Arquitetura

Há diversas maneiras possíveis para elaborarmos uma arquitetura de comunicação entre os componentes de monitoramento e os serviços ou hosts a serem monitorados. Dentre elas, existe uma na qual toda stack é literalmente parte do Swarm e compartilha, portanto, dos mesmos servidores e recursos que suas aplicações em produção. Enquanto, por um lado, há o ganho de não haver necessidade de uma máquina específica para monitoramento, por outro há a falha de estarmos onerando os servidores com serviços que não são parte funcional do seu produto.

Em outra abordagem, há um cenário no qual apenas o Telegraf faz parte do cluster de serviços. De lá, ele extrai todas as informações necessárias e envia para o restante da stack, que está em outro servidor. Nesse cenário, elimina-se a preocupação de que haja impacto na performance do produto, pois tudo é armazenado e processado em outro host.

Evitando entrar no mérito de comparações detalhadas dos pontos positivos e negativos de ambas abordagens, trataremos aqui da segunda alternativa. É importante ressaltar que, uma vez que estamos lidando com containers Docker, não há diferença relevante de complexidade entre elas e não será trabalhoso adaptar o que será visto para outra arquitetura, se assim for desejado.

A imagem abaixo demonstra a estrutura que consideraremos para o que vem a seguir:

Fluxo de dados entre os componentes da stack TICKS.

2.2. Telegraf

Embora bastasse realizar um deploy da imagem padrão como um novo serviço global no nosso cluster Swarm para que o Telegraf já começasse a funcionar, criaremos uma imagem personalizada nesta etapa do processo, com o objetivo de definir exatamente quais métricas queremos extrair e de que forma e para onde queremos enviá-las.

O seguinte arquivo será a base para isso:

O “Dockerfile” apresentado é o responsável por assegurar de que maneira uma imagem nova é criada. Observa-se a partir dele, portanto, que alteraremos a imagem padrão em dois pontos:

  • Substituiremos o arquivo de configuração “telegraf.conf” original por um criado por nós;
  • Definiremos que todos os containers Docker gerados a partir dessa nova imagem terão um volume no diretório “/var/run/docker.sock” .

O acesso ao arquivo “docker.sock” do host é necessário para que o container do Telegraf tenha acesso aos dados dos outros serviços que estarão rodando na mesma máquina. Já o arquivo “telegraf.conf” é o responsável por carregar nossas definições de como o trabalho de extração e envio das métricas deverá ser feito. Vejamos um exemplo sugerido antes de entrar em detalhes:

Observando com um pouco de atenção, é possível perceber que há dois tipos de configurações sendo definidas. As do tipo “input” são as responsáveis pelo comportamento de extração e tratamento das métricas, como a definição de um “name_suffix”, por exemplo, que trata de concatenar um texto informado ao nome original dos campos coletados.

Já as do tipo “output” definem como essas informações serão enviadas ao InfluxDB, que nesse contexto estará respondendo em “http://host-c:8086. Estipula-se também que as informações referentes aos containers Docker serão armazenadas em um database de nome “docker_metrics” e as demais, que referem-se a métricas do host, como uso de CPU e memória, irão para um database de nome “vm_metrics”.

Além das utilizadas neste arquivo de configuração, há diversas outras possibilidades de personalização do Telegraf. Uma explicação mais detalhada sobre cada uma delas pode ser encontrada nesta documentação.

Em posse dos arquivos “Dockerfile” e o “telegraf.conf” devidamente prontos, partiremos para a criação da imagem. Isso será através do seguinte comando:

docker build --tag minha-imagem-telegraf:1.0 .

Num cenário onde os arquivos se encontram no mesmo diretório a partir do qual executamos o comando e o Docker da máquina em questão funciona como deveria, a imagem nova é criada com sucesso. Com isso, estamos prontos para iniciar o deploy do Telegraf no Swarm.

O deploy de um novo serviço é sustentado por um arquivo de definições de comportamento do mesmo. Há liberdade para preencher com o que fizer sentido para cada negócio, como update_config, restart_policy e logging, mas é imprescindível que seja feita a definição da imagem criada anteriormente na tag “image” e que o “deploy mode” seja setado como global”. Essa última é necessária para que o serviço seja replicado em todas as máquinas que compõem o cluster, tornando possível a extração de métricas de todas elas. Usaremos o seguinte arquivo, “docker-compose.yml”, para centralizar a configuração desse novo serviço:

Com tudo isso pronto, faremos o deploy através do seguinte comando:

docker stack deploy \
--compose-file ./docker-compose.yml \
--with-registry-auth \
tick

Lembrete: é necessário que a imagem que criamos anteriormente esteja em um repositório acessível por todas as máquinas do cluster!

2.3. Host de Monitoramento

Tendo o Telegraf devidamente configurado, coletando e enviando métricas das nossas aplicações e servidores, configuraremos o armazenamento e o uso dessas informações. Lembrando que, conforme explicado anteriormente, os demais componentes da stack TICK estão em uma máquina própria (Host C), portanto as próximas alterações já não afetam os serviços do Swarm.

Nesse host, não utilizaremos Swarm: rodaremos containers Docker a partir das imagens originais dos componentes (InfluxDB, Chronograf e Kapacitor), por meio do docker-compose. As personalizações necessárias serão feitas por meio de volumes. Eis o arquivo de definição da stack:

Há três pontos importantes neste arquivo “docker-compose.yml”:

  • Criaremos uma rede “tick_net” e a referenciaremos nos serviços, para que eles sejam acessíveis entre si;
  • Exporemos as portas referentes à cada um dos serviços, pra que eles também sejam acessíveis por requisições externas;
  • Criaremos volumes para os diretórios “/var/lib/nome_do_serviço”, para que não haja perda de dados quando for necessário reiniciar os containers e para os arquivos de configuração.

O Kapacitor é o único dos três serviços que precisaremos configurar através de um arquivo “kapacitor.conf”. O exemplo sugerido abaixo traz algumas configurações default, que podem ser alteradas se quisermos. O único preenchimento obrigatório é a definição da url de webhook do Slack.

Para saber mais sobre webhooks do Slack, acesse este link.

Com isso pronto, iniciaremos os serviços a partir do seguinte comando:

docker-compose up -d

Após os serviços iniciarem corretamente, será possível acessar o Chronograf através da url “http://host-c:8888”. Uma tela como esta será exibida:

E será necessário criarmos a conexão com o InfluxDB:

Pronto. Toda stack TICK está configurada e funcional.

3. Dashboards

Os dashboards do Chronograf são a porta de entrada para visualizarmos as métricas que foram coletadas e agora estão armazenadas no nosso banco de dados. São várias abordagens possíveis e a criatividade é livre para montar uma coleção de gráficos que faça sentido pra cada sistema.

Criaremos um novo clicando na aba “Dashboards” e na opção “Create Dashboard”. A visão inicial é a demonstrada abaixo:

Alguns pontos importantes sobre a estrutura deste dashboard:

  • Na aba superior ficam as configurações de visualização que afetam a todos os gráficos componentes;
  • É possível escolher a frequência de atualização dos dados exibidos. O default é 10s;
  • É possível definir variáveis que podem ser utilizadas nas queries dos gráficos. Há algumas que são padrão, como a “interval”, que usaremos para criar gráficos de variação de métricas no tempo. Esse intervalo pode ser absoluto ou relativo;
  • Um dashboard é composto de gráficos. As possibilidades são muitas, podemos criar gráficos que exibem as métricas atuais, a variação delas ou ainda mistos. E é possível exibir gráficos de diferentes tipos, lado a lado.

Criaremos então nosso primeiro gráfico, através da opção “Add Data”:

Nesta tela temos duas abas: “queries” e “visualization”. A primeira é responsável pela definição do que será exibido, enquanto na segunda escolheremos como isso acontecerá . As queries podem ser montadas através de um query builder oferecido pela ferramenta ou escritas manualmente com uso de InfluxQL. Uma pré-visualização é exibida enquanto escrevemos as consultas.

Para exibir o uso de CPU nos nossos hosts, por exemplo, usaremos a seguinte query:

SELECT mean("usage_user") AS "mean_usage_user"
FROM "vm_metrics"."autogen"."cpu_vm"
WHERE time > :dashboardTime:
GROUP BY time(:interval:), "host"

Há três pontos que merecem destaque na estrutura desta consulta, para facilitar o seu entendimento:

  • O conjunto de dados do qual buscaremos as métricas é o “cpu_vm”, que é criado a partir do “inputs.cpu” e o “name_suffix = _vm”, que foram definidos anteriormente no arquivo de configuração do Telegraf;
  • O database que estamos consultando é o “vm_metrics”, que foi criado a partir da configuração de output do Telegraf;
  • Duas variáveis globais estão sendo usadas na query, “dashboardTime” e “interval”, para que nosso gráfico resultante não seja estático e responda às alterações de parâmetros do dashboard.

O resultado até aqui é este:

Duas observações sobre o gráfico resultante:

  • Essas duas linhas visíveis no gráfico correspondem aos dois hosts que fazem parte do cluster do Swarm;
  • As escalas foram definidas automaticamente, embora possam ser fixas se quisermos.

Já cumprimos a parte nova da exibição de dados, mas todos sabem que um dashboard com um só gráfico não tem graça nenhuma. Criaremos então um próximo, bastante semelhante ao anterior, com informações de uso de memória, para exercitar o que vimos. Usaremos a seguinte query:

SELECT mean("used") AS "mean_used"
FROM "vm_metrics"."autogen"."mem_vm"
WHERE time > :dashboardTime:
GROUP BY time(:interval:), "host"

E o resultado já é este:

A partir daqui, basta usar a criatividade e definir quais informações fazem sentido serem exibidas em cada dashboard. Criaremos mais uma exibição pra terminar. Dessa vez com métricas de uso de CPU de nossos containers docker dentro do Swarm. Seguindo a mesma lógica usada até aqui, a query é esta:

SELECT mean("usage_percent") AS "usage_percent"
FROM "docker_metrics"."autogen"."docker_container_cpu_docker"
WHERE time > :dashboardTime:
GROUP BY time(:interval:), "com.docker.stack.namespace"

4. Alertas

Agora que sabemos obter, salvar e visualizar as métricas do nosso cluster, podemos nos concentrar em fazer a ferramenta trabalhar a nosso favor. O Kapacitor é o responsável pelo monitoramento proativo e trabalha para que não seja necessário que passemos a vida toda de olho nos dashboards.

Na aba “Configuration”, na qual já temos nossa conexão com InfluxDB configurada, adicionaremos uma nova conexão com o Kapacitor através do botão “Add Kapacitor Connection”.

Tela de configuração com opção de adição de nova conexão com Kapacitor.

Em seguida, basta apontarmos para o banco de dados que está rodando no nosso Host C e escolher um nome para esta configuração, conforme imagem abaixo.

Bem como na etapa em que configuramos a conexão com o InfluxDB, estamos ignorando as configurações de autenticação. Por estarmos em um host próprio para os componentes da stack, isso tende a ser menos importante para o tutorial. Contudo, se necessário, será possível gerenciar usuários e permissões futuramente.

Para conferir se tudo correu como desejado até aqui, acessamos os detalhes da nossa conexão através da opção de edição mostrada na imagem abaixo:

Como criamos nosso “kapacitor.conf” anteriormente já com as informações do Slack, o esperado é que essa conexão já tenha todas as definições necessárias para essa comunicação. É possível alterar algo que consideremos fora do esperado nesta tela de edição:

Com isso, a conexão com o serviço de comunicação está pronta. O botão “Send Test Alert” deve estar funcionando e usaremos ele para garantir que fizemos tudo certo.

Agora já é possível criar uma primeira regra de alerta. Faremos isso acessando o menu “Alerting” e iniciando a criação através do botão “Build Alert Rule”, conforme esta imagem:

A tela de configuração da regra do alerta é extensa. Prosseguiremos então por partes. Na primeira etapa configuraremos o nome e o tipo do alerta, além de qual métrica deverá ser controlada:

Essa etapa é bastante semelhante à construção de um gráfico para o dashboard. Através do query builder são escolhidos o database, a informação e o campo que iremos monitorar. Neste caso, escolheremos o uso percentual de memória de ambos os hosts que compõe o cluster.

Logo abaixo, na segunda etapa, decidiremos as condições que devem gerar o alerta:

Definimos que nosso alerta será gerado quando o uso percentual de algum dos hosts for maior que 80%. Através de um gráfico é possível visualizar as métricas atuais e entender, por exemplo, se o alerta teria sido disparado num intervalo de tempo definido.

Por último, definiremos as características do alerta propriamente dito:

O canal do Slack, embora já esteja definido e venha preenchido por padrão, pode ser alterado. Um nome de usuário e um emoji, que servirá de avatar para o mesmo, também podem ser informados nessa etapa. Já a mensagem pode ser fixa ou dinâmica. Através do uso de templates, podemos usar variáveis para alertar com informações reais. Por exemplo, nesse caso escolhemos o nome do host e a quantidade atual de uso de memória para que sejam concatenados na mensagem.

Tudo pronto! A regra está pronta e pode ser vista na tela de alertas. Toda vez que a métrica que estamos monitorando se encaixar na condição definida, receberemos um alerta conforme a configuração. Seremos alertados também quando ela deixar de atender à condição, para que saibamos que está normalizado novamente.

Alertas de uso de memória do host-a no Slack.

A partir de agora, assim como foi dito sobre os gráficos dos dashboards, fica a cargo da criatividade de cada um escolher os alertas que fazem mais sentido para cada negócio.

5. Outras possibilidades

Se você olhou com atenção para a imagem de capa do artigo, talvez esteja se perguntando de onde vêm os dados referentes às requests e responses do sistema. O dashboard em questão é de um caso real de uso do monitoramento com a stack e exemplifica mais essa possibilidade: não é necessário, tanto para o Chronograf quanto para o Kapacitor, que os dados tenham sido obtidos pelo Telegraf. É possível enviar informação de diversos agentes ao InfluxDB e acessá-las em um mesmo dashboard. No caso da imagem da capa, o Traefik usado como loadbalancer para os serviços que compõe o Swarm é o responsável por enviar as informações referentes às chamadas.

Também não é necessário que as notificações sejam enviadas para o Slack. O Kapacitor é versátil e pode ser integrado com diversas ferramentas, inclusive APIs próprias suas que recebam chamadas REST. Mais informações sobre as possibilidades podem ser encontradas nesta documentação.

Conclusão

Não há pretensão, com esse artigo, de resolver todos os problemas de monitoramento do seu sistema. Apenas de mostrar que é possível ter uma boa estrutura sem necessidade de conhecimentos específicos complexos ou muito tempo investido na configuração. Ainda, e talvez a melhor parte, usando apenas ferramentas free e open source.

E, ao final de tudo isso, se por algum motivo você considerar não precisar desse tipo detalhado de monitoramento e dos alertas em tempo real, ao menos você tem uma tela bonita pra exibir nas reuniões. 🙂

--

--